diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml index 1d6df1893..7083a7cee 100644 --- a/.github/workflows/benchmark.yaml +++ b/.github/workflows/benchmark.yaml @@ -29,7 +29,7 @@ jobs: ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: # We need to get all the git tags to make version injection work. See VERSION in Makefile for more detail. fetch-depth: 0 diff --git a/.github/workflows/build-and-test-msi.yaml b/.github/workflows/build-and-test-msi.yaml index 63142aef7..53fd2a97d 100644 --- a/.github/workflows/build-and-test-msi.yaml +++ b/.github/workflows/build-and-test-msi.yaml @@ -67,7 +67,7 @@ jobs: run: | python -m pip install --upgrade pip pip install awscli - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ needs.get-tag-name.outputs.tag }} fetch-depth: 0 @@ -179,7 +179,7 @@ jobs: run: | python -m pip install --upgrade pip pip install awscli - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ needs.get-tag-name.outputs.tag }} fetch-depth: 0 diff --git a/.github/workflows/build-and-test-pkg.yaml b/.github/workflows/build-and-test-pkg.yaml index 1e5fe3f4c..258b76b4d 100644 --- a/.github/workflows/build-and-test-pkg.yaml +++ b/.github/workflows/build-and-test-pkg.yaml @@ -3,6 +3,10 @@ name: Build, test and upload .pkg to S3 # The scheduler runs at 9 am UTC every day. on: workflow_dispatch: + inputs: + ref_name: + required: true + type: string workflow_call: inputs: ref_name: diff --git a/.github/workflows/build-pkg.yaml b/.github/workflows/build-pkg.yaml index 5098bce08..4d1f52b4a 100644 --- a/.github/workflows/build-pkg.yaml +++ b/.github/workflows/build-pkg.yaml @@ -37,7 +37,7 @@ jobs: ] timeout-minutes: 60 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ inputs.tag }} fetch-depth: 0 diff --git a/.github/workflows/ci-docs.yaml b/.github/workflows/ci-docs.yaml index 66afb4f20..b5ba265dc 100644 --- a/.github/workflows/ci-docs.yaml +++ b/.github/workflows/ci-docs.yaml @@ -45,7 +45,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Pull latest awslabs/git-secrets repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: repository: awslabs/git-secrets ref: 1.3.0 @@ -54,7 +54,7 @@ jobs: - name: Install git secrets from source run: sudo make install working-directory: git-secrets - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Scan repository for git secrets run: | git secrets --register-aws @@ -113,7 +113,7 @@ jobs: mdlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - uses: avto-dev/markdown-lint@04d43ee9191307b50935a753da3b775ab695eceb # v1.5.0 with: args: '**/*.md' diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e78e07020..3a10a2a2e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Pull latest awslabs/git-secrets repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: repository: awslabs/git-secrets ref: 1.3.0 @@ -58,7 +58,7 @@ jobs: - name: Install git secrets from source run: sudo make install working-directory: git-secrets - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Scan repository for git secrets run: | git secrets --register-aws @@ -70,7 +70,7 @@ jobs: os: [macos-latest, windows-latest, ubuntu-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version-file: go.mod @@ -88,7 +88,7 @@ jobs: run: | git config --global core.autocrlf false git config --global core.eol lf - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: # Since this repository is not meant to be used as a library, @@ -101,7 +101,7 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version-file: go.mod @@ -110,7 +110,7 @@ jobs: run: | echo "GOOS=windows" >> $GITHUB_ENV - name: golangci-lint - windows - uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 + uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 with: # Pin the version in case all the builds start to fail at the same time. # There may not be an automatic way (e.g., dependabot) to update a specific parameter of a GitHub Action, @@ -121,7 +121,7 @@ jobs: run: | echo "GOOS=darwin" >> $GITHUB_ENV - name: golangci-lint - darwin - uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 + uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 with: # Pin the version in case all the builds start to fail at the same time. # There may not be an automatic way (e.g., dependabot) to update a specific parameter of a GitHub Action, @@ -132,7 +132,7 @@ jobs: name: ShellCheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - name: Run ShellCheck uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0 with: @@ -141,7 +141,7 @@ jobs: go-mod-tidy-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version-file: go.mod @@ -152,7 +152,7 @@ jobs: check-licenses: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: go-version-file: go.mod @@ -205,7 +205,7 @@ jobs: mdlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 - uses: avto-dev/markdown-lint@04d43ee9191307b50935a753da3b775ab695eceb # v1.5.0 with: args: '**/*.md' diff --git a/.github/workflows/e2e-linux.yaml b/.github/workflows/e2e-linux.yaml index 024c9b92d..572709356 100644 --- a/.github/workflows/e2e-linux.yaml +++ b/.github/workflows/e2e-linux.yaml @@ -33,7 +33,7 @@ jobs: "${{ inputs.runner-type }}", ] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 # checkout uses node version 20, which doesn't run on AL2 if: ${{ ! (startsWith(inputs.os, 'amazon') && inputs.version == '2' ) }} with: diff --git a/.github/workflows/e2e-macos.yaml b/.github/workflows/e2e-macos.yaml index 3da588613..d131bc401 100644 --- a/.github/workflows/e2e-macos.yaml +++ b/.github/workflows/e2e-macos.yaml @@ -33,7 +33,7 @@ jobs: "${{ inputs.runner-type }}", ] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: # We need to get all the git tags to make version injection work. See VERSION in Makefile for more detail. fetch-depth: 0 diff --git a/.github/workflows/e2e-windows.yaml b/.github/workflows/e2e-windows.yaml index cf47666de..3e3c777c8 100644 --- a/.github/workflows/e2e-windows.yaml +++ b/.github/workflows/e2e-windows.yaml @@ -38,7 +38,7 @@ jobs: run: | takeown /F C:\actions-runner\_work\finch /R Remove-Item C:\actions-runner\_work\finch\finch -Recurse -Force -ErrorAction Ignore - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: # We need to get all the git tags to make version injection work. See VERSION in Makefile for more detail. fetch-depth: 0 diff --git a/.github/workflows/release-automation.yaml b/.github/workflows/release-automation.yaml index 35c48713f..9ac819c5d 100644 --- a/.github/workflows/release-automation.yaml +++ b/.github/workflows/release-automation.yaml @@ -10,7 +10,7 @@ jobs: outputs: tag: ${{ steps.latest-tag.outputs.tag }} steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 - name: 'Get the latest tag' diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml index bdf566ab0..967050073 100644 --- a/.github/workflows/release-please.yaml +++ b/.github/workflows/release-please.yaml @@ -12,6 +12,8 @@ jobs: steps: - uses: googleapis/release-please-action@7987652d64b4581673a76e33ad5e98e3dd56832f # v4.1.3 id: release + with: + target-branch: ${{ github.head_ref || github.ref_name }} trigger-release-automation: name: Trigger release-automation.yaml if PR is merged needs: [release-please] diff --git a/.github/workflows/sync-submodules-and-deps.yaml b/.github/workflows/sync-submodules-and-deps.yaml index 5e90ea7bf..c1704cc58 100644 --- a/.github/workflows/sync-submodules-and-deps.yaml +++ b/.github/workflows/sync-submodules-and-deps.yaml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: submodules: recursive token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-pkg.yaml b/.github/workflows/test-pkg.yaml index 6534a2428..184a6b1d0 100644 --- a/.github/workflows/test-pkg.yaml +++ b/.github/workflows/test-pkg.yaml @@ -40,7 +40,7 @@ jobs: ACCESS_TOKEN: ${{ secrets.FINCH_BOT_TOKEN }} steps: - name: Checkout the tag - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: ref: ${{ inputs.tag }} fetch-depth: 0 diff --git a/.github/workflows/upload-build-to-S3.yaml b/.github/workflows/upload-build-to-S3.yaml index b3385ba8c..16f546351 100644 --- a/.github/workflows/upload-build-to-S3.yaml +++ b/.github/workflows/upload-build-to-S3.yaml @@ -16,7 +16,7 @@ jobs: runs-on: [self-hosted, macos, arm64, 14, release] timeout-minutes: 60 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 persist-credentials: false @@ -35,7 +35,7 @@ jobs: shell: zsh {0} - name: Upload macos aarch64 build - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1 with: name: finch.macos-aarch64 path: finch.*.aarch64.tar.gz @@ -45,7 +45,7 @@ jobs: runs-on: [self-hosted, macos, amd64, 14, release] timeout-minutes: 60 steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 persist-credentials: false @@ -64,7 +64,7 @@ jobs: shell: zsh {0} - name: Upload macos x86_64 build - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1 with: name: finch.macos-x86_64 path: finch.*.x86_64.tar.gz @@ -77,7 +77,7 @@ jobs: - macos-x86_64-build - macos-aarch64-build steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 with: fetch-depth: 0 persist-credentials: false diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6a787c5c9..73d3293b9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.3.0" + ".": "1.4.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc92eb42..27fb3f8c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Changelog +## [1.4.0](https://github.com/runfinch/finch/compare/v1.3.1...v1.4.0) (2024-10-08) + + +### Build System or External Dependencies + +* **deps:** Bump github.com/aws/aws-sdk-go-v2 from 1.31.0 to 1.32.1 ([#1134](https://github.com/runfinch/finch/issues/1134)) ([a55450f](https://github.com/runfinch/finch/commit/a55450f70c96e79ec695ceb234189735b99be896)) +* **deps:** Bump golang.org/x/tools from 0.25.0 to 0.26.0 ([#1130](https://github.com/runfinch/finch/issues/1130)) ([633c1bf](https://github.com/runfinch/finch/commit/633c1bfbdd8db4434b6822b4481702e30f07deed)) + + +### Features + +* Add BindMount handler for Linux ([#1119](https://github.com/runfinch/finch/issues/1119)) ([a49df29](https://github.com/runfinch/finch/commit/a49df292d00af9e4b8a247c0b24c0faa5d465515)) +* Add Dockercompat Mode & DevContainer Support ([#1100](https://github.com/runfinch/finch/issues/1100)) ([c004516](https://github.com/runfinch/finch/commit/c004516c48dcbe85cd16b0c4b0060105e5118fa8)) +* add finch version output to support-bundle ([#1124](https://github.com/runfinch/finch/issues/1124)) ([33d519b](https://github.com/runfinch/finch/commit/33d519b824f4df922df654d7ccb6861832eaaa86)) +* Add More PassedEnvs for ECR CredHelper ([#1132](https://github.com/runfinch/finch/issues/1132)) ([0cb6a55](https://github.com/runfinch/finch/commit/0cb6a55c56d0c26f2648806d7983820796c1b04a)) +* allow user configurable docker compose version env variable ([#1133](https://github.com/runfinch/finch/issues/1133)) ([69b066b](https://github.com/runfinch/finch/commit/69b066b2e9b2ffe39c78f21eb809fa74e9728c2e)) +* handle dockercompat inspect for devcontainers ([#1121](https://github.com/runfinch/finch/issues/1121)) ([5ba7305](https://github.com/runfinch/finch/commit/5ba730580300e6b49d37fd6be8ee7d75ac396462)) +* **macOS:** Support host DNS aliases for macos ([#1085](https://github.com/runfinch/finch/issues/1085)) ([6b7f053](https://github.com/runfinch/finch/commit/6b7f05322141d187246c7d2f3925927a69eb4491)) + + +### Bug Fixes + +* check config file before accessing values ([#1120](https://github.com/runfinch/finch/issues/1120)) ([5a47eec](https://github.com/runfinch/finch/commit/5a47eecdff1371ae0611aadcea251cadf648f856)) + +## [1.3.1](https://github.com/runfinch/finch/compare/v1.3.0...v1.3.1) (2024-09-27) + + +### Build System or External Dependencies + +* trigger new release-please build ([6ef2e6b](https://github.com/runfinch/finch/commit/6ef2e6b157bc6226a878196c0b5dd692dcca4ce3)) +* trigger new release-please PR ([#1114](https://github.com/runfinch/finch/issues/1114)) ([6ef2e6b](https://github.com/runfinch/finch/commit/6ef2e6b157bc6226a878196c0b5dd692dcca4ce3)) + ## [1.3.0](https://github.com/runfinch/finch/compare/v1.2.3...v1.3.0) (2024-09-24) diff --git a/Makefile b/Makefile index 45d717557..c5adf413f 100644 --- a/Makefile +++ b/Makefile @@ -244,11 +244,12 @@ download-licenses: # - github.com/runfinch/finch is ignored because we don't have to check our own license. # Moreover, if we don't ignore it, the following error will occur: # `module github.com/runfinch/finch has empty version, defaults to HEAD. The license URL may be incorrect. Please verify!`. +# `module github.com/multiformats/go-base36 has a Apache license and MIT license but not written as LICENSE format` check-licenses: GOBIN = $(CURDIR)/tools_bin check-licenses: go mod download GOBIN=$(GOBIN) go install github.com/google/go-licenses - $(GOBIN)/go-licenses check --ignore golang.org/x,github.com/runfinch/finch --allowed_licenses Apache-2.0,BSD-2-Clause,BSD-3-Clause,ISC,MIT --include_tests ./... + $(GOBIN)/go-licenses check --ignore golang.org/x,github.com/runfinch/finch --ignore github.com/multiformats/go-base36 --allowed_licenses Apache-2.0,BSD-2-Clause,BSD-3-Clause,ISC,MIT --include_tests ./... .PHONY: test-unit test-unit: diff --git a/README.md b/README.md index 827dc2376..59564f34f 100644 --- a/README.md +++ b/README.md @@ -113,15 +113,17 @@ Finch has a simple and extensible configuration. A configuration file at `${HOME}/.finch/finch.yaml` will be generated on first run. Currently, this config file has options for system resource limits for the underlying virtual machine. These default limits are generated dynamically based on the resources available on the host system, but can be changed by manually editing the config file. -For a full list of configuration options, check [the struct here](https://github.com/runfinch/finch/blob/main/pkg/config/config.go#L34). +For a full list of configuration options, check the finch struct for [macOS](pkg/config/config_darwin.go#L32). An example `finch.yaml` looks like this: ```yaml # cpus: the amount of vCPU to dedicate to the virtual machine. (required) cpus: 4 + # memory: the amount of memory to dedicate to the virtual machine. (required) memory: 4GiB + # snapshotters: the snapshotters a user wants to use (the first snapshotter will be set as the default snapshotter) # Supported Snapshotters List: # - soci https://github.com/awslabs/soci-snapshotter/tree/main @@ -132,6 +134,7 @@ memory: 4GiB # and remove the snapshotter configuration in the containerd config file found at /etc/containerd/config.toml snapshotters: - soci + # creds_helpers: a list of credential helpers that will be installed and configured automatically. # Supported Credential Helpers List: # - ecr-login https://github.com/awslabs/amazon-ecr-credential-helper @@ -144,12 +147,14 @@ snapshotters: # folder entirely. (optional) creds_helpers: - ecr-login + # additional_directories: the work directories that are not supported by default. In macOS, only home directory is supported by default. # For example, if you want to mount a directory into a container, and that directory is not under your home directory, # then you'll need to specify this field to add that directory or any ascendant of it as a work directory. (optional) additional_directories: # the path of each additional directory. - path: /Volumes + # vmType: sets which Hypervisor to use to launch the VM. (optional) # Only takes effect when a new VM is launched (only on vm init). # One of: "qemu", "vz". @@ -159,6 +164,7 @@ additional_directories: # NOTE: prior to version 1.2.0, "qemu" was the default, and it will still be the default for # macOS versions that do not support Virtualization.framework (pre-13.0.0). vmType: "vz" + # rosetta: sets whether to enable Rosetta as the binfmt_misc handler for x86_64 # binaries inside the VM, as an alternative to qemu user mode emulation. (optional) # Only takes effect when a new VM is launched (only on vm init). @@ -169,13 +175,17 @@ vmType: "vz" # some performance regressions, as noted in this issue: # https://github.com/lima-vm/lima/issues/1269 rosetta: false + +# dockercompat: a configuration parameter to activate finch functionality to accept Docker-like commands and arguments. +# For running DevContainers on Finch, this functionality will convert Docker-like arguments into compatible nerdctl commands and arguments. +dockercompat: true ``` #### Windows A configuration file at `$env:LOCALAPPDATA\.finch\finch.yaml` will be generated on first run. Currently, this config file does not have options for system resource [limits due to limitations in WSL](https://github.com/microsoft/WSL/issues/8570). -For a full list of configuration options, check [the struct here](pkg/config/config.go#L30). +For a full list of configuration options, check the finch struct for [windows](pkg/config/config_windows.go#L18). An example `finch.yaml` looks like this: @@ -190,6 +200,7 @@ An example `finch.yaml` looks like this: # and remove the snapshotter configuration in the containerd config file found at /etc/containerd/config.toml snapshotters: - soci + # creds_helpers: a list of credential helpers that will be installed and configured automatically. # Supported Credential Helpers List: # - ecr-login https://github.com/awslabs/amazon-ecr-credential-helper @@ -205,6 +216,10 @@ creds_helpers: # sets wsl2 Hypervisor to use to launch the VM. (optional) vmType: "wsl2" + +# dockercompat: a configuration parameter to activate finch functionality to accept Docker-like commands and arguments. +# For running DevContainers on Finch, this functionality will convert Docker-like arguments into compatible nerdctl commands and arguments. +dockercompat: true ``` ### FAQ diff --git a/cmd/finch/devcontainer_patch.go b/cmd/finch/devcontainer_patch.go new file mode 100644 index 000000000..65e66c6fc --- /dev/null +++ b/cmd/finch/devcontainer_patch.go @@ -0,0 +1,125 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package main denotes the entry point of finch CLI. +// TODO: Remove all instances of these calls once supported upstream +package main + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "strings" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/docker/go-connections/nat" + "github.com/sirupsen/logrus" + "golang.org/x/exp/slices" + + "github.com/runfinch/finch/pkg/command" +) + +// Config is from https://github.com/moby/moby/blob/8dbd90ec00daa26dc45d7da2431c965dec99e8b4/api/types/container/config.go#L37-L69 +type Config struct { + Hostname string `json:",omitempty"` // Hostname + User string `json:",omitempty"` // User that will run the command(s) inside the container, also support user:group + AttachStdin bool // Attach the standard input, makes possible user interaction + ExposedPorts nat.PortSet `json:",omitempty"` // List of exposed ports + Env []string `json:",omitempty"` // List of environment variable to set in the container + Cmd []string `json:",omitempty"` // Command to run when starting the container + Volumes map[string]struct{} `json:",omitempty"` // List of volumes (mounts) used for the container + WorkingDir string `json:",omitempty"` // Current directory (PWD) in the command will be launched + Entrypoint []string `json:",omitempty"` // Entrypoint to run when starting the container + Labels map[string]string `json:",omitempty"` // List of labels set to this containerT + Image string `json:",omitempty"` +} + +// Container mimics a `docker container inspect` object. +// From https://github.com/moby/moby/blob/v20.10.1/api/types/types.go#L340-L374 +type Container struct { + ID string `json:"Id"` + Created string + Path string + Args []string + State *dockercompat.ContainerState + Image string + ResolvConfPath string + HostnamePath string + LogPath string + Name string + RestartCount int + Driver string + Platform string + AppArmorProfile string + SizeRw *int64 `json:",omitempty"` + SizeRootFs *int64 `json:",omitempty"` + Mounts []dockercompat.MountPoint + Config *Config + NetworkSettings *dockercompat.NetworkSettings +} + +func prettyPrintJSON(input string) { + var mergedData []Container + jsonObjects := strings.Split(input, "\n") + + for i, jsonStr := range jsonObjects { + if len(jsonStr) == 0 { + continue + } + var container Container + err := json.Unmarshal([]byte(jsonStr), &container) + if err != nil { + logrus.Error("Error parsing JSON at index: ", i, err) + continue + } + + if container.Config != nil { + container.Config.Image = container.Image + } + + if container.State != nil { + container.State.StartedAt = "0001-01-01T00:00:00Z" + } + + if container.NetworkSettings == nil { + container.NetworkSettings = &dockercompat.NetworkSettings{ + Ports: &nat.PortMap{}, + } + } + + mergedData = append(mergedData, container) + } + + finalJSON, err := json.MarshalIndent(mergedData, "", " ") + if err != nil { + logrus.Error("Error marshaling final JSON: ", err) + return + } + + fmt.Println(string(finalJSON)) +} + +func inspectContainerOutputHandler(cmd command.Command) error { + var stdoutBuf bytes.Buffer + cmd.SetStdout(&stdoutBuf) + err := cmd.Run() + if err != nil { + return err + } + prettyPrintJSON(stdoutBuf.String()) + return err +} + +func handleDockerCompatComposeVersion(cmdName string, nc nerdctlCommand, runArgs []string) error { + if cmdName == "compose" && nc.fc.DockerCompat && slices.Contains(runArgs, "version") { + ver := nc.systemDeps.Env("DOCKER_COMPOSE_VERSION") + if ver != "" { + logrus.Warn("Displaying docker compose version set as environment variable DOCKER_COMPOSE_VERSION...") + fmt.Println(ver) + return nil + } + return errors.New("DOCKER_COMPOSE_VERSION environment variable is not set") + } + return errors.New("") +} diff --git a/cmd/finch/main.go b/cmd/finch/main.go index 9a43fcd60..b605b2313 100644 --- a/cmd/finch/main.go +++ b/cmd/finch/main.go @@ -44,5 +44,12 @@ func initializeNerdctlCommands( for cmdName, cmdDescription := range nerdctlCmds { allNerdctlCommands = append(allNerdctlCommands, nerdctlCommandCreator.create(cmdName, cmdDescription)) } + + if fc != nil && fc.DockerCompat { + for cmdName, cmdDescription := range dockerCompatCmds { + allNerdctlCommands = append(allNerdctlCommands, nerdctlCommandCreator.create(cmdName, cmdDescription)) + } + } + return allNerdctlCommands } diff --git a/cmd/finch/main_native.go b/cmd/finch/main_native.go index 9c8443f12..91c289e47 100644 --- a/cmd/finch/main_native.go +++ b/cmd/finch/main_native.go @@ -104,6 +104,7 @@ var newApp = func( ecc, ncc, lima, + system.NewStdLib(), ) // append nerdctl commands diff --git a/cmd/finch/main_remote.go b/cmd/finch/main_remote.go index 2f42e318f..4e23400bb 100644 --- a/cmd/finch/main_remote.go +++ b/cmd/finch/main_remote.go @@ -114,6 +114,7 @@ var newApp = func( ecc, ncc, lima, + system.NewStdLib(), ) // append nerdctl commands diff --git a/cmd/finch/nerdctl.go b/cmd/finch/nerdctl.go index c372c9e27..642ff30e2 100644 --- a/cmd/finch/nerdctl.go +++ b/cmd/finch/nerdctl.go @@ -6,10 +6,12 @@ package main import ( "encoding/json" "fmt" + "strings" "golang.org/x/exp/slices" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/sirupsen/logrus" "github.com/spf13/afero" "github.com/spf13/cobra" @@ -30,6 +32,7 @@ type NerdctlCommandSystemDeps interface { system.FilePathJoiner system.AbsFilePath system.FilePathToSlash + system.EnvGetter } type nerdctlCommandCreator struct { @@ -41,6 +44,11 @@ type nerdctlCommandCreator struct { fc *config.Finch } +type ( + argHandler func(systemDeps NerdctlCommandSystemDeps, fc *config.Finch, args []string, index int) error + commandHandler func(systemDeps NerdctlCommandSystemDeps, fc *config.Finch, cmdName *string, args *[]string, inspectType *string) error +) + func newNerdctlCommandCreator( ncc command.NerdctlCmdCreator, ecc command.Creator, @@ -192,12 +200,36 @@ var nerdctlCmds = map[string]string{ "wait": "Block until one or more containers stop, then print their exit codes", } +var dockerCompatCmds = map[string]string{ + "buildx": "build version", +} + +var aliasMap = map[string]string{ + "build": "image build", + "run": "container run", + "cp": "container cp", +} + +var commandHandlerMap = map[string]commandHandler{ + "buildx": handleBuildx, + "inspect": handleDockerCompatInspect, +} + +var argHandlerMap = map[string]map[string]argHandler{ + "image build": { + "--load": handleDockerBuildLoad, + }, + "container run": { + "--mount": handleBindMounts, + }, +} + var cmdFlagSetMap = map[string]map[string]sets.Set[string]{ "container run": { "shortBoolFlags": sets.New[string]("-d", "-i", "-t"), "longBoolFlags": sets.New[string]( "--detach", "--init", "--interactive", "--oom-kill-disable", - "--privileged", "--read-only", "--rm", "--rootfs", "--tty"), + "--privileged", "--read-only", "--rm", "--rootfs", "--tty", "--sig-proxy"), "shortArgFlags": sets.New[string]("-e", "-h", "-m", "-u", "-w", "-p", "-l", "-v"), }, "exec": { @@ -215,3 +247,164 @@ var cmdFlagSetMap = map[string]map[string]sets.Set[string]{ "shortArgFlags": sets.New[string]("-e", "-h", "-m", "-u", "-w", "-p", "-l", "-v"), }, } + +// converts "docker build --load" flag to "nerdctl build --output=type=docker". +func handleDockerBuildLoad(_ NerdctlCommandSystemDeps, fc *config.Finch, nerdctlCmdArgs []string, index int) error { + if fc != nil && fc.DockerCompat { + nerdctlCmdArgs[index] = "--output=type=docker" + } + + return nil +} + +func handleBuildx(_ NerdctlCommandSystemDeps, fc *config.Finch, cmdName *string, args *[]string, _ *string) error { + if fc == nil || !fc.DockerCompat { + return nil + } + + if cmdName != nil && *cmdName == "buildx" { + subCmd := (*args)[0] + buildxSubcommands := []string{"bake", "create", "debug", "du", "imagetools", "inspect", "ls", "prune", "rm", "stop", "use", "version"} + + if slices.Contains(buildxSubcommands, subCmd) { + return fmt.Errorf("unsupported buildx command: %s", subCmd) + } + + logrus.Warn("buildx is not supported. using standard buildkit instead...") + if subCmd == "build" { + *args = (*args)[1:] + } + *cmdName = "build" + } + // else, continue with the original command + return nil +} + +func handleDockerCompatInspect(_ NerdctlCommandSystemDeps, fc *config.Finch, cmdName *string, args *[]string, inspectType *string) error { + if fc == nil || !fc.DockerCompat { + return nil + } + + if *args == nil { + return fmt.Errorf("invalid arguments: args (null pointer)") + } + + modeDockerCompat := `--mode=dockercompat` + sizeArg := "" + savedArgs := []string{} + skip := false + *inspectType = "" + + for idx, arg := range *args { + if skip { + skip = false + continue + } + + if (arg == "--type") && (idx < len(*args)-1) { + *inspectType = (*args)[idx+1] + skip = true + continue + } + + if strings.Contains(arg, "--type") && strings.Contains(arg, "=") { + *inspectType = strings.Split(arg, "=")[1] + continue + } + + if (arg == "--size") || (arg == "-s") { + sizeArg = "--size" + continue + } + + savedArgs = append(savedArgs, arg) + } + + switch *inspectType { + case "image": + *cmdName = "image inspect" + *args = append([]string{modeDockerCompat}, savedArgs...) + case "volume": + *cmdName = "volume inspect" + if sizeArg != "" { + *args = append([]string{sizeArg}, savedArgs...) + } else { + *args = append([]string{}, savedArgs...) + } + case "container": + *cmdName = "inspect" + *args = append([]string{modeDockerCompat}, savedArgs...) + case "": + *cmdName = "inspect" + *args = append([]string{modeDockerCompat}, savedArgs...) + *inspectType = "container" + default: + return fmt.Errorf("unsupported inspect type: %s", *inspectType) + } + + return nil +} + +// handles the argument & value of --mount option +// +// invokes OS specific path handler for source path of the bind mount +// and removes the consistency key-value entity from value +func handleBindMounts(systemDeps NerdctlCommandSystemDeps, _ *config.Finch, nerdctlCmdArgs []string, index int) error { + prefix := nerdctlCmdArgs[index] + var ( + v string + found bool + before string + ) + if strings.Contains(nerdctlCmdArgs[index], "=") { + before, v, found = strings.Cut(prefix, "=") + } else { + if (index + 1) < len(nerdctlCmdArgs) { + v = nerdctlCmdArgs[index+1] + } else { + return fmt.Errorf("invalid positional parameter for %s", prefix) + } + } + + // eg --mount type=bind,source="$(pwd)"/target,target=/app,readonly + // eg --mount type=bind, source=${pwd}/source_dir, target=/target_dir, consistency=cached + // https://docs.docker.com/storage/bind-mounts/#choose-the--v-or---mount-flag order does not matter, so convert to a map + entries := strings.Split(v, ",") + m := make(map[string]string) + ro := []string{} + for _, e := range entries { + parts := strings.Split(e, "=") + if len(parts) < 2 { + ro = append(ro, parts...) + } else { + m[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + } + } + // Check if type is bind mount, else return + if m["type"] != "bind" { + return nil + } + + // Remove 'consistency' key-value pair, if present + delete(m, "consistency") + + // Invoke the OS specific path handler + err := handleBindMountPath(systemDeps, m) + if err != nil { + return err + } + + // Convert to string representation + s := mapToString(m) + // append read-only key if present + if len(ro) > 0 { + s = s + "," + strings.Join(ro, ",") + } + if found { + nerdctlCmdArgs[index] = fmt.Sprintf("%s=%s", before, s) + } else { + nerdctlCmdArgs[index+1] = s + } + + return nil +} diff --git a/cmd/finch/nerdctl_darwin.go b/cmd/finch/nerdctl_darwin.go index 527bd9eb9..437ee043e 100644 --- a/cmd/finch/nerdctl_darwin.go +++ b/cmd/finch/nerdctl_darwin.go @@ -20,13 +20,11 @@ func convertToWSLPath(_ NerdctlCommandSystemDeps, _ string) (string, error) { return "", nil } -var aliasMap = map[string]string{ - "run": "container run", -} +var osAliasMap = map[string]string{} -var argHandlerMap = map[string]map[string]argHandler{} +var osArgHandlerMap = map[string]map[string]argHandler{} -var commandHandlerMap = map[string]commandHandler{} +var osCommandHandlerMap = map[string]commandHandler{} func (nc *nerdctlCommand) GetCmdArgs() []string { return []string{"shell", limaInstanceName, "sudo", "-E"} @@ -46,3 +44,17 @@ func resolveIP(host string, logger flog.Logger, _ command.Creator) (string, erro } return host, nil } + +func handleBindMountPath(_ NerdctlCommandSystemDeps, _ map[string]string) error { + // Do nothing by default + return nil +} + +func mapToString(m map[string]string) string { + var parts []string + for k, v := range m { + part := fmt.Sprintf("%s=%s", k, v) + parts = append(parts, part) + } + return strings.Join(parts, ",") +} diff --git a/cmd/finch/nerdctl_darwin_test.go b/cmd/finch/nerdctl_darwin_test.go index dfa0e6f5c..5fa79b458 100644 --- a/cmd/finch/nerdctl_darwin_test.go +++ b/cmd/finch/nerdctl_darwin_test.go @@ -6,10 +6,12 @@ package main import ( + "bytes" "errors" "fmt" "os" "path/filepath" + "strings" "testing" "github.com/golang/mock/gomock" @@ -44,11 +46,7 @@ func TestNerdctlCommand_runAdaptor(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "info").Return(c) c.EXPECT().Run() @@ -110,12 +108,8 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) logger.EXPECT().SetLevel(flog.Debug) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) ncc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "pull", "test:tag").Return(c) c.EXPECT().Run() @@ -140,11 +134,7 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) + AddEmptyEnvLookUps(ncsd) ncc.EXPECT().RunWithReplacingStdout( testStdoutRs, "shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "pull", "test:tag", "--help").Return(nil) }, @@ -168,11 +158,7 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) + AddEmptyEnvLookUps(ncsd) ncc.EXPECT().RunWithReplacingStdout( testStdoutRs, "shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "pull", "test:tag", "--help"). Return(fmt.Errorf("failed to replace")) @@ -200,6 +186,10 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) @@ -230,6 +220,10 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) @@ -260,6 +254,10 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) @@ -296,6 +294,10 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("TEST_SESSION_TOKEN", true) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) awsCmd := mocks.NewCommand(ctrl) ecc.EXPECT().Create( @@ -358,6 +360,10 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("TEST_SESSION_TOKEN", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) awsCmd := mocks.NewCommand(ctrl) ecc.EXPECT().Create( @@ -417,6 +423,10 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("TEST_SESSION_TOKEN", true) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) awsCmd := mocks.NewCommand(ctrl) ecc.EXPECT().Create( @@ -472,6 +482,10 @@ func TestNerdctlCommand_run_pullCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("TEST_SESSION_TOKEN", true) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) awsCmd := mocks.NewCommand(ctrl) ecc.EXPECT().Create( @@ -560,11 +574,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "-it", "alpine:latest", "env").Return(c) @@ -593,11 +603,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "-it", "--name", "myContainer", "--rm", "-e", "ARG1=val1", "-e", "ARG2=val2", "-e", "ARG3=val3", @@ -624,14 +630,10 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().LookupEnv("ARG1").Return("val1", true) ncsd.EXPECT().LookupEnv("ARG2").Return("val2", true) ncsd.EXPECT().LookupEnv("ARG3").Return("val3", true) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "-it", "--rm", "--name", "myContainer", "-e", "ARG1=val1", "-e", "ARG2=val2", "-e", "ARG3=val3", @@ -661,14 +663,10 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().LookupEnv("ARG1") ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("ARG3") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--name", "myContainer", "-it", "--rm", "-e", "ARG0=val0", "alpine:latest", "env").Return(c) @@ -698,11 +696,7 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().SetLevel(flog.Debug) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--name", "myContainer", "--rm", "-it", "-e", "ARG1=val1", "-e", "ARG2=val2", "-e", "ARG3=val3", @@ -730,14 +724,10 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().SetLevel(flog.Debug) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().LookupEnv("ARG1").Return("val1", true) ncsd.EXPECT().LookupEnv("ARG2").Return("val2", true) ncsd.EXPECT().LookupEnv("ARG3").Return("val3", true) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "--name", "myContainer", "-it", "-e", "ARG1=val1", "-e", "ARG2=val2", "-e", "ARG3=val3", @@ -768,14 +758,10 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().SetLevel(flog.Debug) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().LookupEnv("ARG1") ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("ARG3") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "-it", "--name", "myContainer", "-e", "ARG0=val0", "alpine:latest", "env").Return(c) @@ -805,11 +791,7 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().SetLevel(flog.Debug) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "-i", "--name", "myContainer", "--rm", "-t", "-e", "ARG1=val1", "-e", "ARG2=val2", "-e", "ARG3=val3", @@ -839,14 +821,10 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("NOTSETARG") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) lcc.EXPECT(). Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "-i", "--name", "myContainer", "--rm", "-e", "ARG1=val1", @@ -877,14 +855,10 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().SetLevel(flog.Debug) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("NOTSETARG") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) lcc.EXPECT(). Create( "shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", @@ -916,14 +890,10 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2").Return("val2", true) ncsd.EXPECT().LookupEnv("NOTSETARG") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) lcc.EXPECT(). Create( "shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", @@ -970,13 +940,9 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC := mocks.NewCommand(ctrl) lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + AddEmptyEnvLookUps(ncsd) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) logger.EXPECT().Debugf(`Resolving special IP "host-gateway" to %q for host %q`, "192.168.5.2", "name") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "--add-host", "name:192.168.5.2", "alpine:latest").Return(c) @@ -1002,11 +968,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "--add-host", "name:0.0.0.0", "alpine:latest").Return(c) @@ -1032,11 +994,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "--add-host", "alpine:latest").Return(c) @@ -1062,12 +1020,8 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) logger.EXPECT().Debugf(`Resolving special IP "host-gateway" to %q for host %q`, "192.168.5.2", "name") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "--add-host=name:192.168.5.2", "alpine:latest").Return(c) @@ -1093,12 +1047,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) - + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "--add-host=name:0.0.0.0", "alpine:latest").Return(c) @@ -1127,11 +1076,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "-v", "/tmp:/tmp1/tmp2:rro", "--volume", "/tmp:/tmp1:rprivate,rro", "-v", "/tmp:/tmp1/tmp2/tmp3/tmp4:rro", @@ -1161,11 +1106,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "--rm", "-v", "/tmp:/tmp1/tmp2:rro", "--volume", "/tmp:/tmp1:rprivate,rro", @@ -1196,11 +1137,7 @@ func TestNerdctlCommand_run(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", "-i", "-d", "-p", "8080:8080", "--name", "myContainer", "--rm", "-e", "ARG1=val1", @@ -1208,6 +1145,32 @@ func TestNerdctlCommand_run(t *testing.T) { c.EXPECT().Run() }, }, + { + name: "bindmount with src and consistency", + cmdName: "run", + fc: &config.Finch{}, + args: []string{"--mount", "type=bind,src=./src,consistency=cached", "alpine:latest"}, + wantErr: nil, + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + AddEmptyEnvLookUps(ncsd) + c := mocks.NewCommand(ctrl) + lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "container", "run", + "--mount", ContainsMultipleStrs([]string{"bind", "type", "!consistency"}), "alpine:latest").Return(c) + c.EXPECT().Run() + }, + }, } for _, tc := range testCases { @@ -1228,6 +1191,300 @@ func TestNerdctlCommand_run(t *testing.T) { } } +func TestNerdctlCommand_run_inspectCommand(t *testing.T) { + t.Parallel() + testCases := []struct { + name string + cmdName string + fc *config.Finch + args []string + wantErr error + mockSvc func( + t *testing.T, + lcc *mocks.NerdctlCmdCreator, + ecc *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + fs afero.Fs, + ) + }{ + { + name: "inspect without flags", + cmdName: "inspect", + fc: &config.Finch{ + SharedSettings: config.SharedSettings{ + DockerCompat: true, + }, + }, + args: []string{"da24"}, + wantErr: nil, + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + AddEmptyEnvLookUps(ncsd) + c := mocks.NewCommand(ctrl) + var stdoutBuf bytes.Buffer + c.EXPECT().SetStdout(&stdoutBuf) + lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "inspect", "--mode=dockercompat", "da24", + "--format", "{{json .}}").Return(c) + c.EXPECT().Run() + }, + }, + { + name: "inspect with typeContainer flag", + cmdName: "inspect", + fc: &config.Finch{ + SharedSettings: config.SharedSettings{ + DockerCompat: true, + }, + }, + args: []string{"--type=container", "44de"}, + wantErr: nil, + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + AddEmptyEnvLookUps(ncsd) + c := mocks.NewCommand(ctrl) + var stdoutBuf bytes.Buffer + c.EXPECT().SetStdout(&stdoutBuf) + lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "inspect", "--mode=dockercompat", "44de", + "--format", "{{json .}}").Return(c) + c.EXPECT().Run() + }, + }, + { + name: "inspect with typeVolume option", + cmdName: "inspect", + fc: &config.Finch{ + SharedSettings: config.SharedSettings{ + DockerCompat: true, + }, + }, + args: []string{"--type=volume", "myVolume"}, + wantErr: nil, + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + AddEmptyEnvLookUps(ncsd) + c := mocks.NewCommand(ctrl) + lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "volume", "inspect", "myVolume").Return(c) + c.EXPECT().Run() + }, + }, + { + name: "inspect with typeImage option", + cmdName: "inspect", + fc: &config.Finch{ + SharedSettings: config.SharedSettings{ + DockerCompat: true, + }, + }, + args: []string{"--type=image", "myImage"}, + wantErr: nil, + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + AddEmptyEnvLookUps(ncsd) + c := mocks.NewCommand(ctrl) + lcc.EXPECT().Create( + "shell", + limaInstanceName, + "sudo", + "-E", + nerdctlCmdName, + "image", + "inspect", + "--mode=dockercompat", + "myImage", + ).Return(c) + c.EXPECT().Run() + }, + }, + { + name: "inspect with size flag", + cmdName: "inspect", + fc: &config.Finch{ + SharedSettings: config.SharedSettings{ + DockerCompat: true, + }, + }, + args: []string{"--size", "44de"}, + wantErr: nil, + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + AddEmptyEnvLookUps(ncsd) + c := mocks.NewCommand(ctrl) + var stdoutBuf bytes.Buffer + c.EXPECT().SetStdout(&stdoutBuf) + lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "inspect", "--mode=dockercompat", "44de", + "--format", "{{json .}}").Return(c) + c.EXPECT().Run() + }, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + ncc := mocks.NewNerdctlCmdCreator(ctrl) + ecc := mocks.NewCommandCreator(ctrl) + ncsd := mocks.NewNerdctlCommandSystemDeps(ctrl) + logger := mocks.NewLogger(ctrl) + fs := afero.NewMemMapFs() + tc.mockSvc(t, ncc, ecc, ncsd, logger, ctrl, fs) + + assert.Equal(t, tc.wantErr, newNerdctlCommand(ncc, ecc, ncsd, logger, fs, tc.fc).run(tc.cmdName, tc.args)) + }) + } +} + +func TestNerdctlCommand_run_buildxCommand(t *testing.T) { + t.Parallel() + testCases := []struct { + name string + cmdName string + fc *config.Finch + args []string + wantErr error + mockSvc func( + t *testing.T, + lcc *mocks.NerdctlCmdCreator, + ecc *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + fs afero.Fs, + ) + }{ + { + name: "docker buildx build", + cmdName: "buildx", + fc: &config.Finch{ + SharedSettings: config.SharedSettings{ + DockerCompat: true, + }, + }, + args: []string{"build", "-t", "demo", "."}, + wantErr: nil, + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + ncsd *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + AddEmptyEnvLookUps(ncsd) + c := mocks.NewCommand(ctrl) + lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "build", "-t", "demo", ".").Return(c) + c.EXPECT().Run() + }, + }, + { + name: "docker buildx version", + cmdName: "buildx", + fc: &config.Finch{ + SharedSettings: config.SharedSettings{ + DockerCompat: true, + }, + }, + args: []string{"version"}, + wantErr: fmt.Errorf("unsupported buildx command: version"), + mockSvc: func( + _ *testing.T, + lcc *mocks.NerdctlCmdCreator, + _ *mocks.CommandCreator, + _ *mocks.NerdctlCommandSystemDeps, + logger *mocks.Logger, + ctrl *gomock.Controller, + _ afero.Fs, + ) { + getVMStatusC := mocks.NewCommand(ctrl) + lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) + getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) + logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") + }, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + ncc := mocks.NewNerdctlCmdCreator(ctrl) + ecc := mocks.NewCommandCreator(ctrl) + ncsd := mocks.NewNerdctlCommandSystemDeps(ctrl) + logger := mocks.NewLogger(ctrl) + fs := afero.NewMemMapFs() + tc.mockSvc(t, ncc, ecc, ncsd, logger, ctrl, fs) + + assert.Equal(t, tc.wantErr, newNerdctlCommand(ncc, ecc, ncsd, logger, fs, tc.fc).run(tc.cmdName, tc.args)) + }) + } +} + func TestNerdctlCommand_run_miscCommand(t *testing.T) { t.Parallel() testCases := []struct { @@ -1265,13 +1522,9 @@ func TestNerdctlCommand_run_miscCommand(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) - lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "build", "-t", "demo", ".").Return(c) + lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "image", "build", "-t", "demo", ".").Return(c) c.EXPECT().Run() }, }, @@ -1297,6 +1550,10 @@ func TestNerdctlCommand_run_miscCommand(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) c := mocks.NewCommand(ctrl) @@ -1325,11 +1582,7 @@ func TestNerdctlCommand_run_miscCommand(t *testing.T) { lcc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) lcc.EXPECT().Create("shell", limaInstanceName, "sudo", "-E", nerdctlCmdName, "exec", "test-ctr", "sh", "-c", "echo", "foo", ">", "/tmp/test.txt").Return(c) @@ -1355,3 +1608,70 @@ func TestNerdctlCommand_run_miscCommand(t *testing.T) { }) } } + +func AddEmptyEnvLookUps(ncsd *mocks.NerdctlCommandSystemDeps) { + ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) + ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) +} + +type ContainsSubstring struct { + substr string +} + +func (m *ContainsSubstring) Matches(x interface{}) bool { + s, ok := x.(string) + if !ok { + return false + } + return strings.Contains(s, m.substr) +} + +func (m *ContainsSubstring) String() string { + return fmt.Sprintf("contains substring %q", m.substr) +} + +func ContainsStr(substr string) gomock.Matcher { + return &ContainsSubstring{substr: substr} +} + +type ContainsMultipleSubstrings struct { + substrs []string +} + +func (m *ContainsMultipleSubstrings) Matches(x interface{}) bool { + s, ok := x.(string) + if !ok { + return false + } + // Check if each substrings is present in the input string + // except strings that start with "!" + passTest := true + for _, substr := range m.substrs { + if substr[0] == '!' { + if strings.Contains(s, substr[1:]) { + passTest = false + } + continue + } + + if !strings.Contains(s, substr) { + passTest = false + } + } + return passTest +} + +func (m *ContainsMultipleSubstrings) String() string { + return fmt.Sprintf("contains substrings %q", m.substrs) +} + +func ContainsMultipleStrs(substrs []string) gomock.Matcher { + return &ContainsMultipleSubstrings{substrs: substrs} +} diff --git a/cmd/finch/nerdctl_native.go b/cmd/finch/nerdctl_native.go index 062115f22..094660173 100644 --- a/cmd/finch/nerdctl_native.go +++ b/cmd/finch/nerdctl_native.go @@ -6,6 +6,9 @@ package main import ( + "fmt" + "strings" + "golang.org/x/exp/slices" "github.com/runfinch/finch/pkg/command" @@ -13,6 +16,14 @@ import ( ) func (nc *nerdctlCommand) run(cmdName string, args []string) error { + var ( + hasCmdHandler, hasArgHandler bool + cmdHandler commandHandler + aMap map[string]argHandler + err error + inspectType string + ) + // eat the debug arg, and set the log level to avoid nerdctl parsing this flag dbgIdx := slices.Index(args, "--debug") if dbgIdx >= 0 { @@ -20,13 +31,87 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { nc.logger.SetLevel(flog.Debug) } - cmdArgs := append([]string{cmdName}, args...) - if nc.shouldReplaceForHelp(cmdName, args) { + alias, hasAlias := aliasMap[cmdName] + if hasAlias { + cmdHandler, hasCmdHandler = commandHandlerMap[alias] + aMap, hasArgHandler = argHandlerMap[alias] + } else { + cmdHandler, hasCmdHandler = commandHandlerMap[cmdName] + aMap, hasArgHandler = argHandlerMap[cmdName] + + if !hasArgHandler && len(args) > 0 { + // for commands like image build, container run + key := fmt.Sprintf("%s %s", cmdName, args[0]) + cmdHandler, hasCmdHandler = commandHandlerMap[key] + aMap, hasArgHandler = argHandlerMap[key] + } + } + + // First check if the command has a command handler + if hasCmdHandler { + err := cmdHandler(nc.systemDeps, nc.fc, &cmdName, &args, &inspectType) + if err != nil { + return err + } + } + + for i, arg := range args { + // Check if individual argument (and possibly following value) requires manipulation-in-place handling + if hasArgHandler { + // Check if argument for the command needs handling, sometimes it can be --file= + b, _, _ := strings.Cut(arg, "=") + h, ok := aMap[b] + if ok { + err = h(nc.systemDeps, nc.fc, args, i) + if err != nil { + return err + } + } + } + } + + // Extra manipulation for cases that overwrite cmdName with alias + splitName := strings.Split(cmdName, " ") + cmdArgs := append([]string{splitName[0]}, splitName[1:]...) + cmdArgs = append(cmdArgs, args...) + + if nc.shouldReplaceForHelp(splitName[0], args) { return nc.ncc.RunWithReplacingStdout( []command.Replacement{{Source: "nerdctl", Target: "finch"}}, cmdArgs..., ) } + if inspectType == "container" && nc.fc.DockerCompat && !slices.Contains(cmdArgs, "--format") { + cmdArgs = append(cmdArgs, "--format", "{{json .}}") + cmd := nc.ncc.Create(cmdArgs...) + return inspectContainerOutputHandler(cmd) + } + + if err := handleDockerCompatComposeVersion(cmdName, *nc, cmdArgs); err == nil { + return nil + } + return nc.ncc.Create(cmdArgs...).Run() + +} + +var osAliasMap = map[string]string{} + +var osArgHandlerMap = map[string]map[string]argHandler{} + +var osCommandHandlerMap = map[string]commandHandler{} + +func mapToString(m map[string]string) string { + var parts []string + for k, v := range m { + part := fmt.Sprintf("%s=%s", k, v) + parts = append(parts, part) + } + return strings.Join(parts, ",") +} + +func handleBindMountPath(_ NerdctlCommandSystemDeps, _ map[string]string) error { + // Do nothing by default + return nil } diff --git a/cmd/finch/nerdctl_remote.go b/cmd/finch/nerdctl_remote.go index f1659df50..6f679e152 100644 --- a/cmd/finch/nerdctl_remote.go +++ b/cmd/finch/nerdctl_remote.go @@ -8,6 +8,7 @@ package main import ( "bufio" "fmt" + "maps" "path/filepath" "runtime" "strings" @@ -25,11 +26,6 @@ import ( const nerdctlCmdName = "nerdctl" -type ( - argHandler func(systemDeps NerdctlCommandSystemDeps, args []string, index int) error - commandHandler func(systemDeps NerdctlCommandSystemDeps, args []string) error -) - func (nc *nerdctlCommand) run(cmdName string, args []string) error { err := nc.assertVMIsRunning(nc.ncc, nc.logger) if err != nil { @@ -37,33 +33,55 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { } var ( nerdctlArgs, envs, fileEnvs, cmdArgs, runArgs []string - skip, hasCmdHander, hasArgHandler, lastOpt bool + skip, hasCmdHandler, hasArgHandler, lastOpt bool cmdHandler commandHandler aMap map[string]argHandler firstOptPos int + inspectType string ) - alias, hasAlias := aliasMap[cmdName] + // accumulate distributed map entities + aggAliasMap := make(map[string]string) + maps.Copy(aggAliasMap, aliasMap) + maps.Copy(aggAliasMap, osAliasMap) + + aggCmdHandlerMap := make(map[string]commandHandler) + maps.Copy(aggCmdHandlerMap, commandHandlerMap) + maps.Copy(aggCmdHandlerMap, osCommandHandlerMap) + + aggArgHandlerMap := make(map[string]map[string]argHandler) + for k := range argHandlerMap { + aggArgHandlerMap[k] = make(map[string]argHandler) + maps.Copy(aggArgHandlerMap[k], argHandlerMap[k]) + } + for k := range osArgHandlerMap { + if _, ok := aggArgHandlerMap[k]; !ok { + aggArgHandlerMap[k] = make(map[string]argHandler) + } + maps.Copy(aggArgHandlerMap[k], osArgHandlerMap[k]) + } + + alias, hasAlias := aggAliasMap[cmdName] if hasAlias { cmdName = alias - cmdHandler, hasCmdHander = commandHandlerMap[alias] - aMap, hasArgHandler = argHandlerMap[alias] + cmdHandler, hasCmdHandler = aggCmdHandlerMap[alias] + aMap, hasArgHandler = aggArgHandlerMap[alias] } else { // Check if the command has a handler - cmdHandler, hasCmdHander = commandHandlerMap[cmdName] - aMap, hasArgHandler = argHandlerMap[cmdName] + cmdHandler, hasCmdHandler = aggCmdHandlerMap[cmdName] + aMap, hasArgHandler = aggArgHandlerMap[cmdName] - if !hasCmdHander && !hasArgHandler && len(args) > 0 { + if !hasCmdHandler && !hasArgHandler && len(args) > 0 { // for commands like image build, container run key := fmt.Sprintf("%s %s", cmdName, args[0]) - cmdHandler, hasCmdHander = commandHandlerMap[key] - aMap, hasArgHandler = argHandlerMap[key] + cmdHandler, hasCmdHandler = aggCmdHandlerMap[key] + aMap, hasArgHandler = aggArgHandlerMap[key] } } // First check if the command has command handler - if hasCmdHander { - err := cmdHandler(nc.systemDeps, args) + if hasCmdHandler { + err := cmdHandler(nc.systemDeps, nc.fc, &cmdName, &args, &inspectType) if err != nil { return err } @@ -89,13 +107,13 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { shortFlagArgSet := cmdFlagSetMap[cmdName]["shortArgFlags"] for i, arg := range args { - // Check if command requires arg handling + // Check if individual argument (and possibly following value) requires manipulation-in-place handling if hasArgHandler { // Check if argument for the command needs handling, sometimes it can be --file= b, _, _ := strings.Cut(arg, "=") h, ok := aMap[b] if ok { - err = h(nc.systemDeps, args, i) + err = h(nc.systemDeps, nc.fc, args, i) if err != nil { return err } @@ -103,6 +121,7 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { arg = args[i] } } + // parsing arguments from the command line // may pre-fetch and consume the next argument; // the loop variable will skip any pre-consumed args @@ -116,7 +135,6 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { cmdArgs = append(cmdArgs, arg) continue } - switch { case arg == "--debug": nc.logger.SetLevel(flog.Debug) @@ -157,17 +175,26 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { envs = append(envs, addEnv) } case shortFlagBoolSet.Has(arg) || longFlagBoolSet.Has(arg): - // exact match to a short flag: -? + // exact match to a short no argument flag: -? // or exact match to: -- nerdctlArgs = append(nerdctlArgs, arg) + case longFlagBoolSet.Has(strings.Split(arg, "=")[0]): + // begins with -- + // e.g. --sig-proxy=false + nerdctlArgs = append(nerdctlArgs, arg) case shortFlagBoolSet.Has(arg[:2]): - // begins with a defined short flag, but is adjacent to one or more short flags: -???? + // or begins with a defined short no argument flag, but is adjacent to something + // -???? one or more short bool flags; no following values + // -????="" one or more short bool flags ending with a short arg flag equated to value + // -????"" one or more short bool flags ending with a short arg flag concatenated to value addArg := nc.handleMultipleShortFlags(shortFlagBoolSet, shortFlagArgSet, args, i) nerdctlArgs = append(nerdctlArgs, addArg) case shortFlagArgSet.Has(arg) || shortFlagArgSet.Has(arg[:2]): - // exact match to: -h,-m,-u,-w,-p,-l,-v - // or begins with: -h,-m,-u,-w,-p,-l,-v - // concatenated short flags and values: -p"8080:8080" + // exact match to a short arg flag: -? + // next arg must be the + // or begins with a short arg flag: + // short arg flag concatenated to value: -?"" + // short arg flag equated to value: -?="" or -?= shouldSkip, addKey, addVal := nc.handleFlagArg(arg, args[i+1]) skip = shouldSkip if addKey != "" { @@ -175,7 +202,11 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { nerdctlArgs = append(nerdctlArgs, addVal) } case strings.HasPrefix(arg, "--"): - // --="", -- "" + // exact match to a long arg flag: - + // next arg must be the + // or begins with a long arg flag: + // long arg flag concatenated to value: --"" + // long arg flag equated to value: --="" or --= shouldSkip, addKey, addVal := nc.handleFlagArg(arg, args[i+1]) skip = shouldSkip if addKey != "" { @@ -227,13 +258,13 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { default: for i, arg := range args { - // Check if command requires arg handling + // Check if individual argument (and possibly following value) requires manipulation-in-place handling if hasArgHandler { // Check if argument for the command needs handling, sometimes it can be --file= b, _, _ := strings.Cut(arg, "=") h, ok := aMap[b] if ok { - err = h(nc.systemDeps, args, i) + err = h(nc.systemDeps, nc.fc, args, i) if err != nil { return err } @@ -255,7 +286,8 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { passedEnvs := []string{ "COSIGN_PASSWORD", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", - "AWS_SESSION_TOKEN", "COMPOSE_FILE", + "AWS_SESSION_TOKEN", "COMPOSE_FILE", "SOURCE_DATE_EPOCH", + "AWS_ECR_DISABLE_CACHE", "AWS_ECR_CACHE_DIR", "AWS_ECR_IGNORE_CREDS_STORAGE", } var passedEnvArgs []string @@ -284,7 +316,7 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { if slices.Contains(args, "run") { ensureRemoteCredentials(nc.fc, nc.ecc, &additionalEnv, nc.logger) } - case "build", "pull", "push", "run": + case "build", "pull", "push", "container run": ensureRemoteCredentials(nc.fc, nc.ecc, &additionalEnv, nc.logger) } @@ -303,6 +335,16 @@ func (nc *nerdctlCommand) run(cmdName string, args []string) error { return nc.ncc.RunWithReplacingStdout([]command.Replacement{{Source: "nerdctl", Target: "finch"}}, runArgs...) } + if inspectType == "container" && nc.fc.DockerCompat && !slices.Contains(runArgs, "--format") { + runArgs = append(runArgs, "--format", "{{json .}}") + cmd := nc.ncc.Create(runArgs...) + return inspectContainerOutputHandler(cmd) + } + + if err := handleDockerCompatComposeVersion(cmdName, *nc, cmdArgs); err == nil { + return nil + } + return nc.ncc.Create(runArgs...).Run() } diff --git a/cmd/finch/nerdctl_windows.go b/cmd/finch/nerdctl_windows.go index 26bcf26d0..6a594dc41 100644 --- a/cmd/finch/nerdctl_windows.go +++ b/cmd/finch/nerdctl_windows.go @@ -12,9 +12,49 @@ import ( dockerops "github.com/docker/docker/opts" "github.com/runfinch/finch/pkg/command" + "github.com/runfinch/finch/pkg/config" "github.com/runfinch/finch/pkg/flog" ) +var osAliasMap = map[string]string{ + "save": "image save", + "load": "image load", +} + +var osCommandHandlerMap = map[string]commandHandler{ + "container cp": cpHandler, + "image build": imageBuildHandler, +} + +var osArgHandlerMap = map[string]map[string]argHandler{ + "image build": { + "-f": handleFilePath, + "--file": handleFilePath, + "--iidfile": handleFilePath, + "-o": handleOutputOption, + "--output": handleOutputOption, + "--secret": handleSecretOption, + }, + "image save": { + "-o": handleFilePath, + "--output": handleFilePath, + }, + "image load": { + "-i": handleFilePath, + "--input": handleFilePath, + }, + "container run": { + "--label-file": handleFilePath, + "--cosign-key": handleFilePath, + "--cidfile": handleFilePath, + "-v": handleVolume, + "--volume": handleVolume, + }, + "compose": { + "--file": handleFilePath, + }, +} + func (nc *nerdctlCommand) GetCmdArgs() []string { wd, err := nc.systemDeps.GetWd() if err != nil { @@ -46,7 +86,7 @@ func convertToWSLPath(systemDeps NerdctlCommandSystemDeps, winPath string) (stri } // substitutes wsl path for the provided option in place for nerdctl args. -func handleFilePath(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string, index int) error { +func handleFilePath(systemDeps NerdctlCommandSystemDeps, _ *config.Finch, nerdctlCmdArgs []string, index int) error { prefix := nerdctlCmdArgs[index] // If --filename=" then we need to cut and convert that to wsl path @@ -72,7 +112,7 @@ func handleFilePath(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string } // hanldes -v/--volumes option. For anonymous volumes and named volumes this is no-op. For bind mounts path is converted to wsl path. -func handleVolume(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string, index int) error { +func handleVolume(systemDeps NerdctlCommandSystemDeps, _ *config.Finch, nerdctlCmdArgs []string, index int) error { prefix := nerdctlCmdArgs[index] var ( v string @@ -128,76 +168,8 @@ func handleVolume(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string, return nil } -// translates source path of the bind mount to wslpath for --mount option. -func handleBindMounts(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string, index int) error { - prefix := nerdctlCmdArgs[index] - var ( - v string - found bool - before string - ) - if strings.Contains(nerdctlCmdArgs[index], "=") { - before, v, found = strings.Cut(prefix, "=") - } else { - if (index + 1) < len(nerdctlCmdArgs) { - v = nerdctlCmdArgs[index+1] - } else { - return fmt.Errorf("invalid positional parameter for %s", prefix) - } - } - - // https://docs.docker.com/storage/bind-mounts/#choose-the--v-or---mount-flag order does not matter, so convert to a map - entries := strings.Split(v, ",") - m := make(map[string]string) - ro := []string{} - for _, e := range entries { - parts := strings.Split(e, "=") - // eg --mount type=bind,source="$(pwd)"/target,target=/app,readonly - if len(parts) < 2 { - ro = append(ro, parts...) - } else { - m[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - } - // Check if type is bind mount, else return - if m["type"] != "bind" { - return nil - } - var k string - path, ok := m["src"] - if !ok { - path, ok = m["source"] - k = "source" - } else { - k = "src" - } - // If there is no src or source or not a windows path, do nothing, let nerdctl handle error - if !ok || !strings.Contains(path, `\`) { - return nil - } - wslPath, err := convertToWSLPath(systemDeps, path) - if err != nil { - return err - } - m[k] = wslPath - - // Convert to string representation - s := mapToString(m) - // append read-only key if present - if len(ro) > 0 { - s = s + "," + strings.Join(ro, ",") - } - if found { - nerdctlCmdArgs[index] = fmt.Sprintf("%s=%s", before, s) - } else { - nerdctlCmdArgs[index+1] = s - } - - return nil -} - // handles --output/-o for build command. -func handleOutputOption(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string, index int) error { +func handleOutputOption(systemDeps NerdctlCommandSystemDeps, _ *config.Finch, nerdctlCmdArgs []string, index int) error { prefix := nerdctlCmdArgs[index] var ( v string @@ -244,7 +216,7 @@ func handleOutputOption(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []st } // handles --secret option for build command. -func handleSecretOption(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string, index int) error { +func handleSecretOption(systemDeps NerdctlCommandSystemDeps, _ *config.Finch, nerdctlCmdArgs []string, index int) error { prefix := nerdctlCmdArgs[index] var ( v string @@ -290,8 +262,8 @@ func handleSecretOption(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []st } // cp command handler, takes command arguments and converts hostpath to wsl path in place. It ignores all other arguments. -func cpHandler(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string) error { - for i, arg := range nerdctlCmdArgs { +func cpHandler(systemDeps NerdctlCommandSystemDeps, _ *config.Finch, _ *string, nerdctlCmdArgs *[]string, _ *string) error { + for i, arg := range *nerdctlCmdArgs { // -L and --follow-symlink don't have to be processed if strings.HasPrefix(arg, "-") || arg == "cp" { continue @@ -307,28 +279,28 @@ func cpHandler(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string) err if err != nil { return err } - nerdctlCmdArgs[i] = wslPath + (*nerdctlCmdArgs)[i] = wslPath } return nil } // this is the handler for image build command. It translates build context to wsl path. -func imageBuildHandler(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []string) error { +func imageBuildHandler(systemDeps NerdctlCommandSystemDeps, _ *config.Finch, _ *string, nerdctlCmdArgs *[]string, _ *string) error { var err error - argLen := len(nerdctlCmdArgs) - 1 + argLen := len(*nerdctlCmdArgs) - 1 // -h/--help don't have buildcontext, just return - for _, a := range nerdctlCmdArgs { + for _, a := range *nerdctlCmdArgs { if a == "--help" || a == "-h" { return nil } } - if nerdctlCmdArgs[argLen] != "--debug" { - nerdctlCmdArgs[argLen], err = convertToWSLPath(systemDeps, nerdctlCmdArgs[argLen]) + if (*nerdctlCmdArgs)[argLen] != "--debug" { + (*nerdctlCmdArgs)[argLen], err = convertToWSLPath(systemDeps, (*nerdctlCmdArgs)[argLen]) if err != nil { return err } } else { - nerdctlCmdArgs[argLen-1], err = convertToWSLPath(systemDeps, nerdctlCmdArgs[argLen-1]) + (*nerdctlCmdArgs)[argLen-1], err = convertToWSLPath(systemDeps, (*nerdctlCmdArgs)[argLen-1]) if err != nil { return err } @@ -336,47 +308,27 @@ func imageBuildHandler(systemDeps NerdctlCommandSystemDeps, nerdctlCmdArgs []str return nil } -var aliasMap = map[string]string{ - "build": "image build", - "save": "image save", - "load": "image load", - "cp": "container cp", - "run": "container run", -} - -var argHandlerMap = map[string]map[string]argHandler{ - "image build": { - "-f": handleFilePath, - "--file": handleFilePath, - "--iidfile": handleFilePath, - "-o": handleOutputOption, - "--output": handleOutputOption, - "--secret": handleSecretOption, - }, - "image save": { - "-o": handleFilePath, - "--output": handleFilePath, - }, - "image load": { - "-i": handleFilePath, - "--input": handleFilePath, - }, - "container run": { - "--label-file": handleFilePath, - "--cosign-key": handleFilePath, - "--cidfile": handleFilePath, - "-v": handleVolume, - "--volume": handleVolume, - "--mount": handleBindMounts, - }, - "compose": { - "--file": handleFilePath, - }, -} +func handleBindMountPath(systemDeps NerdctlCommandSystemDeps, m map[string]string) error { + // Handle src/source path + var k string + path, ok := m["src"] + if !ok { + path, ok = m["source"] + k = "source" + } else { + k = "src" + } + // If there is no src or source or not a windows path, do nothing, let nerdctl handle error + if !ok || !strings.Contains(path, `\`) { + return nil + } + wslPath, err := convertToWSLPath(systemDeps, path) + if err != nil { + return err + } -var commandHandlerMap = map[string]commandHandler{ - "container cp": cpHandler, - "image build": imageBuildHandler, + m[k] = wslPath + return nil } func mapToString(m map[string]string) string { diff --git a/cmd/finch/nerdctl_windows_test.go b/cmd/finch/nerdctl_windows_test.go index e03aac519..e3400541d 100644 --- a/cmd/finch/nerdctl_windows_test.go +++ b/cmd/finch/nerdctl_windows_test.go @@ -51,11 +51,7 @@ func TestNerdctlCommand_runAdaptor(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -116,11 +112,7 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\Users").Return("C:\\Users", nil) @@ -156,12 +148,8 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) logger.EXPECT().SetLevel(flog.Debug) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -192,15 +180,11 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG1") ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("ARG3") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -231,14 +215,10 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("ARG3").Return("val3", true) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -270,14 +250,10 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().SetLevel(flog.Debug) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("ARG3").Return("val3", true) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -311,14 +287,10 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("NOTSETARG") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -352,14 +324,10 @@ func TestNerdctlCommand_run(t *testing.T) { getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().SetLevel(flog.Debug) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2") ncsd.EXPECT().LookupEnv("NOTSETARG") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -392,14 +360,10 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) c := mocks.NewCommand(ctrl) ncsd.EXPECT().LookupEnv("ARG2").Return("val2", true) ncsd.EXPECT().LookupEnv("NOTSETARG") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -453,12 +417,8 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) logger.EXPECT().Debugf(`Resolving special IP "host-gateway" to %q for host %q`, "192.168.5.2", "name") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -490,11 +450,7 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -525,11 +481,7 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -562,12 +514,8 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + AddEmptyEnvLookUps(ncsd) logger.EXPECT().Debugf(`Resolving special IP "host-gateway" to %q for host %q`, "192.168.5.2", "name") - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -598,11 +546,7 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -636,11 +580,7 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil).Times(1) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil).Times(5) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath).Times(3) @@ -672,11 +612,7 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -706,11 +642,7 @@ func TestNerdctlCommand_run(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -745,6 +677,10 @@ func TestNerdctlCommand_run(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -780,6 +716,10 @@ func TestNerdctlCommand_run(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -815,6 +755,10 @@ func TestNerdctlCommand_run(t *testing.T) { ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("test", true) ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -893,11 +837,7 @@ func TestNerdctlCommand_Run_withBindMounts(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil).Times(2) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath).Times(2) @@ -929,11 +869,7 @@ func TestNerdctlCommand_Run_withBindMounts(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil).Times(2) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath).Times(2) @@ -965,11 +901,7 @@ func TestNerdctlCommand_Run_withBindMounts(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil).Times(2) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath).Times(2) @@ -1001,11 +933,7 @@ func TestNerdctlCommand_Run_withBindMounts(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil).Times(1) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath).Times(1) @@ -1037,11 +965,7 @@ func TestNerdctlCommand_Run_withBindMounts(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil).Times(1) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath).Times(1) @@ -1096,11 +1020,7 @@ func TestNerdctlCommand_run_CpCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -1126,11 +1046,7 @@ func TestNerdctlCommand_run_CpCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -1156,11 +1072,7 @@ func TestNerdctlCommand_run_CpCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -1220,11 +1132,7 @@ func TestNerdctlCommand_run_BuildCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -1250,11 +1158,7 @@ func TestNerdctlCommand_run_BuildCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -1280,11 +1184,7 @@ func TestNerdctlCommand_run_BuildCommand(t *testing.T) { ncc.EXPECT().CreateWithoutStdio("ls", "-f", "{{.Status}}", limaInstanceName).Return(getVMStatusC) getVMStatusC.EXPECT().Output().Return([]byte("Running"), nil) logger.EXPECT().Debugf("Status of virtual machine: %s", "Running") - ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) - ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) - ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) - ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + AddEmptyEnvLookUps(ncsd) ncsd.EXPECT().GetWd().Return("C:\\workdir", nil) ncsd.EXPECT().FilePathAbs("C:\\workdir").Return("C:\\workdir", nil) ncsd.EXPECT().FilePathJoin(string(filepath.Separator), "mnt", "c", "workdir").Return(augmentedPath) @@ -1322,3 +1222,15 @@ func TestNerdctlCommand_run_BuildCommand(t *testing.T) { }) } } + +func AddEmptyEnvLookUps(ncsd *mocks.NerdctlCommandSystemDeps) { + ncsd.EXPECT().LookupEnv("AWS_ACCESS_KEY_ID").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_SECRET_ACCESS_KEY").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_SESSION_TOKEN").Return("", false) + ncsd.EXPECT().LookupEnv("COSIGN_PASSWORD").Return("", false) + ncsd.EXPECT().LookupEnv("COMPOSE_FILE").Return("", false) + ncsd.EXPECT().LookupEnv("SOURCE_DATE_EPOCH").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_DISABLE_CACHE").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_CACHE_DIR").Return("", false) + ncsd.EXPECT().LookupEnv("AWS_ECR_IGNORE_CREDS_STORAGE").Return("", false) +} diff --git a/e2e/vm/soci_remote_test.go b/e2e/vm/soci_remote_test.go index 2c3cab3ae..f060bbb00 100644 --- a/e2e/vm/soci_remote_test.go +++ b/e2e/vm/soci_remote_test.go @@ -8,8 +8,6 @@ package vm import ( "fmt" "os" - "os/exec" - "path/filepath" "runtime" "strings" @@ -31,29 +29,15 @@ const ( var testSoci = func(o *option.Option, installed bool) { ginkgo.Describe("SOCI", func() { var limactlO *option.Option - var fpath, realFinchPath, limactlPath, limaHomePathEnv, wd, vmType string + var vmType string var err error var port int ginkgo.BeforeEach(func() { // Find lima paths. limactl is used to shell into the Finch VM and verify // mounted snapshots match the expected SOCI snapshotter behavior. - if installed { - fpath, err = exec.LookPath("finch") - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - realFinchPath, err = filepath.EvalSymlinks(fpath) - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - limactlPath = filepath.Join(realFinchPath, "../../lima/bin/limactl") - limaHomePathEnv = "LIMA_HOME=" + filepath.Join(realFinchPath, "../../lima/data") - } else { - wd, err = os.Getwd() - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - limactlPath = filepath.Join(wd, "../../_output/lima/bin/limactl") - limaHomePathEnv = "LIMA_HOME=" + filepath.Join(wd, "../../_output/lima/data") - } - limactlO, err = option.New([]string{limactlPath}, - option.Env([]string{limaHomePathEnv})) + limactlO, err = limaCtlOpt(installed) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) if runtime.GOOS == "windows" { vmType = "wsl2" diff --git a/e2e/vm/vm_darwin_test.go b/e2e/vm/vm_darwin_test.go index a928c5bec..9354e727d 100644 --- a/e2e/vm/vm_darwin_test.go +++ b/e2e/vm/vm_darwin_test.go @@ -70,6 +70,7 @@ func TestVM(t *testing.T) { testSupportBundle(o) testCredHelper(o, *e2e.Installed, *e2e.Registry) testSoci(o, *e2e.Installed) + testVMNetwork(o, *e2e.Installed) }) gomega.RegisterFailHandler(ginkgo.Fail) diff --git a/e2e/vm/vm_network_test.go b/e2e/vm/vm_network_test.go new file mode 100644 index 000000000..7c41904c3 --- /dev/null +++ b/e2e/vm/vm_network_test.go @@ -0,0 +1,99 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +//go:build darwin + +package vm + +import ( + "context" + "fmt" + "net/http" + "time" + + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + "github.com/onsi/gomega/gbytes" + "github.com/runfinch/common-tests/command" + "github.com/runfinch/common-tests/option" + "golang.org/x/sync/errgroup" +) + +const ( + addr = "localhost" + port = "8888" + responseBody = "ack" + finchHost = "host.finch.internal" + dockerHost = "host.docker.internal" +) + +func hostWithPort(host, port string) string { + return fmt.Sprintf("%s:%s", host, port) +} + +func vmDNSValidationCommand(host, port string) []string { + // The finch rootfs has curl but not wget + return []string{ + "shell", + "finch", + "curl", + "--silent", + "--connect-timeout", "1", + hostWithPort(host, port), + } +} + +func containerDNSValidationCommand(host, port string) []string { + // The container rootfs has wget, but not curl + return []string{ + "run", + "public.ecr.aws/docker/library/alpine:latest", + "wget", + "-O", "-", // output to stdout + "-q", // quiet + "-T", "1", // read timeout + hostWithPort(host, port), + } +} + +func testVMNetwork(finchO *option.Option, installed bool) { + limaCtlO, err := limaCtlOpt(installed) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + eg, _ := errgroup.WithContext(context.Background()) + var srv *http.Server + ginkgo.Describe("vm networking", func() { + ginkgo.BeforeEach(func() { + srv = &http.Server{ + Addr: hostWithPort(addr, port), + ReadHeaderTimeout: 1 * time.Second, + Handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, err := w.Write([]byte(responseBody)) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + }), + } + eg.Go(srv.ListenAndServe) + }) + ginkgo.AfterEach(func() { + err := srv.Shutdown(context.Background()) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + err = eg.Wait() + gomega.Expect(err).To(gomega.MatchError(http.ErrServerClosed)) + }) + ginkgo.It("should resolve host.finch.internal in the vm", func() { + out := command.New(limaCtlO, vmDNSValidationCommand(finchHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out + gomega.Expect(out).To(gbytes.Say(responseBody)) + }) + ginkgo.It("should resolve host.docker.internal in the vm", func() { + out := command.New(limaCtlO, vmDNSValidationCommand(dockerHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out + gomega.Expect(out).To(gbytes.Say(responseBody)) + }) + ginkgo.It("should resolve host.finch.internal in a container", func() { + out := command.New(finchO, containerDNSValidationCommand(finchHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out + gomega.Expect(out).To(gbytes.Say(responseBody)) + }) + ginkgo.It("should resolve host.docker.internal in a container", func() { + out := command.New(finchO, containerDNSValidationCommand(dockerHost, port)...).WithStdout(gbytes.NewBuffer()).Run().Out + gomega.Expect(out).To(gbytes.Say(responseBody)) + }) + }) +} diff --git a/e2e/vm/vm_util_test.go b/e2e/vm/vm_util_test.go new file mode 100644 index 000000000..343d0134e --- /dev/null +++ b/e2e/vm/vm_util_test.go @@ -0,0 +1,38 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +//go:build darwin || windows + +package vm + +import ( + "os" + "os/exec" + "path/filepath" + + "github.com/runfinch/common-tests/option" +) + +func limaCtlOpt(installed bool) (*option.Option, error) { + var limactlPath, limaHomePathEnv string + if installed { + fpath, err := exec.LookPath("finch") + if err != nil { + return nil, err + } + realFinchPath, err := filepath.EvalSymlinks(fpath) + if err != nil { + return nil, err + } + limactlPath = filepath.Join(realFinchPath, "../../lima/bin/limactl") + limaHomePathEnv = "LIMA_HOME=" + filepath.Join(realFinchPath, "../../lima/data") + } else { + wd, err := os.Getwd() + if err != nil { + return nil, err + } + limactlPath = filepath.Join(wd, "../../_output/lima/bin/limactl") + limaHomePathEnv = "LIMA_HOME=" + filepath.Join(wd, "../../_output/lima/data") + } + return option.New([]string{limactlPath}, option.Env([]string{limaHomePathEnv})) +} diff --git a/finch.yaml.d/mac.yaml b/finch.yaml.d/mac.yaml index 3264e38bc..56f80ad35 100644 --- a/finch.yaml.d/mac.yaml +++ b/finch.yaml.d/mac.yaml @@ -39,3 +39,8 @@ firmware: video: display: "none" + +hostResolver: + hosts: + host.finch.internal: host.lima.internal + host.docker.internal: host.lima.internal diff --git a/go.mod b/go.mod index 58b2fb2aa..aab0e39a8 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,12 @@ module github.com/runfinch/finch go 1.22.0 require ( - github.com/aws/aws-sdk-go-v2 v1.31.0 + github.com/aws/aws-sdk-go-v2 v1.32.1 github.com/containerd/cgroups v1.1.0 github.com/containerd/nerdctl/v2 v2.0.0-rc.2 github.com/docker/cli v27.3.1+incompatible github.com/docker/docker v27.3.1+incompatible + github.com/docker/go-connections v0.5.0 github.com/golang/mock v1.6.0 github.com/google/go-licenses v1.6.1-0.20230903011517-706b9c60edd4 github.com/lima-vm/lima v0.23.2 @@ -23,58 +24,109 @@ require ( github.com/stretchr/testify v1.9.0 github.com/tc-hib/go-winres v0.3.3 github.com/xorcare/pointer v1.2.2 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/tools v0.25.0 + golang.org/x/sync v0.8.0 + golang.org/x/tools v0.26.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/apimachinery v0.31.1 ) require ( - github.com/aws/smithy-go v1.21.0 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect + github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Microsoft/hcsshim v0.12.6 // indirect + github.com/aws/smithy-go v1.22.0 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect - github.com/containerd/containerd v1.7.21 // indirect + github.com/containerd/console v1.0.4 // indirect + github.com/containerd/containerd v1.7.22 // indirect + github.com/containerd/containerd/api v1.8.0-rc.3 // indirect github.com/containerd/containerd/v2 v2.0.0-rc.4 // indirect + github.com/containerd/continuity v0.4.3 // indirect github.com/containerd/errdefs v0.1.0 // indirect + github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/go-cni v1.1.10 // indirect + github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f // indirect github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/plugin v0.1.0 // indirect + github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 // indirect + github.com/containerd/ttrpc v1.2.5 // indirect + github.com/containerd/typeurl/v2 v2.2.0 // indirect github.com/containernetworking/cni v1.2.3 // indirect github.com/containernetworking/plugins v1.5.1 // indirect + github.com/containers/ocicrypt v1.2.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect - github.com/docker/go-connections v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/licenseclassifier/v2 v2.0.0 // indirect github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect + github.com/ipfs/go-cid v0.4.1 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/lima-vm/go-qcow2reader v0.1.2 // indirect github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect + github.com/miekg/pkcs11 v1.1.1 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/locker v1.0.1 // indirect + github.com/moby/sys/mountinfo v0.7.2 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/signal v0.7.1 // indirect + github.com/moby/sys/user v0.3.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect + github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect + github.com/opencontainers/selinux v1.11.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/rootless-containers/rootlesskit/v2 v2.3.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect + github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/tc-hib/winres v0.2.1 // indirect github.com/tklauser/go-sysconf v0.3.13 // indirect github.com/tklauser/numcpus v0.7.0 // indirect github.com/urfave/cli/v2 v2.27.4 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect golang.org/x/image v0.18.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/term v0.25.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 // indirect google.golang.org/grpc v1.66.0 // indirect google.golang.org/protobuf v1.34.2 // indirect + lukechampine.com/blake3 v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect + tags.cncf.io/container-device-interface v0.8.0 // indirect + tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect ) require ( @@ -98,9 +150,9 @@ require ( github.com/wk8/go-ordered-map v1.0.0 go.opencensus.io v0.24.0 // indirect golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sys v0.25.0 - golang.org/x/text v0.18.0 + golang.org/x/net v0.30.0 // indirect + golang.org/x/sys v0.26.0 + golang.org/x/text v0.19.0 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 9e499ca59..44ba83d8f 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,19 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/aws/aws-sdk-go-v2 v1.31.0 h1:3V05LbxTSItI5kUqNwhJrrrY1BAXxXt0sN0l72QmG5U= -github.com/aws/aws-sdk-go-v2 v1.31.0/go.mod h1:ztolYtaEUtdpf9Wftr31CJfLVjOnD/CVRkKOOYgF8hA= -github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA= -github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/hcsshim v0.12.6 h1:qEnZjoHXv+4/s0LmKZWE0/AiZmMWEIkFfWBSf1a0wlU= +github.com/Microsoft/hcsshim v0.12.6/go.mod h1:ZABCLVcvLMjIkzr9rUGcQ1QA0p0P3Ps+d3N1g2DsFfk= +github.com/aws/aws-sdk-go-v2 v1.32.1 h1:8WuZ43ytA+TV6QEPT/R23mr7pWyI7bSSiEHdt9BS2Pw= +github.com/aws/aws-sdk-go-v2 v1.32.1/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -11,24 +21,44 @@ github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaD github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= -github.com/containerd/containerd v1.7.21 h1:USGXRK1eOC/SX0L195YgxTHb0a00anxajOzgfN0qrCA= -github.com/containerd/containerd v1.7.21/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= +github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= +github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= +github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= +github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= +github.com/containerd/containerd/api v1.8.0-rc.3 h1:q9MyeXmuAGEyKmUGYvvFftNX1RQhfTLsAvYK+SQHQso= +github.com/containerd/containerd/api v1.8.0-rc.3/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/v2 v2.0.0-rc.4 h1:Bvto4h5i2VZkQ+L5SrGupg5ilQ+zkVPILdjf9RWMego= github.com/containerd/containerd/v2 v2.0.0-rc.4/go.mod h1:p35nJi4Pl9ibzuoVOPc3MputVh6Gbp9xoDg9VHz6/YI= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= +github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= +github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= github.com/containerd/go-cni v1.1.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCyhyg= github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= +github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f h1:VuW2PlwpES6W86asOw+ysYEpARdlPkwpM6DsT4sbv8U= +github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f/go.mod h1:F9roK2DzKlFnV+h+ZJy/r2FoS28bIvxKgdcoV7o8Sms= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/nerdctl/v2 v2.0.0-rc.2 h1:/qXcykFatPTmlZsiMeciNFSI2GMCl9L9O3cVX5RiJzk= github.com/containerd/nerdctl/v2 v2.0.0-rc.2/go.mod h1:YCsPFv2UE0yLp7uedz+FnXrfnilnRJ7TwFi9Pi7iZss= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/containerd/plugin v0.1.0 h1:CYMyZk9beRAIe1FEKItbMLLAz/z16aXrGc+B+nv0fU4= github.com/containerd/plugin v0.1.0/go.mod h1:j6HlpMtkiZMgT4UsfVNxPBUkwdw9KQGU6nCLfRxnq+w= +github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 h1:Td/dlhRp/kIk9W1rjXHSL87zZZiBQaKPV18OnoEREUA= +github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:dgo5lVziOOnWX8SxxHqYuc8ShsQou54eKLdahxFlHVc= +github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= +github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= +github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= +github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= +github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -39,6 +69,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= @@ -55,8 +87,17 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -91,6 +132,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -98,6 +141,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-licenses v1.6.1-0.20230903011517-706b9c60edd4 h1:2cF5oCuHDHTsC1S1eePsrHKGs1Co9Q6XOc8nhysGer4= @@ -111,10 +155,22 @@ github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3 github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -137,10 +193,38 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= +github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= +github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= @@ -151,8 +235,14 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= +github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= +github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= @@ -161,6 +251,8 @@ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2D github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= @@ -171,6 +263,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rootless-containers/rootlesskit/v2 v2.3.1 h1:wdYtdKxWFvVLby9ThMP6O6/v2q/GmOXbkRi+4m9nPW0= @@ -188,19 +282,26 @@ github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af h1:Sp5TG9f7K39yfB+If0vjp97vuT74F72r8hfRpP8jLU0= github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= +github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -209,6 +310,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tc-hib/go-winres v0.3.3 h1:DQ50qlvDVhqrDOY0svTxZFZWfKWtZtfnXXHPCw6lqh0= github.com/tc-hib/go-winres v0.3.3/go.mod h1:5NGzOtuvjSqnpIEi2o1h48MKZzP9olvrf+PeY2t1uoA= github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= @@ -217,12 +320,20 @@ github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08 github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= +github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wk8/go-ordered-map v1.0.0 h1:BV7z+2PaK8LTSd/mWgY12HyMAo5CEgkHqbkVq2thqr8= github.com/wk8/go-ordered-map v1.0.0/go.mod h1:9ZIbRunKbuvfPKyBP1SIKLcXNlv74YCOZ3t3VTS6gRk= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xorcare/pointer v1.2.2 h1:zjD77b5DTehClND4MK+9dDE0DcpFIZisAJ/+yVJvKYA= github.com/xorcare/pointer v1.2.2/go.mod h1:azsKh7oVwYB7C1o8P284fG8MvtErX/F5/dqXiaj71ak= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= @@ -233,15 +344,25 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= +go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -269,8 +390,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -285,6 +406,8 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -296,20 +419,21 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -320,8 +444,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -371,3 +495,11 @@ k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= +lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc= +tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y= +tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA= +tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws= diff --git a/pkg/config/config.go b/pkg/config/config.go index a479d9431..ceff93ea4 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -38,6 +38,7 @@ type SharedSystemSettings struct { type SharedSettings struct { Snapshotters []string `yaml:"snapshotters,omitempty"` CredsHelpers []string `yaml:"creds_helpers,omitempty"` + DockerCompat bool `yaml:"dockercompat,omitempty"` } // Nerdctl is a copy from github.com/containerd/nerdctl/cmd/nerdctl/main.go diff --git a/pkg/mocks/nerdctl_cmd_system_deps.go b/pkg/mocks/nerdctl_cmd_system_deps.go index 1fc2d540b..d55ebf882 100644 --- a/pkg/mocks/nerdctl_cmd_system_deps.go +++ b/pkg/mocks/nerdctl_cmd_system_deps.go @@ -36,6 +36,20 @@ func (m *NerdctlCommandSystemDeps) EXPECT() *NerdctlCommandSystemDepsMockRecorde return m.recorder } +// Env mocks base method. +func (m *NerdctlCommandSystemDeps) Env(key string) string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Env", key) + ret0, _ := ret[0].(string) + return ret0 +} + +// Env indicates an expected call of Env. +func (mr *NerdctlCommandSystemDepsMockRecorder) Env(key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Env", reflect.TypeOf((*NerdctlCommandSystemDeps)(nil).Env), key) +} + // FilePathAbs mocks base method. func (m *NerdctlCommandSystemDeps) FilePathAbs(elem string) (string, error) { m.ctrl.T.Helper() diff --git a/pkg/mocks/pkg_support.go b/pkg/mocks/pkg_support.go new file mode 100644 index 000000000..495a7d3ee --- /dev/null +++ b/pkg/mocks/pkg_support.go @@ -0,0 +1,52 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/runfinch/finch/pkg/support (interfaces: SystemDeps) + +// Package mocks is a generated GoMock package. +package mocks + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// SupportSystemDeps is a mock of SystemDeps interface. +type SupportSystemDeps struct { + ctrl *gomock.Controller + recorder *SupportSystemDepsMockRecorder +} + +// SupportSystemDepsMockRecorder is the mock recorder for SupportSystemDeps. +type SupportSystemDepsMockRecorder struct { + mock *SupportSystemDeps +} + +// NewSupportSystemDeps creates a new mock instance. +func NewSupportSystemDeps(ctrl *gomock.Controller) *SupportSystemDeps { + mock := &SupportSystemDeps{ctrl: ctrl} + mock.recorder = &SupportSystemDepsMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *SupportSystemDeps) EXPECT() *SupportSystemDepsMockRecorder { + return m.recorder +} + +// Executable mocks base method. +func (m *SupportSystemDeps) Executable() (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Executable") + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Executable indicates an expected call of Executable. +func (mr *SupportSystemDepsMockRecorder) Executable() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Executable", reflect.TypeOf((*SupportSystemDeps)(nil).Executable)) +} diff --git a/pkg/support/support.go b/pkg/support/support.go index 4219dd79c..c98378867 100644 --- a/pkg/support/support.go +++ b/pkg/support/support.go @@ -31,6 +31,7 @@ import ( const ( bundlePrefix = "finch-support" platformFileName = "platform.yaml" + versionFileName = "version-output.txt" logPrefix = "logs" configPrefix = "configs" additionalPrefix = "misc" @@ -48,14 +49,22 @@ type BundleBuilder interface { GenerateSupportBundle([]string, []string) (string, error) } +// SystemDeps provides methods to get system dependencies. +// +//go:generate mockgen -copyright_file=../../copyright_header -destination=../mocks/pkg_support.go -package=mocks -mock_names SystemDeps=SupportSystemDeps . SystemDeps +type SystemDeps interface { + system.ExecutableFinder +} + type bundleBuilder struct { - logger flog.Logger - fs afero.Fs - config BundleConfig - finch fpath.Finch - ecc command.Creator - ncc command.NerdctlCmdCreator - lima wrapper.LimaWrapper + logger flog.Logger + fs afero.Fs + config BundleConfig + finch fpath.Finch + ecc command.Creator + ncc command.NerdctlCmdCreator + lima wrapper.LimaWrapper + systemDeps SystemDeps } // NewBundleBuilder produces a new BundleBuilder. @@ -67,15 +76,17 @@ func NewBundleBuilder( ecc command.Creator, ncc command.NerdctlCmdCreator, lima wrapper.LimaWrapper, + systemDeps SystemDeps, ) BundleBuilder { return &bundleBuilder{ - logger: logger, - fs: fs, - config: config, - finch: finch, - ecc: ecc, - ncc: ncc, - lima: lima, + logger: logger, + fs: fs, + config: config, + finch: finch, + ecc: ecc, + ncc: ncc, + lima: lima, + systemDeps: systemDeps, } } @@ -108,6 +119,13 @@ func (bb *bundleBuilder) GenerateSupportBundle(additionalFiles []string, exclude return "", err } + bb.logger.Debugln("Collecting finch version output...") + version := bb.getFinchVersion() + err = writeVersionOutput(writer, version, zipPrefix) + if err != nil { + return "", err + } + bb.logger.Debugln("Copying in log files...") for _, file := range bb.config.LogFiles() { if fileShouldBeExcluded(file, excludeFiles) { @@ -320,6 +338,21 @@ func getFinchVersion() string { return version.Version } +func (bb *bundleBuilder) getFinchVersion() string { + // get current finch executable + executable, err := bb.systemDeps.Executable() + if err != nil { + return "" + } + cmd := bb.ecc.Create(executable, "version") + out, err := cmd.Output() + if err != nil { + return "" + } + output := string(out) + return output +} + func writePlatformData(writer *zip.Writer, platform *PlatformData, prefix string) error { platformFile, err := writer.Create(path.Join(prefix, platformFileName)) if err != nil { @@ -371,3 +404,17 @@ func fileShouldBeExcluded(filename string, exclude []string) bool { func isFileFromVM(filename string) bool { return strings.HasPrefix(filename, "vm:") } + +func writeVersionOutput(writer *zip.Writer, version, prefix string) error { + versionFile, err := writer.Create(path.Join(prefix, versionFileName)) + if err != nil { + return err + } + + _, err = versionFile.Write([]byte(version)) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/support/support_test.go b/pkg/support/support_test.go index b5e27b2bb..38f80ea35 100644 --- a/pkg/support/support_test.go +++ b/pkg/support/support_test.go @@ -30,9 +30,10 @@ func TestSupport_NewBundleBuilder(t *testing.T) { fs := afero.NewMemMapFs() finch := fpath.Finch("mockfinch") lima := mocks.NewMockLimaWrapper(ctrl) + systemDeps := mocks.NewSupportSystemDeps(ctrl) config := NewBundleConfig(finch, "mockhome") - NewBundleBuilder(logger, fs, config, finch, ecc, ncc, lima) + NewBundleBuilder(logger, fs, config, finch, ecc, ncc, lima, systemDeps) } func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { @@ -51,6 +52,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { *mocks.NerdctlCmdCreator, *mocks.Command, *mocks.MockLimaWrapper, + *mocks.SupportSystemDeps, afero.Fs, ) include []string @@ -67,6 +69,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { _ *mocks.NerdctlCmdCreator, cmd *mocks.Command, lima *mocks.MockLimaWrapper, + systemDeps *mocks.SupportSystemDeps, _ afero.Fs, ) { logger.EXPECT().Debugf("Creating %s...", gomock.Any()) @@ -83,7 +86,11 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { cmd = nil } - cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil) + cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil).AnyTimes() + + logger.EXPECT().Debugln("Collecting finch version output...") + systemDeps.EXPECT().Executable().Return("/bin/path", nil) + ecc.EXPECT().Create("/bin/path", "version").Return(cmd) config.EXPECT().LogFiles().Return([]string{ "log1", @@ -117,6 +124,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { _ *mocks.NerdctlCmdCreator, cmd *mocks.Command, lima *mocks.MockLimaWrapper, + systemDeps *mocks.SupportSystemDeps, _ afero.Fs, ) { logger.EXPECT().Debugf("Creating %s...", gomock.Any()) @@ -133,7 +141,11 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { cmd = nil } - cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil) + cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil).AnyTimes() + + logger.EXPECT().Debugln("Collecting finch version output...") + systemDeps.EXPECT().Executable().Return("/bin/path", nil) + ecc.EXPECT().Create("/bin/path", "version").Return(cmd) config.EXPECT().LogFiles().Return([]string{ "log1", @@ -164,6 +176,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { _ *mocks.NerdctlCmdCreator, cmd *mocks.Command, lima *mocks.MockLimaWrapper, + systemDeps *mocks.SupportSystemDeps, _ afero.Fs, ) { logger.EXPECT().Debugf("Creating %s...", gomock.Any()) @@ -180,7 +193,11 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { cmd = nil } - cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil) + cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil).AnyTimes() + + logger.EXPECT().Debugln("Collecting finch version output...") + systemDeps.EXPECT().Executable().Return("/bin/path", nil) + ecc.EXPECT().Create("/bin/path", "version").Return(cmd) config.EXPECT().LogFiles().Return([]string{ "log1", @@ -210,6 +227,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { _ *mocks.NerdctlCmdCreator, cmd *mocks.Command, lima *mocks.MockLimaWrapper, + systemDeps *mocks.SupportSystemDeps, _ afero.Fs, ) { logger.EXPECT().Debugf("Creating %s...", gomock.Any()) @@ -226,7 +244,11 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { cmd = nil } - cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil) + cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil).AnyTimes() + + logger.EXPECT().Debugln("Collecting finch version output...") + systemDeps.EXPECT().Executable().Return("/bin/path", nil) + ecc.EXPECT().Create("/bin/path", "version").Return(cmd) config.EXPECT().LogFiles().Return([]string{ "log1", @@ -256,6 +278,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { _ *mocks.NerdctlCmdCreator, cmd *mocks.Command, lima *mocks.MockLimaWrapper, + systemDeps *mocks.SupportSystemDeps, _ afero.Fs, ) { logger.EXPECT().Debugf("Creating %s...", gomock.Any()) @@ -272,7 +295,11 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { cmd = nil } - cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil) + cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil).AnyTimes() + + logger.EXPECT().Debugln("Collecting finch version output...") + systemDeps.EXPECT().Executable().Return("/bin/path", nil) + ecc.EXPECT().Create("/bin/path", "version").Return(cmd) config.EXPECT().LogFiles().Return([]string{ "log1", @@ -306,6 +333,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { ncc *mocks.NerdctlCmdCreator, cmd *mocks.Command, lima *mocks.MockLimaWrapper, + systemDeps *mocks.SupportSystemDeps, _ afero.Fs, ) { logger.EXPECT().Debugf("Creating %s...", gomock.Any()) @@ -322,7 +350,11 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { cmd = nil } - cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil) + cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil).AnyTimes() + + logger.EXPECT().Debugln("Collecting finch version output...") + systemDeps.EXPECT().Executable().Return("/bin/path", nil) + ecc.EXPECT().Create("/bin/path", "version").Return(cmd) config.EXPECT().LogFiles().Return([]string{ "log1", @@ -375,6 +407,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { _ *mocks.NerdctlCmdCreator, cmd *mocks.Command, lima *mocks.MockLimaWrapper, + systemDeps *mocks.SupportSystemDeps, _ afero.Fs, ) { logger.EXPECT().Debugf("Creating %s...", gomock.Any()) @@ -391,7 +424,11 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { cmd = nil } - cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil) + cmd.EXPECT().Output().Return([]byte("1.2.3\n"), nil).AnyTimes() + + logger.EXPECT().Debugln("Collecting finch version output...") + systemDeps.EXPECT().Executable().Return("/bin/path", nil) + ecc.EXPECT().Create("/bin/path", "version").Return(cmd) config.EXPECT().LogFiles().Return([]string{ "log1", @@ -437,15 +474,17 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { ncc := mocks.NewNerdctlCmdCreator(ctrl) lima := mocks.NewMockLimaWrapper(ctrl) cmd := mocks.NewCommand(ctrl) + systemDeps := mocks.NewSupportSystemDeps(ctrl) builder := &bundleBuilder{ - logger: logger, - fs: fs, - config: config, - finch: finch, - ecc: ecc, - ncc: ncc, - lima: lima, + logger: logger, + fs: fs, + config: config, + finch: finch, + ecc: ecc, + ncc: ncc, + lima: lima, + systemDeps: systemDeps, } testFiles := []string{ @@ -465,7 +504,7 @@ func TestSupportBundleBuilder_GenerateSupportBundle(t *testing.T) { require.NoError(t, err) } - tc.mockSvc(logger, config, ecc, ncc, cmd, lima, fs) + tc.mockSvc(logger, config, ecc, ncc, cmd, lima, systemDeps, fs) zipFile, err := builder.GenerateSupportBundle(tc.include, tc.exclude) assert.NoError(t, err) @@ -593,3 +632,100 @@ func TestSupport_fileShouldBeExcluded(t *testing.T) { }) } } + +func TestSupport_writeVersionOutput(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + versionOutput string + prefix string + expectedPath string + expectedContent string + expectError bool + }{ + { + name: "Write version output successfully", + versionOutput: "1.2.3", + prefix: "test_prefix", + expectedPath: "test_prefix/version-output.txt", + expectedContent: "1.2.3", + expectError: false, + }, + { + name: "Write version output with empty prefix", + versionOutput: "1.2.3", + prefix: "", + expectedPath: "version-output.txt", + expectedContent: "1.2.3", + expectError: false, + }, + { + name: "Write empty output", + versionOutput: "", + prefix: "empty_version", + expectedPath: "empty_version/version-output.txt", + expectedContent: "", + expectError: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + fs := afero.NewMemMapFs() + + file, err := fs.Create("testFile") + require.NoError(t, err) + + writer := zip.NewWriter(file) + + err = writeVersionOutput(writer, tc.versionOutput, tc.prefix) + + // Check if we expected an error + if tc.expectError { + assert.Error(t, err) + return + } + assert.NoError(t, err) + + err = writer.Close() + assert.NoError(t, err) + + err = file.Close() + assert.NoError(t, err) + + // Open the zip archive for reading + readFile, err := fs.Open("testFile") + require.NoError(t, err) + defer readFile.Close() //nolint:errcheck // closing the file + + fileInfo, err := readFile.Stat() + require.NoError(t, err) + + reader, err := zip.NewReader(readFile, fileInfo.Size()) + require.NoError(t, err) + + // Check if the file exists in the zip + var found bool + for _, f := range reader.File { + if f.Name == tc.expectedPath { + found = true + rc, err := f.Open() + require.NoError(t, err) + defer rc.Close() //nolint:errcheck // closing the file + + content, err := io.ReadAll(rc) + require.NoError(t, err) + + // Check the file content + assert.Equal(t, tc.expectedContent, string(content)) + break + } + } + assert.True(t, found, "Expected file not found in zip archive") + }) + } +}