diff --git a/.github/workflows/dockerd.yml b/.github/workflows/dockerd.yml new file mode 100644 index 000000000000..04ece8563be4 --- /dev/null +++ b/.github/workflows/dockerd.yml @@ -0,0 +1,139 @@ +name: dockerd + +on: + # TODO: add event to build on command in PR (e.g., /test-dockerd) + workflow_dispatch: + inputs: + version: + description: 'Docker version' + required: true + default: '20.10.13' + +env: + REPO_SLUG_ORIGIN: "moby/buildkit:latest" + CACHE_GHA_SCOPE_IT: "integration-tests" + CACHE_GHA_SCOPE_BINARIES: "binaries" + +jobs: + prepare: + runs-on: ubuntu-latest + steps: + - + name: Check version + run: | + version=${{ github.event.inputs.version }} + if [ -z "$version" ]; then + version=20.10.13 + fi + echo "DOCKER_VERSION=$version" >> $GITHUB_ENV + - + name: Check build + uses: actions/github-script@v6 + id: build + with: + result-encoding: string + script: | + try { + new URL("${{ env.DOCKER_VERSION }}"); + } catch (e) { + return false; + } + return true; + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + with: + driver-opts: image=${{ env.REPO_SLUG_ORIGIN }} + buildkitd-flags: --debug + - + name: Build + if: steps.build.outputs.result == 'true' + uses: docker/build-push-action@v2 + with: + context: ${{ env.DOCKER_VERSION }} + target: binary + outputs: /tmp/moby + - + # FIXME: remove symlink and rename bin. should be fixed upstream on moby. + name: Rename binary + if: steps.build.outputs.result == 'true' + run: | + rm /tmp/moby/binary-daemon/dockerd + mv /tmp/moby/binary-daemon/dockerd-dev /tmp/moby/binary-daemon/dockerd + - + name: Download + if: steps.build.outputs.result != 'true' + run: | + mkdir -p /tmp/moby/binary-daemon + cd /tmp/moby/binary-daemon + wget -qO- "https://download.docker.com/linux/static/stable/x86_64/docker-${{ env.DOCKER_VERSION }}.tgz" | tar xvz --strip 1 + - + name: Upload dockerd + uses: actions/upload-artifact@v2 + with: + name: dockerd + path: /tmp/moby/binary-daemon/dockerd + if-no-files-found: error + + test: + runs-on: ubuntu-latest + needs: + - prepare + strategy: + fail-fast: false + matrix: + pkg: + - ./client + - ./cmd/buildctl + - ./solver + - ./frontend + - ./frontend/dockerfile + typ: + - integration + include: + - pkg: ./... + skip-integration-tests: 1 + steps: + - + name: Checkout + uses: actions/checkout@v2 + - + name: Expose GitHub Runtime + uses: crazy-max/ghaction-github-runtime@v1 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + with: + driver-opts: image=${{ env.REPO_SLUG_ORIGIN }} + buildkitd-flags: --debug + - + name: Download dockerd + uses: actions/download-artifact@v2 + with: + name: dockerd + path: ./build/ + - + name: Fix dockerd perms + run: | + chmod +x ./build/dockerd + - + name: Update daemon.json + run: | + sudo rm /etc/docker/daemon.json + sudo service docker restart + docker version + docker info + - + name: Test + run: | + ./hack/test ${{ matrix.typ }} + env: + TEST_DOCKERD: "1" + TEST_DOCKERD_BINARY: "./build/dockerd" + TESTPKGS: "${{ matrix.pkg }}" + TESTFLAGS: "-v --parallel=1 --timeout=30m --run=//worker=dockerd$" + SKIP_INTEGRATION_TESTS: "${{ matrix.skip-integration-tests }}" + CACHE_FROM: "type=gha,scope=${{ env.CACHE_GHA_SCOPE_IT }} type=gha,scope=${{ env.CACHE_GHA_SCOPE_BINARIES }}" diff --git a/client/build_test.go b/client/build_test.go index 58fa5f4684cb..23642de80f60 100644 --- a/client/build_test.go +++ b/client/build_test.go @@ -1650,7 +1650,7 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox } allowedEntitlements = []entitlements.Entitlement{} } else { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb) assertCaps = func(caps uint64) { /* $ capsh --decode=0000003fffffffff diff --git a/client/client_test.go b/client/client_test.go index cda4e58c59e4..425fbeb667df 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -57,7 +57,7 @@ import ( ) func init() { - if os.Getenv("TEST_DOCKERD") == "1" { + if integration.IsTestDockerd() { integration.InitDockerdWorker() } else { integration.InitOCIWorker() @@ -194,6 +194,7 @@ func newContainerd(cdAddress string) (*containerd.Client, error) { // moby/buildkit#1336 func testCacheExportCacheKeyLoop(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "remote cache export") c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) defer c.Close() @@ -706,7 +707,7 @@ func testNetworkMode(t *testing.T, sb integration.Sandbox) { } func testPushByDigest(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "direct push") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -767,7 +768,7 @@ func testSecurityMode(t *testing.T, sb integration.Sandbox) { } allowedEntitlements = []entitlements.Entitlement{} } else { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb) assertCaps = func(caps uint64) { /* $ capsh --decode=0000003fffffffff @@ -834,7 +835,7 @@ func testSecurityModeSysfs(t *testing.T, sb integration.Sandbox) { if secMode == securitySandbox { allowedEntitlements = []entitlements.Entitlement{} } else { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb) mode = llb.SecurityModeInsecure allowedEntitlements = []entitlements.Entitlement{entitlements.EntitlementSecurityInsecure} } @@ -896,7 +897,7 @@ func testSecurityModeErrors(t *testing.T, sb integration.Sandbox) { } func testFrontendImageNaming(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "oci exporter", "direct push") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -1893,7 +1894,7 @@ func testUser(t *testing.T, sb integration.Sandbox) { } func testOCIExporter(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "oci exporter") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -1996,7 +1997,6 @@ func testOCIExporter(t *testing.T, sb integration.Sandbox) { } func testFrontendMetadataReturn(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2010,14 +2010,24 @@ func testFrontendMetadataReturn(t *testing.T, sb integration.Sandbox) { return res, nil } - res, err := c.Build(sb.Context(), SolveOpt{ - Exports: []ExportEntry{ - { - Type: ExporterOCI, - Attrs: map[string]string{}, - Output: fixedWriteCloser(nopWriteCloser{ioutil.Discard}), + var exports []ExportEntry + if integration.IsTestDockerd() { + exports = []ExportEntry{{ + Type: "moby", + Attrs: map[string]string{ + "name": "reg.dummy:5000/buildkit/test:latest", }, - }, + }} + } else { + exports = []ExportEntry{{ + Type: ExporterOCI, + Attrs: map[string]string{}, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }} + } + + res, err := c.Build(sb.Context(), SolveOpt{ + Exports: exports, }, "", frontend, nil) require.NoError(t, err) require.Contains(t, res.ExporterResponse, "frontend.returned") @@ -2093,16 +2103,8 @@ func testFrontendUseSolveResults(t *testing.T, sb integration.Sandbox) { require.Equal(t, dt, []byte("data")) } -func skipDockerd(t *testing.T, sb integration.Sandbox) { - // TODO: remove me once dockerd supports the image and exporter. - t.Helper() - if os.Getenv("TEST_DOCKERD") == "1" { - t.Skip("dockerd missing a required exporter, cache exporter, or entitlement") - } -} - func testExporterTargetExists(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "oci exporter") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2135,10 +2137,6 @@ func testExporterTargetExists(t *testing.T, sb integration.Sandbox) { } func testTarExporterWithSocket(t *testing.T, sb integration.Sandbox) { - if os.Getenv("TEST_DOCKERD") == "1" { - t.Skip("tar exporter is temporarily broken on dockerd") - } - requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2163,10 +2161,6 @@ func testTarExporterWithSocket(t *testing.T, sb integration.Sandbox) { } func testTarExporterWithSocketCopy(t *testing.T, sb integration.Sandbox) { - if os.Getenv("TEST_DOCKERD") == "1" { - t.Skip("tar exporter is temporarily broken on dockerd") - } - requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2231,9 +2225,7 @@ func testTarExporterSymlink(t *testing.T, sb integration.Sandbox) { } func testBuildExportWithForeignLayer(t *testing.T, sb integration.Sandbox) { - if os.Getenv("TEST_DOCKERD") == "1" { - t.Skip("image exporter is missing in dockerd") - } + integration.SkipIfDockerd(t, sb, "image exporter") c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2341,9 +2333,8 @@ func testBuildExportWithForeignLayer(t *testing.T, sb integration.Sandbox) { } func testBuildExportWithUncompressed(t *testing.T, sb integration.Sandbox) { - if os.Getenv("TEST_DOCKERD") == "1" { - t.Skip("image exporter is missing in dockerd") - } + integration.SkipIfDockerd(t, sb, "image exporter") + requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2534,6 +2525,7 @@ func testBuildExportWithUncompressed(t *testing.T, sb integration.Sandbox) { } func testBuildExportZstd(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "oci export") c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) defer c.Close() @@ -2631,6 +2623,7 @@ func testBuildExportZstd(t *testing.T, sb integration.Sandbox) { } func testPullZstdImage(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "direct push") c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) defer c.Close() @@ -2700,7 +2693,7 @@ func testPullZstdImage(t *testing.T, sb integration.Sandbox) { require.Equal(t, dt, []byte("zstd")) } func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "direct push") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -2900,7 +2893,7 @@ func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) { } func testStargzLazyRegistryCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") requiresLinux(t) cdAddress := sb.ContainerdAddress() @@ -3048,7 +3041,7 @@ func testStargzLazyRegistryCacheImportExport(t *testing.T, sb integration.Sandbo } func testStargzLazyInlineCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") requiresLinux(t) cdAddress := sb.ContainerdAddress() @@ -3201,7 +3194,6 @@ func testStargzLazyInlineCacheImportExport(t *testing.T, sb integration.Sandbox) } func testStargzLazyPull(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) requiresLinux(t) cdAddress := sb.ContainerdAddress() @@ -3326,7 +3318,7 @@ func testStargzLazyPull(t *testing.T, sb integration.Sandbox) { } func testLazyImagePush(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "direct push") requiresLinux(t) cdAddress := sb.ContainerdAddress() @@ -3460,6 +3452,7 @@ func testLazyImagePush(t *testing.T, sb integration.Sandbox) { } func testZstdLocalCacheExport(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "remote cache export") c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) defer c.Close() @@ -3523,7 +3516,7 @@ func testZstdLocalCacheExport(t *testing.T, sb integration.Sandbox) { } func testUncompressedLocalCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") dir, err := ioutil.TempDir("", "buildkit") require.NoError(t, err) defer os.RemoveAll(dir) @@ -3545,7 +3538,7 @@ func testUncompressedLocalCacheImportExport(t *testing.T, sb integration.Sandbox } func testUncompressedRegistryCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { t.Skip(err.Error()) @@ -3570,7 +3563,7 @@ func testUncompressedRegistryCacheImportExport(t *testing.T, sb integration.Sand } func testZstdLocalCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") if sb.Name() == "containerd-1.4" { // containerd 1.4 doesn't support zstd compression return @@ -3597,7 +3590,7 @@ func testZstdLocalCacheImportExport(t *testing.T, sb integration.Sandbox) { } func testZstdRegistryCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") if sb.Name() == "containerd-1.4" { // containerd 1.4 doesn't support zstd compression return @@ -3693,7 +3686,7 @@ func testBasicCacheImportExport(t *testing.T, sb integration.Sandbox, cacheOptio } func testBasicRegistryCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { t.Skip(err.Error()) @@ -3710,7 +3703,7 @@ func testBasicRegistryCacheImportExport(t *testing.T, sb integration.Sandbox) { } func testMultipleRegistryCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { t.Skip(err.Error()) @@ -3733,7 +3726,7 @@ func testMultipleRegistryCacheImportExport(t *testing.T, sb integration.Sandbox) } func testBasicLocalCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") dir, err := ioutil.TempDir("", "buildkit") require.NoError(t, err) defer os.RemoveAll(dir) @@ -3753,7 +3746,7 @@ func testBasicLocalCacheImportExport(t *testing.T, sb integration.Sandbox) { } func testBasicInlineCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "direct push") requiresLinux(t) registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { @@ -4196,7 +4189,7 @@ func testCopyFromEmptyImage(t *testing.T, sb integration.Sandbox) { // containerd/containerd#2119 func testDuplicateWhiteouts(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "oci exporter") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -4268,7 +4261,7 @@ func testDuplicateWhiteouts(t *testing.T, sb integration.Sandbox) { // #276 func testWhiteoutParentDir(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "oci exporter") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) @@ -4335,6 +4328,7 @@ func testWhiteoutParentDir(t *testing.T, sb integration.Sandbox) { // #2490 func testMoveParentDir(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "oci export") c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) defer c.Close() @@ -4709,7 +4703,7 @@ func testMergeOp(t *testing.T, sb integration.Sandbox) { } var imageTarget string - if os.Getenv("TEST_DOCKERD") == "1" { + if integration.IsTestDockerd() { // do image export but use a fake url as the image should just end up in moby's // local store imageTarget = "fake.invalid:33333/buildkit/testmergeop:latest" @@ -4808,7 +4802,7 @@ func testMergeOpCacheMax(t *testing.T, sb integration.Sandbox) { func testMergeOpCache(t *testing.T, sb integration.Sandbox, mode string) { t.Helper() - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "direct push") requiresLinux(t) cdAddress := sb.ContainerdAddress() @@ -5197,7 +5191,7 @@ func requireContents(ctx context.Context, t *testing.T, c *Client, sb integratio if imageTarget != "" { var exports []ExportEntry - if os.Getenv("TEST_DOCKERD") == "1" { + if integration.IsTestDockerd() { exports = []ExportEntry{{ Type: "moby", Attrs: map[string]string{ @@ -5567,22 +5561,24 @@ func testBuildInfoExporter(t *testing.T, sb integration.Sandbox) { }) } - registry, err := sb.NewRegistry() - if errors.Is(err, integration.ErrRequirements) { - t.Skip(err.Error()) + var exports []ExportEntry + if integration.IsTestDockerd() { + exports = []ExportEntry{{ + Type: "moby", + Attrs: map[string]string{ + "name": "reg.dummy:5000/buildkit/test:latest", + }, + }} + } else { + exports = []ExportEntry{{ + Type: ExporterOCI, + Attrs: map[string]string{}, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }} } - require.NoError(t, err) res, err := c.Build(sb.Context(), SolveOpt{ - Exports: []ExportEntry{ - { - Type: ExporterImage, - Attrs: map[string]string{ - "name": registry + "/buildkit/test-buildinfo:latest", - "push": "true", - }, - }, - }, + Exports: exports, }, "", frontend, nil) require.NoError(t, err) @@ -5603,6 +5599,7 @@ func testBuildInfoExporter(t *testing.T, sb integration.Sandbox) { // moby/buildkit#2476 func testBuildInfoInline(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "direct push") requiresLinux(t) c, err := New(sb.Context(), sb.Address()) require.NoError(t, err) diff --git a/client/mergediff_test.go b/client/mergediff_test.go index da1d12d42f55..83e97f0c5ac0 100644 --- a/client/mergediff_test.go +++ b/client/mergediff_test.go @@ -3,7 +3,6 @@ package client import ( "context" "fmt" - "os" "strings" "testing" @@ -1192,6 +1191,13 @@ func (tc verifyContents) Run(t *testing.T, sb integration.Sandbox) { t.Skip("rootless") } + // FIXME: TestDiffUpperScratch broken on dockerd and seems flaky with containerd. + // see https://github.com/moby/buildkit/pull/2726#issuecomment-1070978499 + // and https://github.com/moby/buildkit/pull/2725#issuecomment-1066521712 + if integration.IsTestDockerd() && tc.name == "TestDiffUpperScratch" { + t.Skip("TestDiffUpperScratch is temporarily broken on dockerd") + } + requiresLinux(t) cdAddress := sb.ContainerdAddress() @@ -1218,7 +1224,7 @@ func (tc verifyContents) Run(t *testing.T, sb integration.Sandbox) { var exportInlineCacheOpts []CacheOptionsEntry var importRegistryCacheOpts []CacheOptionsEntry var exportRegistryCacheOpts []CacheOptionsEntry - if os.Getenv("TEST_DOCKERD") != "1" { + if !integration.IsTestDockerd() { importInlineCacheOpts = []CacheOptionsEntry{{ Type: "registry", Attrs: map[string]string{ @@ -1245,7 +1251,7 @@ func (tc verifyContents) Run(t *testing.T, sb integration.Sandbox) { resetState(t, c, sb) requireContents(ctx, t, c, sb, tc.state, nil, exportInlineCacheOpts, imageTarget, tc.contents(sb)) - if os.Getenv("TEST_DOCKERD") == "1" { + if integration.IsTestDockerd() { return } @@ -1310,7 +1316,6 @@ func (tc verifyBlobReuse) Name() string { } func (tc verifyBlobReuse) Run(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) requiresLinux(t) cdAddress := sb.ContainerdAddress() diff --git a/frontend/dockerfile/dockerfile_buildinfo_test.go b/frontend/dockerfile/dockerfile_buildinfo_test.go index 84e0c24622d5..87cd8c70813f 100644 --- a/frontend/dockerfile/dockerfile_buildinfo_test.go +++ b/frontend/dockerfile/dockerfile_buildinfo_test.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "io" "io/ioutil" "net/http" "net/http/httptest" @@ -75,25 +76,28 @@ COPY --from=alpine /bin/busybox /alpine-busybox server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join(gitDir)))) defer server.Close() - destDir, err := ioutil.TempDir("", "buildkit") - require.NoError(t, err) - defer os.RemoveAll(destDir) - - out := filepath.Join(destDir, "out.tar") - outW, err := os.Create(out) - require.NoError(t, err) - c, err := client.New(sb.Context(), sb.Address()) require.NoError(t, err) defer c.Close() - res, err := f.Solve(sb.Context(), c, client.SolveOpt{ - Exports: []client.ExportEntry{ - { - Type: client.ExporterOCI, - Output: fixedWriteCloser(outW), + var exports []client.ExportEntry + if integration.IsTestDockerd() { + exports = []client.ExportEntry{{ + Type: "moby", + Attrs: map[string]string{ + "name": "reg.dummy:5000/buildkit/test:latest", }, - }, + }} + } else { + exports = []client.ExportEntry{{ + Type: client.ExporterOCI, + Attrs: map[string]string{}, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }} + } + + res, err := f.Solve(sb.Context(), c, client.SolveOpt{ + Exports: exports, FrontendAttrs: map[string]string{ builder.DefaultLocalNameContext: server.URL + "/.git#buildinfo", }, @@ -145,21 +149,24 @@ FROM busybox:latest require.NoError(t, err) defer c.Close() - destDir, err := ioutil.TempDir("", "buildkit") - require.NoError(t, err) - defer os.RemoveAll(destDir) - - out := filepath.Join(destDir, "out.tar") - outW, err := os.Create(out) - require.NoError(t, err) + var exports []client.ExportEntry + if integration.IsTestDockerd() { + exports = []client.ExportEntry{{ + Type: "moby", + Attrs: map[string]string{ + "name": "reg.dummy:5000/buildkit/test:latest", + }, + }} + } else { + exports = []client.ExportEntry{{ + Type: client.ExporterOCI, + Attrs: map[string]string{}, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }} + } res, err := f.Solve(sb.Context(), c, client.SolveOpt{ - Exports: []client.ExportEntry{ - { - Type: client.ExporterOCI, - Output: fixedWriteCloser(outW), - }, - }, + Exports: exports, LocalDirs: map[string]string{ builder.DefaultLocalNameDockerfile: dir, builder.DefaultLocalNameContext: dir, @@ -204,24 +211,27 @@ RUN echo $foo require.NoError(t, err) defer c.Close() - destDir, err := ioutil.TempDir("", "buildkit") - require.NoError(t, err) - defer os.RemoveAll(destDir) - - out := filepath.Join(destDir, "out.tar") - outW, err := os.Create(out) - require.NoError(t, err) + var exports []client.ExportEntry + if integration.IsTestDockerd() { + exports = []client.ExportEntry{{ + Type: "moby", + Attrs: map[string]string{ + "name": "reg.dummy:5000/buildkit/test:latest", + }, + }} + } else { + exports = []client.ExportEntry{{ + Type: client.ExporterOCI, + Attrs: map[string]string{}, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }} + } res, err := f.Solve(sb.Context(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "build-arg:foo": "bar", }, - Exports: []client.ExportEntry{ - { - Type: client.ExporterOCI, - Output: fixedWriteCloser(outW), - }, - }, + Exports: exports, LocalDirs: map[string]string{ builder.DefaultLocalNameDockerfile: dir, builder.DefaultLocalNameContext: dir, @@ -243,6 +253,7 @@ RUN echo $foo // moby/buildkit#2476 func testBuildInfoMultiPlatform(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "multi-platform") f := getFrontend(t, sb) f.RequiresBuildctl(t) @@ -263,14 +274,6 @@ ADD https://raw.githubusercontent.com/moby/moby/master/README.md / require.NoError(t, err) defer c.Close() - destDir, err := ioutil.TempDir("", "buildkit") - require.NoError(t, err) - defer os.RemoveAll(destDir) - - out := filepath.Join(destDir, "out.tar") - outW, err := os.Create(out) - require.NoError(t, err) - platforms := []string{"linux/amd64", "linux/arm64"} res, err := f.Solve(sb.Context(), c, client.SolveOpt{ @@ -281,7 +284,7 @@ ADD https://raw.githubusercontent.com/moby/moby/master/README.md / Exports: []client.ExportEntry{ { Type: client.ExporterOCI, - Output: fixedWriteCloser(outW), + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), }, }, LocalDirs: map[string]string{ @@ -337,25 +340,28 @@ COPY --from=base /out / require.NoError(t, err) defer c.Close() - destDir, err := ioutil.TempDir("", "buildkit") - require.NoError(t, err) - defer os.RemoveAll(destDir) - - out := filepath.Join(destDir, "out.tar") - outW, err := os.Create(out) - require.NoError(t, err) + var exports []client.ExportEntry + if integration.IsTestDockerd() { + exports = []client.ExportEntry{{ + Type: "moby", + Attrs: map[string]string{ + "name": "reg.dummy:5000/buildkit/test:latest", + }, + }} + } else { + exports = []client.ExportEntry{{ + Type: client.ExporterOCI, + Attrs: map[string]string{}, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }} + } res, err := f.Solve(sb.Context(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "build-arg:foo": "bar", "context:busybox": "docker-image://alpine", }, - Exports: []client.ExportEntry{ - { - Type: client.ExporterOCI, - Output: fixedWriteCloser(outW), - }, - }, + Exports: exports, LocalDirs: map[string]string{ builder.DefaultLocalNameDockerfile: dir, builder.DefaultLocalNameContext: dir, @@ -404,14 +410,6 @@ COPY --from=base /o* / require.NoError(t, err) defer c.Close() - destDir, err := ioutil.TempDir("", "buildkit") - require.NoError(t, err) - defer os.RemoveAll(destDir) - - out := filepath.Join(destDir, "out.tar") - outW, err := os.Create(out) - require.NoError(t, err) - outf := []byte(`dummy-result`) dir2, err := tmpdir( @@ -422,17 +420,28 @@ COPY --from=base /o* / require.NoError(t, err) defer os.RemoveAll(dir2) + var exports []client.ExportEntry + if integration.IsTestDockerd() { + exports = []client.ExportEntry{{ + Type: "moby", + Attrs: map[string]string{ + "name": "reg.dummy:5000/buildkit/test:latest", + }, + }} + } else { + exports = []client.ExportEntry{{ + Type: client.ExporterOCI, + Attrs: map[string]string{}, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }} + } + res, err := f.Solve(sb.Context(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "build-arg:foo": "bar", "context:base": "local:basedir", }, - Exports: []client.ExportEntry{ - { - Type: client.ExporterOCI, - Output: fixedWriteCloser(outW), - }, - }, + Exports: exports, LocalDirs: map[string]string{ builder.DefaultLocalNameDockerfile: dir, builder.DefaultLocalNameContext: dir, diff --git a/frontend/dockerfile/dockerfile_heredoc_test.go b/frontend/dockerfile/dockerfile_heredoc_test.go index 4be68738e982..09f067540d99 100644 --- a/frontend/dockerfile/dockerfile_heredoc_test.go +++ b/frontend/dockerfile/dockerfile_heredoc_test.go @@ -617,6 +617,7 @@ COPY --from=build /dest / } func testOnBuildHeredoc(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "image export") f := getFrontend(t, sb) registry, err := sb.NewRegistry() diff --git a/frontend/dockerfile/dockerfile_runnetwork_test.go b/frontend/dockerfile/dockerfile_runnetwork_test.go index 8244d48f5716..f8cad899f526 100644 --- a/frontend/dockerfile/dockerfile_runnetwork_test.go +++ b/frontend/dockerfile/dockerfile_runnetwork_test.go @@ -141,8 +141,12 @@ RUN --network=host nc 127.0.0.1 %s | grep foo case networkHostGranted: require.NoError(t, err) case networkHostDenied: - require.Error(t, err) - require.Contains(t, err.Error(), "entitlement network.host is not allowed") + if !integration.IsTestDockerd() { + require.Error(t, err) + require.Contains(t, err.Error(), "entitlement network.host is not allowed") + } else { + require.NoError(t, err) + } default: require.Fail(t, "unexpected network.host mode %q", hostAllowed) } @@ -188,8 +192,12 @@ RUN --network=none ! nc -z 127.0.0.1 %s case networkHostGranted: require.NoError(t, err) case networkHostDenied: - require.Error(t, err) - require.Contains(t, err.Error(), "entitlement network.host is not allowed") + if !integration.IsTestDockerd() { + require.Error(t, err) + require.Contains(t, err.Error(), "entitlement network.host is not allowed") + } else { + require.NoError(t, err) + } default: require.Fail(t, "unexpected network.host mode %q", hostAllowed) } diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index a4ca3578c7dd..2e5a16012a96 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -48,7 +48,7 @@ import ( ) func init() { - if os.Getenv("TEST_DOCKERD") == "1" { + if integration.IsTestDockerd() { integration.InitDockerdWorker() } else { integration.InitOCIWorker() @@ -406,6 +406,7 @@ RUN [ "$(cat testfile)" == "contents0" ] } func testExportCacheLoop(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "cache export") f := getFrontend(t, sb) dockerfile := []byte(` @@ -1308,7 +1309,7 @@ COPY --from=build /out . } func testDefaultShellAndPath(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "oci exporter") f := getFrontend(t, sb) dockerfile := []byte(` @@ -1398,7 +1399,7 @@ COPY Dockerfile . } func testExportMultiPlatform(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "oci exporter", "multi-platform") f := getFrontend(t, sb) dockerfile := []byte(` @@ -2066,7 +2067,6 @@ FROM busybox:${tag} } func testDockerfileDirs(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) @@ -2135,7 +2135,6 @@ func testDockerfileDirs(t *testing.T, sb integration.Sandbox) { } func testDockerfileInvalidCommand(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) dockerfile := []byte(` @@ -2162,7 +2161,6 @@ func testDockerfileInvalidCommand(t *testing.T, sb integration.Sandbox) { } func testDockerfileInvalidInstruction(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) dockerfile := []byte(` @@ -2193,7 +2191,6 @@ func testDockerfileInvalidInstruction(t *testing.T, sb integration.Sandbox) { } func testDockerfileADDFromURL(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) @@ -2276,7 +2273,6 @@ ADD %s /dest/ } func testDockerfileAddArchive(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) @@ -2559,7 +2555,6 @@ RUN [ "$(stat -c "%u %G" /foo)" == "1000 nobody" ] } func testSymlinkDestination(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) @@ -2673,8 +2668,7 @@ ENV foo=bar } func testExposeExpansion(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) - + integration.SkipIfDockerd(t, sb, "image export") f := getFrontend(t, sb) dockerfile := []byte(` @@ -2888,7 +2882,6 @@ func testDockerfileLowercase(t *testing.T, sb integration.Sandbox) { } func testExportedHistory(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) @@ -2915,6 +2908,8 @@ RUN ["ls"] args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) + integration.SkipIfDockerd(t, sb, "image export") + target := "example.com/moby/dockerfilescratch:test" cmd := sb.Cmd(args + " --exporter=image --exporter-opt=name=" + target) require.NoError(t, cmd.Run()) @@ -2966,17 +2961,8 @@ RUN ["ls"] require.NotNil(t, ociimg.History[6].Created) } -func skipDockerd(t *testing.T, sb integration.Sandbox) { - // TODO: remove me once dockerd supports the image and exporter. - t.Helper() - if os.Getenv("TEST_DOCKERD") == "1" { - t.Skip("dockerd missing a required exporter, cache exporter, or entitlement") - } -} - func testUser(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) - + integration.SkipIfDockerd(t, sb, "image export") f := getFrontend(t, sb) dockerfile := []byte(` @@ -3514,7 +3500,6 @@ RUN sh -c "[ $(cat /test5/foo) = 'hello' ]" } func testAddURLChmod(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) f.RequiresBuildctl(t) @@ -3864,7 +3849,7 @@ COPY --from=stage1 baz bax } func testLabels(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "image export") f := getFrontend(t, sb) dockerfile := []byte(` @@ -3940,7 +3925,6 @@ LABEL foo=bar // #2008 func testWildcardRenameCache(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) f := getFrontend(t, sb) dockerfile := []byte(` @@ -3985,6 +3969,7 @@ RUN ls /files/file1 } func testOnBuildCleared(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "direct push") f := getFrontend(t, sb) registry, err := sb.NewRegistry() @@ -4092,7 +4077,7 @@ ONBUILD RUN mkdir -p /out && echo -n 11 >> /out/foo } func testCacheMultiPlatformImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "direct push") f := getFrontend(t, sb) registry, err := sb.NewRegistry() @@ -4215,7 +4200,7 @@ COPY --from=base arch / } func testCacheImportExport(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "remote cache export") f := getFrontend(t, sb) registry, err := sb.NewRegistry() @@ -4315,7 +4300,7 @@ COPY --from=base unique / } func testReproducibleIDs(t *testing.T, sb integration.Sandbox) { - skipDockerd(t, sb) + integration.SkipIfDockerd(t, sb, "image export") f := getFrontend(t, sb) dockerfile := []byte(` @@ -5532,6 +5517,7 @@ COPY --from=build /foo /out / } func testNamedMultiplatformInputContext(t *testing.T, sb integration.Sandbox) { + integration.SkipIfDockerd(t, sb, "multiplatform") ctx := sb.Context() c, err := client.New(ctx, sb.Address()) diff --git a/frontend/frontend_test.go b/frontend/frontend_test.go index b1d061a265eb..29a77f03482f 100644 --- a/frontend/frontend_test.go +++ b/frontend/frontend_test.go @@ -19,7 +19,7 @@ import ( ) func init() { - if os.Getenv("TEST_DOCKERD") == "1" { + if integration.IsTestDockerd() { integration.InitDockerdWorker() } else { integration.InitOCIWorker() diff --git a/go.mod b/go.mod index b3129c69662f..3890812c6ddf 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,6 @@ require ( ) require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -121,7 +120,6 @@ require ( golang.org/x/text v0.3.7 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - gotest.tools/v3 v3.0.3 // indirect ) replace github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220224222438-c78f6963a1c0+incompatible diff --git a/go.sum b/go.sum index 80787289e36b..a29335482e29 100644 --- a/go.sum +++ b/go.sum @@ -408,7 +408,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= diff --git a/hack/test b/hack/test index d5b253055f94..7b6ea11a8d1f 100755 --- a/hack/test +++ b/hack/test @@ -13,9 +13,18 @@ set -eu -o pipefail : ${DOCKERFILE_RELEASES=} : ${BUILDKIT_WORKER_RANDOM=} -if [ "$TEST_DOCKERD" == "1" ] && ! file $TEST_DOCKERD_BINARY | grep "statically linked" >/dev/null; then - echo "dockerd binary needs to be statically linked" - exit 1 +if [ "$TEST_DOCKERD" == "1" ]; then + if [ ! -f "$TEST_DOCKERD_BINARY" ]; then + echo "dockerd binary not found" + exit 1 + fi + if [ ! -x "$TEST_DOCKERD_BINARY" ]; then + chmod +x "$TEST_DOCKERD_BINARY" + fi + if ! file "$TEST_DOCKERD_BINARY" | grep "statically linked" >/dev/null; then + echo "dockerd binary needs to be statically linked" + exit 1 + fi fi if [ "$#" == 0 ]; then TEST_INTEGRATION=1; fi @@ -63,7 +72,7 @@ fi if [ "$TEST_INTEGRATION" == 1 ]; then cid=$(docker create --rm -v /tmp $coverageVol --volumes-from=$cacheVolume -e TEST_DOCKERD -e SKIP_INTEGRATION_TESTS ${BUILDKIT_INTEGRATION_SNAPSHOTTER:+"-eBUILDKIT_INTEGRATION_SNAPSHOTTER"} -e BUILDKIT_REGISTRY_MIRROR_DIR=/root/.cache/registry --privileged $iid go test $coverageFlags ${TESTFLAGS:--v} ${TESTPKGS:-./...}) if [ "$TEST_DOCKERD" = "1" ]; then - docker cp "$TEST_DOCKERD_BINARY" $cid:/usr/bin/ + docker cp "$TEST_DOCKERD_BINARY" $cid:/usr/bin/dockerd fi docker start -a $cid fi @@ -104,7 +113,7 @@ if [ "$TEST_DOCKERFILE" == 1 ]; then cid=$(docker create -v /tmp $coverageVol --rm --privileged --volumes-from=$cacheVolume -e TEST_DOCKERD -e BUILDKIT_REGISTRY_MIRROR_DIR=/root/.cache/registry -e BUILDKIT_WORKER_RANDOM -e FRONTEND_GATEWAY_ONLY=local:/$release.tar -e EXTERNAL_DF_FRONTEND=/dockerfile-frontend $iid go test $coverageFlags --count=1 -tags "$buildtags" ${TESTFLAGS:--v} ./frontend/dockerfile) docker cp $tarout $cid:/$release.tar if [ "$TEST_DOCKERD" = "1" ]; then - docker cp "$TEST_DOCKERD_BINARY" $cid:/usr/bin/ + docker cp "$TEST_DOCKERD_BINARY" $cid:/usr/bin/dockerd fi docker start -a $cid fi diff --git a/hack/util b/hack/util index 44fb5c9fa728..dc2ecfa9bdb2 100755 --- a/hack/util +++ b/hack/util @@ -5,6 +5,8 @@ export BUILDX_NO_DEFAULT_LOAD=true : ${PREFER_LEGACY=} : ${CI=} : ${GITHUB_ACTIONS=} + +: ${CONTEXT=} : ${CACHE_FROM=} : ${CACHE_TO=} @@ -61,3 +63,6 @@ fi if [ -n "$currentref" ]; then currentcontext="--build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 $currentref" fi +if [ -n "$CONTEXT" ]; then + currentcontext=$CONTEXT +fi diff --git a/util/testutil/integration/dockerd.go b/util/testutil/integration/dockerd.go index 1aeb50a30811..93b656615782 100644 --- a/util/testutil/integration/dockerd.go +++ b/util/testutil/integration/dockerd.go @@ -1,33 +1,29 @@ package integration import ( - "bytes" "context" - "fmt" "io" "io/ioutil" "net" "os" + "os/exec" + "path/filepath" + "strings" + "syscall" + "testing" "time" + "github.com/docker/docker/client" + "github.com/moby/buildkit/identity" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" - - "github.com/docker/docker/testutil/daemon" ) -const dockerdBinary = "dockerd" - -type logTAdapter struct { - Name string - Logs map[string]*bytes.Buffer -} - -func (l logTAdapter) Logf(format string, v ...interface{}) { - if buf, ok := l.Logs[l.Name]; !ok || buf == nil { - l.Logs[l.Name] = &bytes.Buffer{} - } - fmt.Fprintf(l.Logs[l.Name], format, v...) -} +const ( + shortLen = 12 + dockerdBinary = "dockerd" +) // InitDockerdWorker registers a dockerd worker with the global registry. func InitDockerdWorker() { @@ -63,38 +59,66 @@ func (c dockerd) New(ctx context.Context, cfg *BackendConfig) (b Backend, cl fun return nil, nil, err } - cmd, err := daemon.NewDaemon( - workDir, - daemon.WithTestLogger(logTAdapter{ - Name: "creatingDaemon", - Logs: cfg.Logs, - }), - daemon.WithContainerdSocket(""), - ) + dockerdBinaryPath, err := exec.LookPath(dockerdBinary) if err != nil { - return nil, nil, fmt.Errorf("new daemon error: %q, %s", err, formatLogs(cfg.Logs)) + return nil, nil, errors.Wrapf(err, "could not find docker binary in $PATH") } - err = cmd.StartWithError() + id := "d" + identity.NewID()[:shortLen] + dir := filepath.Join(workDir, id) + daemonFolder, err := filepath.Abs(dir) if err != nil { return nil, nil, err } - deferF.append(cmd.StopWithError) - - logs := map[string]*bytes.Buffer{} - if err := waitUnix(cmd.Sock(), 5*time.Second); err != nil { - return nil, nil, fmt.Errorf("dockerd did not start up: %q, %s", err, formatLogs(logs)) + daemonRoot := filepath.Join(daemonFolder, "root") + if err := os.MkdirAll(daemonRoot, 0755); err != nil { + return nil, nil, errors.Wrapf(err, "failed to create daemon root %q", daemonRoot) + } + execRoot := filepath.Join(os.TempDir(), "dxr", id) + daemonSocket := "unix://" + filepath.Join(daemonFolder, "docker.sock") + + cmd := exec.Command(dockerdBinaryPath, []string{ + "--data-root", daemonRoot, + "--exec-root", execRoot, + "--pidfile", filepath.Join(daemonFolder, "docker.pid"), + "--host", daemonSocket, + "--userland-proxy=false", + "--containerd-namespace", id, + "--containerd-plugins-namespace", id + "p", + "--bip", "10.66.66.1/24", + "--default-address-pool", "base=10.66.66.0/16,size=24", + "--debug", + }...) + cmd.Env = append(os.Environ(), "DOCKER_SERVICE_PREFER_OFFLINE_IMAGE=1", "BUILDKIT_DEBUG_EXEC_OUTPUT=1", "BUILDKIT_DEBUG_PANIC_ON_ERROR=1") + cmd.SysProcAttr = getSysProcAttr() + + dockerdStop, err := startCmd(cmd, cfg.Logs) + if err != nil { + return nil, nil, errors.Wrapf(err, "dockerd startcmd error: %s", formatLogs(cfg.Logs)) + } + if err := waitUnix(daemonSocket, 15*time.Second); err != nil { + dockerdStop() + return nil, nil, errors.Wrapf(err, "dockerd did not start up: %s", formatLogs(cfg.Logs)) } + deferF.append(dockerdStop) ctx, cancel := context.WithCancel(context.Background()) deferF.append(func() error { cancel(); return nil }) - dockerAPI, err := cmd.NewClient() + dockerAPI, err := client.NewClientWithOpts( + client.FromEnv, + client.WithHost(daemonSocket), + ) if err != nil { - return nil, nil, err + return nil, nil, errors.Wrapf(err, "dockerd client api error: %s", formatLogs(cfg.Logs)) } deferF.append(dockerAPI.Close) + err = waitForAPI(ctx, dockerAPI, 5*time.Second) + if err != nil { + return nil, nil, errors.Wrapf(err, "dockerd client api timed out: %s", formatLogs(cfg.Logs)) + } + // Create a file descriptor to be used as a Unix domain socket. // Remove it immediately (the name will still be valid for the socket) so that // we don't leave files all over the users tmp tree. @@ -108,7 +132,7 @@ func (c dockerd) New(ctx context.Context, cfg *BackendConfig) (b Backend, cl fun listener, err := net.Listen("unix", localPath) if err != nil { - return nil, nil, err + return nil, nil, errors.Wrapf(err, "dockerd listener error: %s", formatLogs(cfg.Logs)) } deferF.append(listener.Close) @@ -121,20 +145,26 @@ func (c dockerd) New(ctx context.Context, cfg *BackendConfig) (b Backend, cl fun } conn, err := dockerAPI.DialHijack(ctx, "/grpc", "h2c", nil) if err != nil { - return err + if errors.Is(err, syscall.ECONNRESET) || errors.Is(err, net.ErrClosed) { + logrus.Warn("dockerd conn already closed: ", err) + return nil + } + return errors.Wrap(err, "dockerd grpc conn error") } proxyGroup.Go(func() error { _, err := io.Copy(conn, tmpConn) if err != nil { - return err + logrus.Warn("dockerd proxy error: ", err) + return nil } return tmpConn.Close() }) proxyGroup.Go(func() error { _, err := io.Copy(tmpConn, conn) if err != nil { - return err + logrus.Warn("dockerd proxy error: ", err) + return nil } return conn.Close() }) @@ -142,7 +172,43 @@ func (c dockerd) New(ctx context.Context, cfg *BackendConfig) (b Backend, cl fun }) return backend{ - address: "unix://" + listener.Addr().String(), - rootless: false, + address: "unix://" + listener.Addr().String(), + rootless: false, + isDockerd: true, }, cl, nil } + +func waitForAPI(ctx context.Context, apiClient *client.Client, d time.Duration) error { + step := 50 * time.Millisecond + i := 0 + for { + if _, err := apiClient.Ping(ctx); err == nil { + break + } + i++ + if time.Duration(i)*step > d { + return errors.New("failed to connect to /_ping endpoint") + } + time.Sleep(step) + } + return nil +} + +func SkipIfDockerd(t *testing.T, sb Sandbox, reason ...string) { + t.Helper() + sbx, ok := sb.(*sandbox) + if !ok { + t.Fatalf("invalid sandbox type %T", sb) + } + b, ok := sbx.Backend.(backend) + if !ok { + t.Fatalf("invalid backend type %T", b) + } + if b.isDockerd { + t.Skipf("dockerd worker can not currently run this test due to missing features (%s)", strings.Join(reason, ", ")) + } +} + +func IsTestDockerd() bool { + return os.Getenv("TEST_DOCKERD") == "1" +} diff --git a/util/testutil/integration/sandbox.go b/util/testutil/integration/sandbox.go index 8896ec62d657..51936c7d299a 100644 --- a/util/testutil/integration/sandbox.go +++ b/util/testutil/integration/sandbox.go @@ -26,6 +26,7 @@ type backend struct { containerdAddress string rootless bool snapshotter string + isDockerd bool } func (b backend) Address() string { diff --git a/util/testutil/integration/util.go b/util/testutil/integration/util.go index ee92291e531c..6668b97a07d2 100644 --- a/util/testutil/integration/util.go +++ b/util/testutil/integration/util.go @@ -76,7 +76,7 @@ func waitUnix(address string, d time.Duration) error { address = strings.TrimPrefix(address, "unix://") addr, err := net.ResolveUnixAddr("unix", address) if err != nil { - return err + return errors.Wrapf(err, "failed resolving unix addr: %s", address) } step := 50 * time.Millisecond diff --git a/vendor/github.com/Azure/go-ansiterm/LICENSE b/vendor/github.com/Azure/go-ansiterm/LICENSE deleted file mode 100644 index e3d9a64d1d85..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Microsoft Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/Azure/go-ansiterm/README.md b/vendor/github.com/Azure/go-ansiterm/README.md deleted file mode 100644 index 261c041e7aba..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# go-ansiterm - -This is a cross platform Ansi Terminal Emulation library. It reads a stream of Ansi characters and produces the appropriate function calls. The results of the function calls are platform dependent. - -For example the parser might receive "ESC, [, A" as a stream of three characters. This is the code for Cursor Up (http://www.vt100.net/docs/vt510-rm/CUU). The parser then calls the cursor up function (CUU()) on an event handler. The event handler determines what platform specific work must be done to cause the cursor to move up one position. - -The parser (parser.go) is a partial implementation of this state machine (http://vt100.net/emu/vt500_parser.png). There are also two event handler implementations, one for tests (test_event_handler.go) to validate that the expected events are being produced and called, the other is a Windows implementation (winterm/win_event_handler.go). - -See parser_test.go for examples exercising the state machine and generating appropriate function calls. - ------ -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/vendor/github.com/Azure/go-ansiterm/constants.go b/vendor/github.com/Azure/go-ansiterm/constants.go deleted file mode 100644 index 96504a33bc9e..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/constants.go +++ /dev/null @@ -1,188 +0,0 @@ -package ansiterm - -const LogEnv = "DEBUG_TERMINAL" - -// ANSI constants -// References: -// -- http://www.ecma-international.org/publications/standards/Ecma-048.htm -// -- http://man7.org/linux/man-pages/man4/console_codes.4.html -// -- http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html -// -- http://en.wikipedia.org/wiki/ANSI_escape_code -// -- http://vt100.net/emu/dec_ansi_parser -// -- http://vt100.net/emu/vt500_parser.svg -// -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html -// -- http://www.inwap.com/pdp10/ansicode.txt -const ( - // ECMA-48 Set Graphics Rendition - // Note: - // -- Constants leading with an underscore (e.g., _ANSI_xxx) are unsupported or reserved - // -- Fonts could possibly be supported via SetCurrentConsoleFontEx - // -- Windows does not expose the per-window cursor (i.e., caret) blink times - ANSI_SGR_RESET = 0 - ANSI_SGR_BOLD = 1 - ANSI_SGR_DIM = 2 - _ANSI_SGR_ITALIC = 3 - ANSI_SGR_UNDERLINE = 4 - _ANSI_SGR_BLINKSLOW = 5 - _ANSI_SGR_BLINKFAST = 6 - ANSI_SGR_REVERSE = 7 - _ANSI_SGR_INVISIBLE = 8 - _ANSI_SGR_LINETHROUGH = 9 - _ANSI_SGR_FONT_00 = 10 - _ANSI_SGR_FONT_01 = 11 - _ANSI_SGR_FONT_02 = 12 - _ANSI_SGR_FONT_03 = 13 - _ANSI_SGR_FONT_04 = 14 - _ANSI_SGR_FONT_05 = 15 - _ANSI_SGR_FONT_06 = 16 - _ANSI_SGR_FONT_07 = 17 - _ANSI_SGR_FONT_08 = 18 - _ANSI_SGR_FONT_09 = 19 - _ANSI_SGR_FONT_10 = 20 - _ANSI_SGR_DOUBLEUNDERLINE = 21 - ANSI_SGR_BOLD_DIM_OFF = 22 - _ANSI_SGR_ITALIC_OFF = 23 - ANSI_SGR_UNDERLINE_OFF = 24 - _ANSI_SGR_BLINK_OFF = 25 - _ANSI_SGR_RESERVED_00 = 26 - ANSI_SGR_REVERSE_OFF = 27 - _ANSI_SGR_INVISIBLE_OFF = 28 - _ANSI_SGR_LINETHROUGH_OFF = 29 - ANSI_SGR_FOREGROUND_BLACK = 30 - ANSI_SGR_FOREGROUND_RED = 31 - ANSI_SGR_FOREGROUND_GREEN = 32 - ANSI_SGR_FOREGROUND_YELLOW = 33 - ANSI_SGR_FOREGROUND_BLUE = 34 - ANSI_SGR_FOREGROUND_MAGENTA = 35 - ANSI_SGR_FOREGROUND_CYAN = 36 - ANSI_SGR_FOREGROUND_WHITE = 37 - _ANSI_SGR_RESERVED_01 = 38 - ANSI_SGR_FOREGROUND_DEFAULT = 39 - ANSI_SGR_BACKGROUND_BLACK = 40 - ANSI_SGR_BACKGROUND_RED = 41 - ANSI_SGR_BACKGROUND_GREEN = 42 - ANSI_SGR_BACKGROUND_YELLOW = 43 - ANSI_SGR_BACKGROUND_BLUE = 44 - ANSI_SGR_BACKGROUND_MAGENTA = 45 - ANSI_SGR_BACKGROUND_CYAN = 46 - ANSI_SGR_BACKGROUND_WHITE = 47 - _ANSI_SGR_RESERVED_02 = 48 - ANSI_SGR_BACKGROUND_DEFAULT = 49 - // 50 - 65: Unsupported - - ANSI_MAX_CMD_LENGTH = 4096 - - MAX_INPUT_EVENTS = 128 - DEFAULT_WIDTH = 80 - DEFAULT_HEIGHT = 24 - - ANSI_BEL = 0x07 - ANSI_BACKSPACE = 0x08 - ANSI_TAB = 0x09 - ANSI_LINE_FEED = 0x0A - ANSI_VERTICAL_TAB = 0x0B - ANSI_FORM_FEED = 0x0C - ANSI_CARRIAGE_RETURN = 0x0D - ANSI_ESCAPE_PRIMARY = 0x1B - ANSI_ESCAPE_SECONDARY = 0x5B - ANSI_OSC_STRING_ENTRY = 0x5D - ANSI_COMMAND_FIRST = 0x40 - ANSI_COMMAND_LAST = 0x7E - DCS_ENTRY = 0x90 - CSI_ENTRY = 0x9B - OSC_STRING = 0x9D - ANSI_PARAMETER_SEP = ";" - ANSI_CMD_G0 = '(' - ANSI_CMD_G1 = ')' - ANSI_CMD_G2 = '*' - ANSI_CMD_G3 = '+' - ANSI_CMD_DECPNM = '>' - ANSI_CMD_DECPAM = '=' - ANSI_CMD_OSC = ']' - ANSI_CMD_STR_TERM = '\\' - - KEY_CONTROL_PARAM_2 = ";2" - KEY_CONTROL_PARAM_3 = ";3" - KEY_CONTROL_PARAM_4 = ";4" - KEY_CONTROL_PARAM_5 = ";5" - KEY_CONTROL_PARAM_6 = ";6" - KEY_CONTROL_PARAM_7 = ";7" - KEY_CONTROL_PARAM_8 = ";8" - KEY_ESC_CSI = "\x1B[" - KEY_ESC_N = "\x1BN" - KEY_ESC_O = "\x1BO" - - FILL_CHARACTER = ' ' -) - -func getByteRange(start byte, end byte) []byte { - bytes := make([]byte, 0, 32) - for i := start; i <= end; i++ { - bytes = append(bytes, byte(i)) - } - - return bytes -} - -var toGroundBytes = getToGroundBytes() -var executors = getExecuteBytes() - -// SPACE 20+A0 hex Always and everywhere a blank space -// Intermediate 20-2F hex !"#$%&'()*+,-./ -var intermeds = getByteRange(0x20, 0x2F) - -// Parameters 30-3F hex 0123456789:;<=>? -// CSI Parameters 30-39, 3B hex 0123456789; -var csiParams = getByteRange(0x30, 0x3F) - -var csiCollectables = append(getByteRange(0x30, 0x39), getByteRange(0x3B, 0x3F)...) - -// Uppercase 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ -var upperCase = getByteRange(0x40, 0x5F) - -// Lowercase 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~ -var lowerCase = getByteRange(0x60, 0x7E) - -// Alphabetics 40-7E hex (all of upper and lower case) -var alphabetics = append(upperCase, lowerCase...) - -var printables = getByteRange(0x20, 0x7F) - -var escapeIntermediateToGroundBytes = getByteRange(0x30, 0x7E) -var escapeToGroundBytes = getEscapeToGroundBytes() - -// See http://www.vt100.net/emu/vt500_parser.png for description of the complex -// byte ranges below - -func getEscapeToGroundBytes() []byte { - escapeToGroundBytes := getByteRange(0x30, 0x4F) - escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x51, 0x57)...) - escapeToGroundBytes = append(escapeToGroundBytes, 0x59) - escapeToGroundBytes = append(escapeToGroundBytes, 0x5A) - escapeToGroundBytes = append(escapeToGroundBytes, 0x5C) - escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x60, 0x7E)...) - return escapeToGroundBytes -} - -func getExecuteBytes() []byte { - executeBytes := getByteRange(0x00, 0x17) - executeBytes = append(executeBytes, 0x19) - executeBytes = append(executeBytes, getByteRange(0x1C, 0x1F)...) - return executeBytes -} - -func getToGroundBytes() []byte { - groundBytes := []byte{0x18} - groundBytes = append(groundBytes, 0x1A) - groundBytes = append(groundBytes, getByteRange(0x80, 0x8F)...) - groundBytes = append(groundBytes, getByteRange(0x91, 0x97)...) - groundBytes = append(groundBytes, 0x99) - groundBytes = append(groundBytes, 0x9A) - groundBytes = append(groundBytes, 0x9C) - return groundBytes -} - -// Delete 7F hex Always and everywhere ignored -// C1 Control 80-9F hex 32 additional control characters -// G1 Displayable A1-FE hex 94 additional displayable characters -// Special A0+FF hex Same as SPACE and DELETE diff --git a/vendor/github.com/Azure/go-ansiterm/context.go b/vendor/github.com/Azure/go-ansiterm/context.go deleted file mode 100644 index 8d66e777c038..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/context.go +++ /dev/null @@ -1,7 +0,0 @@ -package ansiterm - -type ansiContext struct { - currentChar byte - paramBuffer []byte - interBuffer []byte -} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go deleted file mode 100644 index bcbe00d0c5ec..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go +++ /dev/null @@ -1,49 +0,0 @@ -package ansiterm - -type csiEntryState struct { - baseState -} - -func (csiState csiEntryState) Handle(b byte) (s state, e error) { - csiState.parser.logf("CsiEntry::Handle %#x", b) - - nextState, err := csiState.baseState.Handle(b) - if nextState != nil || err != nil { - return nextState, err - } - - switch { - case sliceContains(alphabetics, b): - return csiState.parser.ground, nil - case sliceContains(csiCollectables, b): - return csiState.parser.csiParam, nil - case sliceContains(executors, b): - return csiState, csiState.parser.execute() - } - - return csiState, nil -} - -func (csiState csiEntryState) Transition(s state) error { - csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name()) - csiState.baseState.Transition(s) - - switch s { - case csiState.parser.ground: - return csiState.parser.csiDispatch() - case csiState.parser.csiParam: - switch { - case sliceContains(csiParams, csiState.parser.context.currentChar): - csiState.parser.collectParam() - case sliceContains(intermeds, csiState.parser.context.currentChar): - csiState.parser.collectInter() - } - } - - return nil -} - -func (csiState csiEntryState) Enter() error { - csiState.parser.clear() - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go deleted file mode 100644 index 7ed5e01c3428..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go +++ /dev/null @@ -1,38 +0,0 @@ -package ansiterm - -type csiParamState struct { - baseState -} - -func (csiState csiParamState) Handle(b byte) (s state, e error) { - csiState.parser.logf("CsiParam::Handle %#x", b) - - nextState, err := csiState.baseState.Handle(b) - if nextState != nil || err != nil { - return nextState, err - } - - switch { - case sliceContains(alphabetics, b): - return csiState.parser.ground, nil - case sliceContains(csiCollectables, b): - csiState.parser.collectParam() - return csiState, nil - case sliceContains(executors, b): - return csiState, csiState.parser.execute() - } - - return csiState, nil -} - -func (csiState csiParamState) Transition(s state) error { - csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name()) - csiState.baseState.Transition(s) - - switch s { - case csiState.parser.ground: - return csiState.parser.csiDispatch() - } - - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go deleted file mode 100644 index 1c719db9e48c..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go +++ /dev/null @@ -1,36 +0,0 @@ -package ansiterm - -type escapeIntermediateState struct { - baseState -} - -func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { - escState.parser.logf("escapeIntermediateState::Handle %#x", b) - nextState, err := escState.baseState.Handle(b) - if nextState != nil || err != nil { - return nextState, err - } - - switch { - case sliceContains(intermeds, b): - return escState, escState.parser.collectInter() - case sliceContains(executors, b): - return escState, escState.parser.execute() - case sliceContains(escapeIntermediateToGroundBytes, b): - return escState.parser.ground, nil - } - - return escState, nil -} - -func (escState escapeIntermediateState) Transition(s state) error { - escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name()) - escState.baseState.Transition(s) - - switch s { - case escState.parser.ground: - return escState.parser.escDispatch() - } - - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_state.go b/vendor/github.com/Azure/go-ansiterm/escape_state.go deleted file mode 100644 index 6390abd231ba..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/escape_state.go +++ /dev/null @@ -1,47 +0,0 @@ -package ansiterm - -type escapeState struct { - baseState -} - -func (escState escapeState) Handle(b byte) (s state, e error) { - escState.parser.logf("escapeState::Handle %#x", b) - nextState, err := escState.baseState.Handle(b) - if nextState != nil || err != nil { - return nextState, err - } - - switch { - case b == ANSI_ESCAPE_SECONDARY: - return escState.parser.csiEntry, nil - case b == ANSI_OSC_STRING_ENTRY: - return escState.parser.oscString, nil - case sliceContains(executors, b): - return escState, escState.parser.execute() - case sliceContains(escapeToGroundBytes, b): - return escState.parser.ground, nil - case sliceContains(intermeds, b): - return escState.parser.escapeIntermediate, nil - } - - return escState, nil -} - -func (escState escapeState) Transition(s state) error { - escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name()) - escState.baseState.Transition(s) - - switch s { - case escState.parser.ground: - return escState.parser.escDispatch() - case escState.parser.escapeIntermediate: - return escState.parser.collectInter() - } - - return nil -} - -func (escState escapeState) Enter() error { - escState.parser.clear() - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/event_handler.go b/vendor/github.com/Azure/go-ansiterm/event_handler.go deleted file mode 100644 index 98087b38c202..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/event_handler.go +++ /dev/null @@ -1,90 +0,0 @@ -package ansiterm - -type AnsiEventHandler interface { - // Print - Print(b byte) error - - // Execute C0 commands - Execute(b byte) error - - // CUrsor Up - CUU(int) error - - // CUrsor Down - CUD(int) error - - // CUrsor Forward - CUF(int) error - - // CUrsor Backward - CUB(int) error - - // Cursor to Next Line - CNL(int) error - - // Cursor to Previous Line - CPL(int) error - - // Cursor Horizontal position Absolute - CHA(int) error - - // Vertical line Position Absolute - VPA(int) error - - // CUrsor Position - CUP(int, int) error - - // Horizontal and Vertical Position (depends on PUM) - HVP(int, int) error - - // Text Cursor Enable Mode - DECTCEM(bool) error - - // Origin Mode - DECOM(bool) error - - // 132 Column Mode - DECCOLM(bool) error - - // Erase in Display - ED(int) error - - // Erase in Line - EL(int) error - - // Insert Line - IL(int) error - - // Delete Line - DL(int) error - - // Insert Character - ICH(int) error - - // Delete Character - DCH(int) error - - // Set Graphics Rendition - SGR([]int) error - - // Pan Down - SU(int) error - - // Pan Up - SD(int) error - - // Device Attributes - DA([]string) error - - // Set Top and Bottom Margins - DECSTBM(int, int) error - - // Index - IND() error - - // Reverse Index - RI() error - - // Flush updates from previous commands - Flush() error -} diff --git a/vendor/github.com/Azure/go-ansiterm/ground_state.go b/vendor/github.com/Azure/go-ansiterm/ground_state.go deleted file mode 100644 index 52451e94693a..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/ground_state.go +++ /dev/null @@ -1,24 +0,0 @@ -package ansiterm - -type groundState struct { - baseState -} - -func (gs groundState) Handle(b byte) (s state, e error) { - gs.parser.context.currentChar = b - - nextState, err := gs.baseState.Handle(b) - if nextState != nil || err != nil { - return nextState, err - } - - switch { - case sliceContains(printables, b): - return gs, gs.parser.print() - - case sliceContains(executors, b): - return gs, gs.parser.execute() - } - - return gs, nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go deleted file mode 100644 index 593b10ab6963..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go +++ /dev/null @@ -1,31 +0,0 @@ -package ansiterm - -type oscStringState struct { - baseState -} - -func (oscState oscStringState) Handle(b byte) (s state, e error) { - oscState.parser.logf("OscString::Handle %#x", b) - nextState, err := oscState.baseState.Handle(b) - if nextState != nil || err != nil { - return nextState, err - } - - switch { - case isOscStringTerminator(b): - return oscState.parser.ground, nil - } - - return oscState, nil -} - -// See below for OSC string terminators for linux -// http://man7.org/linux/man-pages/man4/console_codes.4.html -func isOscStringTerminator(b byte) bool { - - if b == ANSI_BEL || b == 0x5C { - return true - } - - return false -} diff --git a/vendor/github.com/Azure/go-ansiterm/parser.go b/vendor/github.com/Azure/go-ansiterm/parser.go deleted file mode 100644 index 03cec7ada62a..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/parser.go +++ /dev/null @@ -1,151 +0,0 @@ -package ansiterm - -import ( - "errors" - "log" - "os" -) - -type AnsiParser struct { - currState state - eventHandler AnsiEventHandler - context *ansiContext - csiEntry state - csiParam state - dcsEntry state - escape state - escapeIntermediate state - error state - ground state - oscString state - stateMap []state - - logf func(string, ...interface{}) -} - -type Option func(*AnsiParser) - -func WithLogf(f func(string, ...interface{})) Option { - return func(ap *AnsiParser) { - ap.logf = f - } -} - -func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser { - ap := &AnsiParser{ - eventHandler: evtHandler, - context: &ansiContext{}, - } - for _, o := range opts { - o(ap) - } - - if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" { - logFile, _ := os.Create("ansiParser.log") - logger := log.New(logFile, "", log.LstdFlags) - if ap.logf != nil { - l := ap.logf - ap.logf = func(s string, v ...interface{}) { - l(s, v...) - logger.Printf(s, v...) - } - } else { - ap.logf = logger.Printf - } - } - - if ap.logf == nil { - ap.logf = func(string, ...interface{}) {} - } - - ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}} - ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}} - ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}} - ap.escape = escapeState{baseState{name: "Escape", parser: ap}} - ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}} - ap.error = errorState{baseState{name: "Error", parser: ap}} - ap.ground = groundState{baseState{name: "Ground", parser: ap}} - ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}} - - ap.stateMap = []state{ - ap.csiEntry, - ap.csiParam, - ap.dcsEntry, - ap.escape, - ap.escapeIntermediate, - ap.error, - ap.ground, - ap.oscString, - } - - ap.currState = getState(initialState, ap.stateMap) - - ap.logf("CreateParser: parser %p", ap) - return ap -} - -func getState(name string, states []state) state { - for _, el := range states { - if el.Name() == name { - return el - } - } - - return nil -} - -func (ap *AnsiParser) Parse(bytes []byte) (int, error) { - for i, b := range bytes { - if err := ap.handle(b); err != nil { - return i, err - } - } - - return len(bytes), ap.eventHandler.Flush() -} - -func (ap *AnsiParser) handle(b byte) error { - ap.context.currentChar = b - newState, err := ap.currState.Handle(b) - if err != nil { - return err - } - - if newState == nil { - ap.logf("WARNING: newState is nil") - return errors.New("New state of 'nil' is invalid.") - } - - if newState != ap.currState { - if err := ap.changeState(newState); err != nil { - return err - } - } - - return nil -} - -func (ap *AnsiParser) changeState(newState state) error { - ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name()) - - // Exit old state - if err := ap.currState.Exit(); err != nil { - ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err) - return err - } - - // Perform transition action - if err := ap.currState.Transition(newState); err != nil { - ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err) - return err - } - - // Enter new state - if err := newState.Enter(); err != nil { - ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err) - return err - } - - ap.currState = newState - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go deleted file mode 100644 index de0a1f9cde3b..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go +++ /dev/null @@ -1,99 +0,0 @@ -package ansiterm - -import ( - "strconv" -) - -func parseParams(bytes []byte) ([]string, error) { - paramBuff := make([]byte, 0, 0) - params := []string{} - - for _, v := range bytes { - if v == ';' { - if len(paramBuff) > 0 { - // Completed parameter, append it to the list - s := string(paramBuff) - params = append(params, s) - paramBuff = make([]byte, 0, 0) - } - } else { - paramBuff = append(paramBuff, v) - } - } - - // Last parameter may not be terminated with ';' - if len(paramBuff) > 0 { - s := string(paramBuff) - params = append(params, s) - } - - return params, nil -} - -func parseCmd(context ansiContext) (string, error) { - return string(context.currentChar), nil -} - -func getInt(params []string, dflt int) int { - i := getInts(params, 1, dflt)[0] - return i -} - -func getInts(params []string, minCount int, dflt int) []int { - ints := []int{} - - for _, v := range params { - i, _ := strconv.Atoi(v) - // Zero is mapped to the default value in VT100. - if i == 0 { - i = dflt - } - ints = append(ints, i) - } - - if len(ints) < minCount { - remaining := minCount - len(ints) - for i := 0; i < remaining; i++ { - ints = append(ints, dflt) - } - } - - return ints -} - -func (ap *AnsiParser) modeDispatch(param string, set bool) error { - switch param { - case "?3": - return ap.eventHandler.DECCOLM(set) - case "?6": - return ap.eventHandler.DECOM(set) - case "?25": - return ap.eventHandler.DECTCEM(set) - } - return nil -} - -func (ap *AnsiParser) hDispatch(params []string) error { - if len(params) == 1 { - return ap.modeDispatch(params[0], true) - } - - return nil -} - -func (ap *AnsiParser) lDispatch(params []string) error { - if len(params) == 1 { - return ap.modeDispatch(params[0], false) - } - - return nil -} - -func getEraseParam(params []string) int { - param := getInt(params, 0) - if param < 0 || 3 < param { - param = 0 - } - - return param -} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_actions.go b/vendor/github.com/Azure/go-ansiterm/parser_actions.go deleted file mode 100644 index 0bb5e51e9aa6..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/parser_actions.go +++ /dev/null @@ -1,119 +0,0 @@ -package ansiterm - -func (ap *AnsiParser) collectParam() error { - currChar := ap.context.currentChar - ap.logf("collectParam %#x", currChar) - ap.context.paramBuffer = append(ap.context.paramBuffer, currChar) - return nil -} - -func (ap *AnsiParser) collectInter() error { - currChar := ap.context.currentChar - ap.logf("collectInter %#x", currChar) - ap.context.paramBuffer = append(ap.context.interBuffer, currChar) - return nil -} - -func (ap *AnsiParser) escDispatch() error { - cmd, _ := parseCmd(*ap.context) - intermeds := ap.context.interBuffer - ap.logf("escDispatch currentChar: %#x", ap.context.currentChar) - ap.logf("escDispatch: %v(%v)", cmd, intermeds) - - switch cmd { - case "D": // IND - return ap.eventHandler.IND() - case "E": // NEL, equivalent to CRLF - err := ap.eventHandler.Execute(ANSI_CARRIAGE_RETURN) - if err == nil { - err = ap.eventHandler.Execute(ANSI_LINE_FEED) - } - return err - case "M": // RI - return ap.eventHandler.RI() - } - - return nil -} - -func (ap *AnsiParser) csiDispatch() error { - cmd, _ := parseCmd(*ap.context) - params, _ := parseParams(ap.context.paramBuffer) - ap.logf("Parsed params: %v with length: %d", params, len(params)) - - ap.logf("csiDispatch: %v(%v)", cmd, params) - - switch cmd { - case "@": - return ap.eventHandler.ICH(getInt(params, 1)) - case "A": - return ap.eventHandler.CUU(getInt(params, 1)) - case "B": - return ap.eventHandler.CUD(getInt(params, 1)) - case "C": - return ap.eventHandler.CUF(getInt(params, 1)) - case "D": - return ap.eventHandler.CUB(getInt(params, 1)) - case "E": - return ap.eventHandler.CNL(getInt(params, 1)) - case "F": - return ap.eventHandler.CPL(getInt(params, 1)) - case "G": - return ap.eventHandler.CHA(getInt(params, 1)) - case "H": - ints := getInts(params, 2, 1) - x, y := ints[0], ints[1] - return ap.eventHandler.CUP(x, y) - case "J": - param := getEraseParam(params) - return ap.eventHandler.ED(param) - case "K": - param := getEraseParam(params) - return ap.eventHandler.EL(param) - case "L": - return ap.eventHandler.IL(getInt(params, 1)) - case "M": - return ap.eventHandler.DL(getInt(params, 1)) - case "P": - return ap.eventHandler.DCH(getInt(params, 1)) - case "S": - return ap.eventHandler.SU(getInt(params, 1)) - case "T": - return ap.eventHandler.SD(getInt(params, 1)) - case "c": - return ap.eventHandler.DA(params) - case "d": - return ap.eventHandler.VPA(getInt(params, 1)) - case "f": - ints := getInts(params, 2, 1) - x, y := ints[0], ints[1] - return ap.eventHandler.HVP(x, y) - case "h": - return ap.hDispatch(params) - case "l": - return ap.lDispatch(params) - case "m": - return ap.eventHandler.SGR(getInts(params, 1, 0)) - case "r": - ints := getInts(params, 2, 1) - top, bottom := ints[0], ints[1] - return ap.eventHandler.DECSTBM(top, bottom) - default: - ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context) - return nil - } - -} - -func (ap *AnsiParser) print() error { - return ap.eventHandler.Print(ap.context.currentChar) -} - -func (ap *AnsiParser) clear() error { - ap.context = &ansiContext{} - return nil -} - -func (ap *AnsiParser) execute() error { - return ap.eventHandler.Execute(ap.context.currentChar) -} diff --git a/vendor/github.com/Azure/go-ansiterm/states.go b/vendor/github.com/Azure/go-ansiterm/states.go deleted file mode 100644 index f2ea1fcd12da..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/states.go +++ /dev/null @@ -1,71 +0,0 @@ -package ansiterm - -type stateID int - -type state interface { - Enter() error - Exit() error - Handle(byte) (state, error) - Name() string - Transition(state) error -} - -type baseState struct { - name string - parser *AnsiParser -} - -func (base baseState) Enter() error { - return nil -} - -func (base baseState) Exit() error { - return nil -} - -func (base baseState) Handle(b byte) (s state, e error) { - - switch { - case b == CSI_ENTRY: - return base.parser.csiEntry, nil - case b == DCS_ENTRY: - return base.parser.dcsEntry, nil - case b == ANSI_ESCAPE_PRIMARY: - return base.parser.escape, nil - case b == OSC_STRING: - return base.parser.oscString, nil - case sliceContains(toGroundBytes, b): - return base.parser.ground, nil - } - - return nil, nil -} - -func (base baseState) Name() string { - return base.name -} - -func (base baseState) Transition(s state) error { - if s == base.parser.ground { - execBytes := []byte{0x18} - execBytes = append(execBytes, 0x1A) - execBytes = append(execBytes, getByteRange(0x80, 0x8F)...) - execBytes = append(execBytes, getByteRange(0x91, 0x97)...) - execBytes = append(execBytes, 0x99) - execBytes = append(execBytes, 0x9A) - - if sliceContains(execBytes, base.parser.context.currentChar) { - return base.parser.execute() - } - } - - return nil -} - -type dcsEntryState struct { - baseState -} - -type errorState struct { - baseState -} diff --git a/vendor/github.com/Azure/go-ansiterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/utilities.go deleted file mode 100644 index 392114493a22..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/utilities.go +++ /dev/null @@ -1,21 +0,0 @@ -package ansiterm - -import ( - "strconv" -) - -func sliceContains(bytes []byte, b byte) bool { - for _, v := range bytes { - if v == b { - return true - } - } - - return false -} - -func convertBytesToInteger(bytes []byte) int { - s := string(bytes) - i, _ := strconv.Atoi(s) - return i -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go deleted file mode 100644 index 5599082ae9cb..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go +++ /dev/null @@ -1,196 +0,0 @@ -// +build windows - -package winterm - -import ( - "fmt" - "os" - "strconv" - "strings" - "syscall" - - "github.com/Azure/go-ansiterm" - windows "golang.org/x/sys/windows" -) - -// Windows keyboard constants -// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx. -const ( - VK_PRIOR = 0x21 // PAGE UP key - VK_NEXT = 0x22 // PAGE DOWN key - VK_END = 0x23 // END key - VK_HOME = 0x24 // HOME key - VK_LEFT = 0x25 // LEFT ARROW key - VK_UP = 0x26 // UP ARROW key - VK_RIGHT = 0x27 // RIGHT ARROW key - VK_DOWN = 0x28 // DOWN ARROW key - VK_SELECT = 0x29 // SELECT key - VK_PRINT = 0x2A // PRINT key - VK_EXECUTE = 0x2B // EXECUTE key - VK_SNAPSHOT = 0x2C // PRINT SCREEN key - VK_INSERT = 0x2D // INS key - VK_DELETE = 0x2E // DEL key - VK_HELP = 0x2F // HELP key - VK_F1 = 0x70 // F1 key - VK_F2 = 0x71 // F2 key - VK_F3 = 0x72 // F3 key - VK_F4 = 0x73 // F4 key - VK_F5 = 0x74 // F5 key - VK_F6 = 0x75 // F6 key - VK_F7 = 0x76 // F7 key - VK_F8 = 0x77 // F8 key - VK_F9 = 0x78 // F9 key - VK_F10 = 0x79 // F10 key - VK_F11 = 0x7A // F11 key - VK_F12 = 0x7B // F12 key - - RIGHT_ALT_PRESSED = 0x0001 - LEFT_ALT_PRESSED = 0x0002 - RIGHT_CTRL_PRESSED = 0x0004 - LEFT_CTRL_PRESSED = 0x0008 - SHIFT_PRESSED = 0x0010 - NUMLOCK_ON = 0x0020 - SCROLLLOCK_ON = 0x0040 - CAPSLOCK_ON = 0x0080 - ENHANCED_KEY = 0x0100 -) - -type ansiCommand struct { - CommandBytes []byte - Command string - Parameters []string - IsSpecial bool -} - -func newAnsiCommand(command []byte) *ansiCommand { - - if isCharacterSelectionCmdChar(command[1]) { - // Is Character Set Selection commands - return &ansiCommand{ - CommandBytes: command, - Command: string(command), - IsSpecial: true, - } - } - - // last char is command character - lastCharIndex := len(command) - 1 - - ac := &ansiCommand{ - CommandBytes: command, - Command: string(command[lastCharIndex]), - IsSpecial: false, - } - - // more than a single escape - if lastCharIndex != 0 { - start := 1 - // skip if double char escape sequence - if command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_ESCAPE_SECONDARY { - start++ - } - // convert this to GetNextParam method - ac.Parameters = strings.Split(string(command[start:lastCharIndex]), ansiterm.ANSI_PARAMETER_SEP) - } - - return ac -} - -func (ac *ansiCommand) paramAsSHORT(index int, defaultValue int16) int16 { - if index < 0 || index >= len(ac.Parameters) { - return defaultValue - } - - param, err := strconv.ParseInt(ac.Parameters[index], 10, 16) - if err != nil { - return defaultValue - } - - return int16(param) -} - -func (ac *ansiCommand) String() string { - return fmt.Sprintf("0x%v \"%v\" (\"%v\")", - bytesToHex(ac.CommandBytes), - ac.Command, - strings.Join(ac.Parameters, "\",\"")) -} - -// isAnsiCommandChar returns true if the passed byte falls within the range of ANSI commands. -// See http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html. -func isAnsiCommandChar(b byte) bool { - switch { - case ansiterm.ANSI_COMMAND_FIRST <= b && b <= ansiterm.ANSI_COMMAND_LAST && b != ansiterm.ANSI_ESCAPE_SECONDARY: - return true - case b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_OSC || b == ansiterm.ANSI_CMD_DECPAM || b == ansiterm.ANSI_CMD_DECPNM: - // non-CSI escape sequence terminator - return true - case b == ansiterm.ANSI_CMD_STR_TERM || b == ansiterm.ANSI_BEL: - // String escape sequence terminator - return true - } - return false -} - -func isXtermOscSequence(command []byte, current byte) bool { - return (len(command) >= 2 && command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_CMD_OSC && current != ansiterm.ANSI_BEL) -} - -func isCharacterSelectionCmdChar(b byte) bool { - return (b == ansiterm.ANSI_CMD_G0 || b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_G2 || b == ansiterm.ANSI_CMD_G3) -} - -// bytesToHex converts a slice of bytes to a human-readable string. -func bytesToHex(b []byte) string { - hex := make([]string, len(b)) - for i, ch := range b { - hex[i] = fmt.Sprintf("%X", ch) - } - return strings.Join(hex, "") -} - -// ensureInRange adjusts the passed value, if necessary, to ensure it is within -// the passed min / max range. -func ensureInRange(n int16, min int16, max int16) int16 { - if n < min { - return min - } else if n > max { - return max - } else { - return n - } -} - -func GetStdFile(nFile int) (*os.File, uintptr) { - var file *os.File - - // syscall uses negative numbers - // windows package uses very big uint32 - // Keep these switches split so we don't have to convert ints too much. - switch uint32(nFile) { - case windows.STD_INPUT_HANDLE: - file = os.Stdin - case windows.STD_OUTPUT_HANDLE: - file = os.Stdout - case windows.STD_ERROR_HANDLE: - file = os.Stderr - default: - switch nFile { - case syscall.STD_INPUT_HANDLE: - file = os.Stdin - case syscall.STD_OUTPUT_HANDLE: - file = os.Stdout - case syscall.STD_ERROR_HANDLE: - file = os.Stderr - default: - panic(fmt.Errorf("Invalid standard handle identifier: %v", nFile)) - } - } - - fd, err := syscall.GetStdHandle(nFile) - if err != nil { - panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err)) - } - - return file, uintptr(fd) -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/api.go b/vendor/github.com/Azure/go-ansiterm/winterm/api.go deleted file mode 100644 index 6055e33b912b..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/api.go +++ /dev/null @@ -1,327 +0,0 @@ -// +build windows - -package winterm - -import ( - "fmt" - "syscall" - "unsafe" -) - -//=========================================================================================================== -// IMPORTANT NOTE: -// -// The methods below make extensive use of the "unsafe" package to obtain the required pointers. -// Beginning in Go 1.3, the garbage collector may release local variables (e.g., incoming arguments, stack -// variables) the pointers reference *before* the API completes. -// -// As a result, in those cases, the code must hint that the variables remain in active by invoking the -// dummy method "use" (see below). Newer versions of Go are planned to change the mechanism to no longer -// require unsafe pointers. -// -// If you add or modify methods, ENSURE protection of local variables through the "use" builtin to inform -// the garbage collector the variables remain in use if: -// -// -- The value is not a pointer (e.g., int32, struct) -// -- The value is not referenced by the method after passing the pointer to Windows -// -// See http://golang.org/doc/go1.3. -//=========================================================================================================== - -var ( - kernel32DLL = syscall.NewLazyDLL("kernel32.dll") - - getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo") - setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo") - setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition") - setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode") - getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo") - setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize") - scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA") - setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute") - setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo") - writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW") - readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW") - waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject") -) - -// Windows Console constants -const ( - // Console modes - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. - ENABLE_PROCESSED_INPUT = 0x0001 - ENABLE_LINE_INPUT = 0x0002 - ENABLE_ECHO_INPUT = 0x0004 - ENABLE_WINDOW_INPUT = 0x0008 - ENABLE_MOUSE_INPUT = 0x0010 - ENABLE_INSERT_MODE = 0x0020 - ENABLE_QUICK_EDIT_MODE = 0x0040 - ENABLE_EXTENDED_FLAGS = 0x0080 - ENABLE_AUTO_POSITION = 0x0100 - ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200 - - ENABLE_PROCESSED_OUTPUT = 0x0001 - ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 - ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 - DISABLE_NEWLINE_AUTO_RETURN = 0x0008 - ENABLE_LVB_GRID_WORLDWIDE = 0x0010 - - // Character attributes - // Note: - // -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan). - // Clearing all foreground or background colors results in black; setting all creates white. - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes. - FOREGROUND_BLUE uint16 = 0x0001 - FOREGROUND_GREEN uint16 = 0x0002 - FOREGROUND_RED uint16 = 0x0004 - FOREGROUND_INTENSITY uint16 = 0x0008 - FOREGROUND_MASK uint16 = 0x000F - - BACKGROUND_BLUE uint16 = 0x0010 - BACKGROUND_GREEN uint16 = 0x0020 - BACKGROUND_RED uint16 = 0x0040 - BACKGROUND_INTENSITY uint16 = 0x0080 - BACKGROUND_MASK uint16 = 0x00F0 - - COMMON_LVB_MASK uint16 = 0xFF00 - COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000 - COMMON_LVB_UNDERSCORE uint16 = 0x8000 - - // Input event types - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. - KEY_EVENT = 0x0001 - MOUSE_EVENT = 0x0002 - WINDOW_BUFFER_SIZE_EVENT = 0x0004 - MENU_EVENT = 0x0008 - FOCUS_EVENT = 0x0010 - - // WaitForSingleObject return codes - WAIT_ABANDONED = 0x00000080 - WAIT_FAILED = 0xFFFFFFFF - WAIT_SIGNALED = 0x0000000 - WAIT_TIMEOUT = 0x00000102 - - // WaitForSingleObject wait duration - WAIT_INFINITE = 0xFFFFFFFF - WAIT_ONE_SECOND = 1000 - WAIT_HALF_SECOND = 500 - WAIT_QUARTER_SECOND = 250 -) - -// Windows API Console types -// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682101(v=vs.85).aspx for Console specific types (e.g., COORD) -// -- See https://msdn.microsoft.com/en-us/library/aa296569(v=vs.60).aspx for comments on alignment -type ( - CHAR_INFO struct { - UnicodeChar uint16 - Attributes uint16 - } - - CONSOLE_CURSOR_INFO struct { - Size uint32 - Visible int32 - } - - CONSOLE_SCREEN_BUFFER_INFO struct { - Size COORD - CursorPosition COORD - Attributes uint16 - Window SMALL_RECT - MaximumWindowSize COORD - } - - COORD struct { - X int16 - Y int16 - } - - SMALL_RECT struct { - Left int16 - Top int16 - Right int16 - Bottom int16 - } - - // INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. - INPUT_RECORD struct { - EventType uint16 - KeyEvent KEY_EVENT_RECORD - } - - KEY_EVENT_RECORD struct { - KeyDown int32 - RepeatCount uint16 - VirtualKeyCode uint16 - VirtualScanCode uint16 - UnicodeChar uint16 - ControlKeyState uint32 - } - - WINDOW_BUFFER_SIZE struct { - Size COORD - } -) - -// boolToBOOL converts a Go bool into a Windows int32. -func boolToBOOL(f bool) int32 { - if f { - return int32(1) - } else { - return int32(0) - } -} - -// GetConsoleCursorInfo retrieves information about the size and visiblity of the console cursor. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683163(v=vs.85).aspx. -func GetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { - r1, r2, err := getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) - return checkError(r1, r2, err) -} - -// SetConsoleCursorInfo sets the size and visiblity of the console cursor. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx. -func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { - r1, r2, err := setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) - return checkError(r1, r2, err) -} - -// SetConsoleCursorPosition location of the console cursor. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx. -func SetConsoleCursorPosition(handle uintptr, coord COORD) error { - r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord)) - use(coord) - return checkError(r1, r2, err) -} - -// GetConsoleMode gets the console mode for given file descriptor -// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx. -func GetConsoleMode(handle uintptr) (mode uint32, err error) { - err = syscall.GetConsoleMode(syscall.Handle(handle), &mode) - return mode, err -} - -// SetConsoleMode sets the console mode for given file descriptor -// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. -func SetConsoleMode(handle uintptr, mode uint32) error { - r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0) - use(mode) - return checkError(r1, r2, err) -} - -// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer. -// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx. -func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) { - info := CONSOLE_SCREEN_BUFFER_INFO{} - err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)) - if err != nil { - return nil, err - } - return &info, nil -} - -func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error { - r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char))) - use(scrollRect) - use(clipRect) - use(destOrigin) - use(char) - return checkError(r1, r2, err) -} - -// SetConsoleScreenBufferSize sets the size of the console screen buffer. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx. -func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error { - r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord)) - use(coord) - return checkError(r1, r2, err) -} - -// SetConsoleTextAttribute sets the attributes of characters written to the -// console screen buffer by the WriteFile or WriteConsole function. -// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx. -func SetConsoleTextAttribute(handle uintptr, attribute uint16) error { - r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0) - use(attribute) - return checkError(r1, r2, err) -} - -// SetConsoleWindowInfo sets the size and position of the console screen buffer's window. -// Note that the size and location must be within and no larger than the backing console screen buffer. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx. -func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error { - r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect))) - use(isAbsolute) - use(rect) - return checkError(r1, r2, err) -} - -// WriteConsoleOutput writes the CHAR_INFOs from the provided buffer to the active console buffer. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx. -func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error { - r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion))) - use(buffer) - use(bufferSize) - use(bufferCoord) - return checkError(r1, r2, err) -} - -// ReadConsoleInput reads (and removes) data from the console input buffer. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx. -func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error { - r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count))) - use(buffer) - return checkError(r1, r2, err) -} - -// WaitForSingleObject waits for the passed handle to be signaled. -// It returns true if the handle was signaled; false otherwise. -// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx. -func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) { - r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait))) - switch r1 { - case WAIT_ABANDONED, WAIT_TIMEOUT: - return false, nil - case WAIT_SIGNALED: - return true, nil - } - use(msWait) - return false, err -} - -// String helpers -func (info CONSOLE_SCREEN_BUFFER_INFO) String() string { - return fmt.Sprintf("Size(%v) Cursor(%v) Window(%v) Max(%v)", info.Size, info.CursorPosition, info.Window, info.MaximumWindowSize) -} - -func (coord COORD) String() string { - return fmt.Sprintf("%v,%v", coord.X, coord.Y) -} - -func (rect SMALL_RECT) String() string { - return fmt.Sprintf("(%v,%v),(%v,%v)", rect.Left, rect.Top, rect.Right, rect.Bottom) -} - -// checkError evaluates the results of a Windows API call and returns the error if it failed. -func checkError(r1, r2 uintptr, err error) error { - // Windows APIs return non-zero to indicate success - if r1 != 0 { - return nil - } - - // Return the error if provided, otherwise default to EINVAL - if err != nil { - return err - } - return syscall.EINVAL -} - -// coordToPointer converts a COORD into a uintptr (by fooling the type system). -func coordToPointer(c COORD) uintptr { - // Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass. - return uintptr(*((*uint32)(unsafe.Pointer(&c)))) -} - -// use is a no-op, but the compiler cannot see that it is. -// Calling use(p) ensures that p is kept live until that point. -func use(p interface{}) {} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go b/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go deleted file mode 100644 index cbec8f728f49..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go +++ /dev/null @@ -1,100 +0,0 @@ -// +build windows - -package winterm - -import "github.com/Azure/go-ansiterm" - -const ( - FOREGROUND_COLOR_MASK = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE - BACKGROUND_COLOR_MASK = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE -) - -// collectAnsiIntoWindowsAttributes modifies the passed Windows text mode flags to reflect the -// request represented by the passed ANSI mode. -func collectAnsiIntoWindowsAttributes(windowsMode uint16, inverted bool, baseMode uint16, ansiMode int16) (uint16, bool) { - switch ansiMode { - - // Mode styles - case ansiterm.ANSI_SGR_BOLD: - windowsMode = windowsMode | FOREGROUND_INTENSITY - - case ansiterm.ANSI_SGR_DIM, ansiterm.ANSI_SGR_BOLD_DIM_OFF: - windowsMode &^= FOREGROUND_INTENSITY - - case ansiterm.ANSI_SGR_UNDERLINE: - windowsMode = windowsMode | COMMON_LVB_UNDERSCORE - - case ansiterm.ANSI_SGR_REVERSE: - inverted = true - - case ansiterm.ANSI_SGR_REVERSE_OFF: - inverted = false - - case ansiterm.ANSI_SGR_UNDERLINE_OFF: - windowsMode &^= COMMON_LVB_UNDERSCORE - - // Foreground colors - case ansiterm.ANSI_SGR_FOREGROUND_DEFAULT: - windowsMode = (windowsMode &^ FOREGROUND_MASK) | (baseMode & FOREGROUND_MASK) - - case ansiterm.ANSI_SGR_FOREGROUND_BLACK: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) - - case ansiterm.ANSI_SGR_FOREGROUND_RED: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED - - case ansiterm.ANSI_SGR_FOREGROUND_GREEN: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN - - case ansiterm.ANSI_SGR_FOREGROUND_YELLOW: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN - - case ansiterm.ANSI_SGR_FOREGROUND_BLUE: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_BLUE - - case ansiterm.ANSI_SGR_FOREGROUND_MAGENTA: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_BLUE - - case ansiterm.ANSI_SGR_FOREGROUND_CYAN: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE - - case ansiterm.ANSI_SGR_FOREGROUND_WHITE: - windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE - - // Background colors - case ansiterm.ANSI_SGR_BACKGROUND_DEFAULT: - // Black with no intensity - windowsMode = (windowsMode &^ BACKGROUND_MASK) | (baseMode & BACKGROUND_MASK) - - case ansiterm.ANSI_SGR_BACKGROUND_BLACK: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) - - case ansiterm.ANSI_SGR_BACKGROUND_RED: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED - - case ansiterm.ANSI_SGR_BACKGROUND_GREEN: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN - - case ansiterm.ANSI_SGR_BACKGROUND_YELLOW: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN - - case ansiterm.ANSI_SGR_BACKGROUND_BLUE: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_BLUE - - case ansiterm.ANSI_SGR_BACKGROUND_MAGENTA: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_BLUE - - case ansiterm.ANSI_SGR_BACKGROUND_CYAN: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE - - case ansiterm.ANSI_SGR_BACKGROUND_WHITE: - windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE - } - - return windowsMode, inverted -} - -// invertAttributes inverts the foreground and background colors of a Windows attributes value -func invertAttributes(windowsMode uint16) uint16 { - return (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4) -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go deleted file mode 100644 index 3ee06ea72824..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go +++ /dev/null @@ -1,101 +0,0 @@ -// +build windows - -package winterm - -const ( - horizontal = iota - vertical -) - -func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT { - if h.originMode { - sr := h.effectiveSr(info.Window) - return SMALL_RECT{ - Top: sr.top, - Bottom: sr.bottom, - Left: 0, - Right: info.Size.X - 1, - } - } else { - return SMALL_RECT{ - Top: info.Window.Top, - Bottom: info.Window.Bottom, - Left: 0, - Right: info.Size.X - 1, - } - } -} - -// setCursorPosition sets the cursor to the specified position, bounded to the screen size -func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL_RECT) error { - position.X = ensureInRange(position.X, window.Left, window.Right) - position.Y = ensureInRange(position.Y, window.Top, window.Bottom) - err := SetConsoleCursorPosition(h.fd, position) - if err != nil { - return err - } - h.logf("Cursor position set: (%d, %d)", position.X, position.Y) - return err -} - -func (h *windowsAnsiEventHandler) moveCursorVertical(param int) error { - return h.moveCursor(vertical, param) -} - -func (h *windowsAnsiEventHandler) moveCursorHorizontal(param int) error { - return h.moveCursor(horizontal, param) -} - -func (h *windowsAnsiEventHandler) moveCursor(moveMode int, param int) error { - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - position := info.CursorPosition - switch moveMode { - case horizontal: - position.X += int16(param) - case vertical: - position.Y += int16(param) - } - - if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { - return err - } - - return nil -} - -func (h *windowsAnsiEventHandler) moveCursorLine(param int) error { - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - position := info.CursorPosition - position.X = 0 - position.Y += int16(param) - - if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { - return err - } - - return nil -} - -func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error { - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - position := info.CursorPosition - position.X = int16(param) - 1 - - if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go deleted file mode 100644 index 244b5fa25efb..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go +++ /dev/null @@ -1,84 +0,0 @@ -// +build windows - -package winterm - -import "github.com/Azure/go-ansiterm" - -func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD, toCoord COORD) error { - // Ignore an invalid (negative area) request - if toCoord.Y < fromCoord.Y { - return nil - } - - var err error - - var coordStart = COORD{} - var coordEnd = COORD{} - - xCurrent, yCurrent := fromCoord.X, fromCoord.Y - xEnd, yEnd := toCoord.X, toCoord.Y - - // Clear any partial initial line - if xCurrent > 0 { - coordStart.X, coordStart.Y = xCurrent, yCurrent - coordEnd.X, coordEnd.Y = xEnd, yCurrent - - err = h.clearRect(attributes, coordStart, coordEnd) - if err != nil { - return err - } - - xCurrent = 0 - yCurrent += 1 - } - - // Clear intervening rectangular section - if yCurrent < yEnd { - coordStart.X, coordStart.Y = xCurrent, yCurrent - coordEnd.X, coordEnd.Y = xEnd, yEnd-1 - - err = h.clearRect(attributes, coordStart, coordEnd) - if err != nil { - return err - } - - xCurrent = 0 - yCurrent = yEnd - } - - // Clear remaining partial ending line - coordStart.X, coordStart.Y = xCurrent, yCurrent - coordEnd.X, coordEnd.Y = xEnd, yEnd - - err = h.clearRect(attributes, coordStart, coordEnd) - if err != nil { - return err - } - - return nil -} - -func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error { - region := SMALL_RECT{Top: fromCoord.Y, Left: fromCoord.X, Bottom: toCoord.Y, Right: toCoord.X} - width := toCoord.X - fromCoord.X + 1 - height := toCoord.Y - fromCoord.Y + 1 - size := uint32(width) * uint32(height) - - if size <= 0 { - return nil - } - - buffer := make([]CHAR_INFO, size) - - char := CHAR_INFO{ansiterm.FILL_CHARACTER, attributes} - for i := 0; i < int(size); i++ { - buffer[i] = char - } - - err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, ®ion) - if err != nil { - return err - } - - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go deleted file mode 100644 index 2d27fa1d0288..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go +++ /dev/null @@ -1,118 +0,0 @@ -// +build windows - -package winterm - -// effectiveSr gets the current effective scroll region in buffer coordinates -func (h *windowsAnsiEventHandler) effectiveSr(window SMALL_RECT) scrollRegion { - top := addInRange(window.Top, h.sr.top, window.Top, window.Bottom) - bottom := addInRange(window.Top, h.sr.bottom, window.Top, window.Bottom) - if top >= bottom { - top = window.Top - bottom = window.Bottom - } - return scrollRegion{top: top, bottom: bottom} -} - -func (h *windowsAnsiEventHandler) scrollUp(param int) error { - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - sr := h.effectiveSr(info.Window) - return h.scroll(param, sr, info) -} - -func (h *windowsAnsiEventHandler) scrollDown(param int) error { - return h.scrollUp(-param) -} - -func (h *windowsAnsiEventHandler) deleteLines(param int) error { - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - start := info.CursorPosition.Y - sr := h.effectiveSr(info.Window) - // Lines cannot be inserted or deleted outside the scrolling region. - if start >= sr.top && start <= sr.bottom { - sr.top = start - return h.scroll(param, sr, info) - } else { - return nil - } -} - -func (h *windowsAnsiEventHandler) insertLines(param int) error { - return h.deleteLines(-param) -} - -// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates. -func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error { - h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom) - h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom) - - // Copy from and clip to the scroll region (full buffer width) - scrollRect := SMALL_RECT{ - Top: sr.top, - Bottom: sr.bottom, - Left: 0, - Right: info.Size.X - 1, - } - - // Origin to which area should be copied - destOrigin := COORD{ - X: 0, - Y: sr.top - int16(param), - } - - char := CHAR_INFO{ - UnicodeChar: ' ', - Attributes: h.attributes, - } - - if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { - return err - } - return nil -} - -func (h *windowsAnsiEventHandler) deleteCharacters(param int) error { - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - return h.scrollLine(param, info.CursorPosition, info) -} - -func (h *windowsAnsiEventHandler) insertCharacters(param int) error { - return h.deleteCharacters(-param) -} - -// scrollLine scrolls a line horizontally starting at the provided position by a number of columns. -func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *CONSOLE_SCREEN_BUFFER_INFO) error { - // Copy from and clip to the scroll region (full buffer width) - scrollRect := SMALL_RECT{ - Top: position.Y, - Bottom: position.Y, - Left: position.X, - Right: info.Size.X - 1, - } - - // Origin to which area should be copied - destOrigin := COORD{ - X: position.X - int16(columns), - Y: position.Y, - } - - char := CHAR_INFO{ - UnicodeChar: ' ', - Attributes: h.attributes, - } - - if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { - return err - } - return nil -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go deleted file mode 100644 index afa7635d77ba..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build windows - -package winterm - -// AddInRange increments a value by the passed quantity while ensuring the values -// always remain within the supplied min / max range. -func addInRange(n int16, increment int16, min int16, max int16) int16 { - return ensureInRange(n+increment, min, max) -} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go deleted file mode 100644 index 2d40fb75ad0b..000000000000 --- a/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go +++ /dev/null @@ -1,743 +0,0 @@ -// +build windows - -package winterm - -import ( - "bytes" - "log" - "os" - "strconv" - - "github.com/Azure/go-ansiterm" -) - -type windowsAnsiEventHandler struct { - fd uintptr - file *os.File - infoReset *CONSOLE_SCREEN_BUFFER_INFO - sr scrollRegion - buffer bytes.Buffer - attributes uint16 - inverted bool - wrapNext bool - drewMarginByte bool - originMode bool - marginByte byte - curInfo *CONSOLE_SCREEN_BUFFER_INFO - curPos COORD - logf func(string, ...interface{}) -} - -type Option func(*windowsAnsiEventHandler) - -func WithLogf(f func(string, ...interface{})) Option { - return func(w *windowsAnsiEventHandler) { - w.logf = f - } -} - -func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler { - infoReset, err := GetConsoleScreenBufferInfo(fd) - if err != nil { - return nil - } - - h := &windowsAnsiEventHandler{ - fd: fd, - file: file, - infoReset: infoReset, - attributes: infoReset.Attributes, - } - for _, o := range opts { - o(h) - } - - if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { - logFile, _ := os.Create("winEventHandler.log") - logger := log.New(logFile, "", log.LstdFlags) - if h.logf != nil { - l := h.logf - h.logf = func(s string, v ...interface{}) { - l(s, v...) - logger.Printf(s, v...) - } - } else { - h.logf = logger.Printf - } - } - - if h.logf == nil { - h.logf = func(string, ...interface{}) {} - } - - return h -} - -type scrollRegion struct { - top int16 - bottom int16 -} - -// simulateLF simulates a LF or CR+LF by scrolling if necessary to handle the -// current cursor position and scroll region settings, in which case it returns -// true. If no special handling is necessary, then it does nothing and returns -// false. -// -// In the false case, the caller should ensure that a carriage return -// and line feed are inserted or that the text is otherwise wrapped. -func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) { - if h.wrapNext { - if err := h.Flush(); err != nil { - return false, err - } - h.clearWrap() - } - pos, info, err := h.getCurrentInfo() - if err != nil { - return false, err - } - sr := h.effectiveSr(info.Window) - if pos.Y == sr.bottom { - // Scrolling is necessary. Let Windows automatically scroll if the scrolling region - // is the full window. - if sr.top == info.Window.Top && sr.bottom == info.Window.Bottom { - if includeCR { - pos.X = 0 - h.updatePos(pos) - } - return false, nil - } - - // A custom scroll region is active. Scroll the window manually to simulate - // the LF. - if err := h.Flush(); err != nil { - return false, err - } - h.logf("Simulating LF inside scroll region") - if err := h.scrollUp(1); err != nil { - return false, err - } - if includeCR { - pos.X = 0 - if err := SetConsoleCursorPosition(h.fd, pos); err != nil { - return false, err - } - } - return true, nil - - } else if pos.Y < info.Window.Bottom { - // Let Windows handle the LF. - pos.Y++ - if includeCR { - pos.X = 0 - } - h.updatePos(pos) - return false, nil - } else { - // The cursor is at the bottom of the screen but outside the scroll - // region. Skip the LF. - h.logf("Simulating LF outside scroll region") - if includeCR { - if err := h.Flush(); err != nil { - return false, err - } - pos.X = 0 - if err := SetConsoleCursorPosition(h.fd, pos); err != nil { - return false, err - } - } - return true, nil - } -} - -// executeLF executes a LF without a CR. -func (h *windowsAnsiEventHandler) executeLF() error { - handled, err := h.simulateLF(false) - if err != nil { - return err - } - if !handled { - // Windows LF will reset the cursor column position. Write the LF - // and restore the cursor position. - pos, _, err := h.getCurrentInfo() - if err != nil { - return err - } - h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) - if pos.X != 0 { - if err := h.Flush(); err != nil { - return err - } - h.logf("Resetting cursor position for LF without CR") - if err := SetConsoleCursorPosition(h.fd, pos); err != nil { - return err - } - } - } - return nil -} - -func (h *windowsAnsiEventHandler) Print(b byte) error { - if h.wrapNext { - h.buffer.WriteByte(h.marginByte) - h.clearWrap() - if _, err := h.simulateLF(true); err != nil { - return err - } - } - pos, info, err := h.getCurrentInfo() - if err != nil { - return err - } - if pos.X == info.Size.X-1 { - h.wrapNext = true - h.marginByte = b - } else { - pos.X++ - h.updatePos(pos) - h.buffer.WriteByte(b) - } - return nil -} - -func (h *windowsAnsiEventHandler) Execute(b byte) error { - switch b { - case ansiterm.ANSI_TAB: - h.logf("Execute(TAB)") - // Move to the next tab stop, but preserve auto-wrap if already set. - if !h.wrapNext { - pos, info, err := h.getCurrentInfo() - if err != nil { - return err - } - pos.X = (pos.X + 8) - pos.X%8 - if pos.X >= info.Size.X { - pos.X = info.Size.X - 1 - } - if err := h.Flush(); err != nil { - return err - } - if err := SetConsoleCursorPosition(h.fd, pos); err != nil { - return err - } - } - return nil - - case ansiterm.ANSI_BEL: - h.buffer.WriteByte(ansiterm.ANSI_BEL) - return nil - - case ansiterm.ANSI_BACKSPACE: - if h.wrapNext { - if err := h.Flush(); err != nil { - return err - } - h.clearWrap() - } - pos, _, err := h.getCurrentInfo() - if err != nil { - return err - } - if pos.X > 0 { - pos.X-- - h.updatePos(pos) - h.buffer.WriteByte(ansiterm.ANSI_BACKSPACE) - } - return nil - - case ansiterm.ANSI_VERTICAL_TAB, ansiterm.ANSI_FORM_FEED: - // Treat as true LF. - return h.executeLF() - - case ansiterm.ANSI_LINE_FEED: - // Simulate a CR and LF for now since there is no way in go-ansiterm - // to tell if the LF should include CR (and more things break when it's - // missing than when it's incorrectly added). - handled, err := h.simulateLF(true) - if handled || err != nil { - return err - } - return h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) - - case ansiterm.ANSI_CARRIAGE_RETURN: - if h.wrapNext { - if err := h.Flush(); err != nil { - return err - } - h.clearWrap() - } - pos, _, err := h.getCurrentInfo() - if err != nil { - return err - } - if pos.X != 0 { - pos.X = 0 - h.updatePos(pos) - h.buffer.WriteByte(ansiterm.ANSI_CARRIAGE_RETURN) - } - return nil - - default: - return nil - } -} - -func (h *windowsAnsiEventHandler) CUU(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CUU: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.moveCursorVertical(-param) -} - -func (h *windowsAnsiEventHandler) CUD(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CUD: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.moveCursorVertical(param) -} - -func (h *windowsAnsiEventHandler) CUF(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CUF: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.moveCursorHorizontal(param) -} - -func (h *windowsAnsiEventHandler) CUB(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CUB: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.moveCursorHorizontal(-param) -} - -func (h *windowsAnsiEventHandler) CNL(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CNL: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.moveCursorLine(param) -} - -func (h *windowsAnsiEventHandler) CPL(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CPL: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.moveCursorLine(-param) -} - -func (h *windowsAnsiEventHandler) CHA(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CHA: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.moveCursorColumn(param) -} - -func (h *windowsAnsiEventHandler) VPA(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("VPA: [[%d]]", param) - h.clearWrap() - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - window := h.getCursorWindow(info) - position := info.CursorPosition - position.Y = window.Top + int16(param) - 1 - return h.setCursorPosition(position, window) -} - -func (h *windowsAnsiEventHandler) CUP(row int, col int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("CUP: [[%d %d]]", row, col) - h.clearWrap() - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - window := h.getCursorWindow(info) - position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1} - return h.setCursorPosition(position, window) -} - -func (h *windowsAnsiEventHandler) HVP(row int, col int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("HVP: [[%d %d]]", row, col) - h.clearWrap() - return h.CUP(row, col) -} - -func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)}) - h.clearWrap() - return nil -} - -func (h *windowsAnsiEventHandler) DECOM(enable bool) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)}) - h.clearWrap() - h.originMode = enable - return h.CUP(1, 1) -} - -func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)}) - h.clearWrap() - if err := h.ED(2); err != nil { - return err - } - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - targetWidth := int16(80) - if use132 { - targetWidth = 132 - } - if info.Size.X < targetWidth { - if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { - h.logf("set buffer failed: %v", err) - return err - } - } - window := info.Window - window.Left = 0 - window.Right = targetWidth - 1 - if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { - h.logf("set window failed: %v", err) - return err - } - if info.Size.X > targetWidth { - if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { - h.logf("set buffer failed: %v", err) - return err - } - } - return SetConsoleCursorPosition(h.fd, COORD{0, 0}) -} - -func (h *windowsAnsiEventHandler) ED(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("ED: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - - // [J -- Erases from the cursor to the end of the screen, including the cursor position. - // [1J -- Erases from the beginning of the screen to the cursor, including the cursor position. - // [2J -- Erases the complete display. The cursor does not move. - // Notes: - // -- Clearing the entire buffer, versus just the Window, works best for Windows Consoles - - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - var start COORD - var end COORD - - switch param { - case 0: - start = info.CursorPosition - end = COORD{info.Size.X - 1, info.Size.Y - 1} - - case 1: - start = COORD{0, 0} - end = info.CursorPosition - - case 2: - start = COORD{0, 0} - end = COORD{info.Size.X - 1, info.Size.Y - 1} - } - - err = h.clearRange(h.attributes, start, end) - if err != nil { - return err - } - - // If the whole buffer was cleared, move the window to the top while preserving - // the window-relative cursor position. - if param == 2 { - pos := info.CursorPosition - window := info.Window - pos.Y -= window.Top - window.Bottom -= window.Top - window.Top = 0 - if err := SetConsoleCursorPosition(h.fd, pos); err != nil { - return err - } - if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { - return err - } - } - - return nil -} - -func (h *windowsAnsiEventHandler) EL(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("EL: [%v]", strconv.Itoa(param)) - h.clearWrap() - - // [K -- Erases from the cursor to the end of the line, including the cursor position. - // [1K -- Erases from the beginning of the line to the cursor, including the cursor position. - // [2K -- Erases the complete line. - - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - var start COORD - var end COORD - - switch param { - case 0: - start = info.CursorPosition - end = COORD{info.Size.X, info.CursorPosition.Y} - - case 1: - start = COORD{0, info.CursorPosition.Y} - end = info.CursorPosition - - case 2: - start = COORD{0, info.CursorPosition.Y} - end = COORD{info.Size.X, info.CursorPosition.Y} - } - - err = h.clearRange(h.attributes, start, end) - if err != nil { - return err - } - - return nil -} - -func (h *windowsAnsiEventHandler) IL(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("IL: [%v]", strconv.Itoa(param)) - h.clearWrap() - return h.insertLines(param) -} - -func (h *windowsAnsiEventHandler) DL(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("DL: [%v]", strconv.Itoa(param)) - h.clearWrap() - return h.deleteLines(param) -} - -func (h *windowsAnsiEventHandler) ICH(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("ICH: [%v]", strconv.Itoa(param)) - h.clearWrap() - return h.insertCharacters(param) -} - -func (h *windowsAnsiEventHandler) DCH(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("DCH: [%v]", strconv.Itoa(param)) - h.clearWrap() - return h.deleteCharacters(param) -} - -func (h *windowsAnsiEventHandler) SGR(params []int) error { - if err := h.Flush(); err != nil { - return err - } - strings := []string{} - for _, v := range params { - strings = append(strings, strconv.Itoa(v)) - } - - h.logf("SGR: [%v]", strings) - - if len(params) <= 0 { - h.attributes = h.infoReset.Attributes - h.inverted = false - } else { - for _, attr := range params { - - if attr == ansiterm.ANSI_SGR_RESET { - h.attributes = h.infoReset.Attributes - h.inverted = false - continue - } - - h.attributes, h.inverted = collectAnsiIntoWindowsAttributes(h.attributes, h.inverted, h.infoReset.Attributes, int16(attr)) - } - } - - attributes := h.attributes - if h.inverted { - attributes = invertAttributes(attributes) - } - err := SetConsoleTextAttribute(h.fd, attributes) - if err != nil { - return err - } - - return nil -} - -func (h *windowsAnsiEventHandler) SU(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("SU: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.scrollUp(param) -} - -func (h *windowsAnsiEventHandler) SD(param int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("SD: [%v]", []string{strconv.Itoa(param)}) - h.clearWrap() - return h.scrollDown(param) -} - -func (h *windowsAnsiEventHandler) DA(params []string) error { - h.logf("DA: [%v]", params) - // DA cannot be implemented because it must send data on the VT100 input stream, - // which is not available to go-ansiterm. - return nil -} - -func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error { - if err := h.Flush(); err != nil { - return err - } - h.logf("DECSTBM: [%d, %d]", top, bottom) - - // Windows is 0 indexed, Linux is 1 indexed - h.sr.top = int16(top - 1) - h.sr.bottom = int16(bottom - 1) - - // This command also moves the cursor to the origin. - h.clearWrap() - return h.CUP(1, 1) -} - -func (h *windowsAnsiEventHandler) RI() error { - if err := h.Flush(); err != nil { - return err - } - h.logf("RI: []") - h.clearWrap() - - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - sr := h.effectiveSr(info.Window) - if info.CursorPosition.Y == sr.top { - return h.scrollDown(1) - } - - return h.moveCursorVertical(-1) -} - -func (h *windowsAnsiEventHandler) IND() error { - h.logf("IND: []") - return h.executeLF() -} - -func (h *windowsAnsiEventHandler) Flush() error { - h.curInfo = nil - if h.buffer.Len() > 0 { - h.logf("Flush: [%s]", h.buffer.Bytes()) - if _, err := h.buffer.WriteTo(h.file); err != nil { - return err - } - } - - if h.wrapNext && !h.drewMarginByte { - h.logf("Flush: drawing margin byte '%c'", h.marginByte) - - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return err - } - - charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}} - size := COORD{1, 1} - position := COORD{0, 0} - region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y} - if err := WriteConsoleOutput(h.fd, charInfo, size, position, ®ion); err != nil { - return err - } - h.drewMarginByte = true - } - return nil -} - -// cacheConsoleInfo ensures that the current console screen information has been queried -// since the last call to Flush(). It must be called before accessing h.curInfo or h.curPos. -func (h *windowsAnsiEventHandler) getCurrentInfo() (COORD, *CONSOLE_SCREEN_BUFFER_INFO, error) { - if h.curInfo == nil { - info, err := GetConsoleScreenBufferInfo(h.fd) - if err != nil { - return COORD{}, nil, err - } - h.curInfo = info - h.curPos = info.CursorPosition - } - return h.curPos, h.curInfo, nil -} - -func (h *windowsAnsiEventHandler) updatePos(pos COORD) { - if h.curInfo == nil { - panic("failed to call getCurrentInfo before calling updatePos") - } - h.curPos = pos -} - -// clearWrap clears the state where the cursor is in the margin -// waiting for the next character before wrapping the line. This must -// be done before most operations that act on the cursor. -func (h *windowsAnsiEventHandler) clearWrap() { - h.wrapNext = false - h.drewMarginByte = false -} diff --git a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go b/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go deleted file mode 100644 index cf8d04b1b201..000000000000 --- a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go +++ /dev/null @@ -1,283 +0,0 @@ -package jsonmessage // import "github.com/docker/docker/pkg/jsonmessage" - -import ( - "encoding/json" - "fmt" - "io" - "strings" - "time" - - units "github.com/docker/go-units" - "github.com/moby/term" - "github.com/morikuni/aec" -) - -// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to -// ensure the formatted time isalways the same number of characters. -const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" - -// JSONError wraps a concrete Code and Message, `Code` is -// is an integer error code, `Message` is the error message. -type JSONError struct { - Code int `json:"code,omitempty"` - Message string `json:"message,omitempty"` -} - -func (e *JSONError) Error() string { - return e.Message -} - -// JSONProgress describes a Progress. terminalFd is the fd of the current terminal, -// Start is the initial value for the operation. Current is the current status and -// value of the progress made towards Total. Total is the end value describing when -// we made 100% progress for an operation. -type JSONProgress struct { - terminalFd uintptr - Current int64 `json:"current,omitempty"` - Total int64 `json:"total,omitempty"` - Start int64 `json:"start,omitempty"` - // If true, don't show xB/yB - HideCounts bool `json:"hidecounts,omitempty"` - Units string `json:"units,omitempty"` - nowFunc func() time.Time - winSize int -} - -func (p *JSONProgress) String() string { - var ( - width = p.width() - pbBox string - numbersBox string - timeLeftBox string - ) - if p.Current <= 0 && p.Total <= 0 { - return "" - } - if p.Total <= 0 { - switch p.Units { - case "": - current := units.HumanSize(float64(p.Current)) - return fmt.Sprintf("%8v", current) - default: - return fmt.Sprintf("%d %s", p.Current, p.Units) - } - } - - percentage := int(float64(p.Current)/float64(p.Total)*100) / 2 - if percentage > 50 { - percentage = 50 - } - if width > 110 { - // this number can't be negative gh#7136 - numSpaces := 0 - if 50-percentage > 0 { - numSpaces = 50 - percentage - } - pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", numSpaces)) - } - - switch { - case p.HideCounts: - case p.Units == "": // no units, use bytes - current := units.HumanSize(float64(p.Current)) - total := units.HumanSize(float64(p.Total)) - - numbersBox = fmt.Sprintf("%8v/%v", current, total) - - if p.Current > p.Total { - // remove total display if the reported current is wonky. - numbersBox = fmt.Sprintf("%8v", current) - } - default: - numbersBox = fmt.Sprintf("%d/%d %s", p.Current, p.Total, p.Units) - - if p.Current > p.Total { - // remove total display if the reported current is wonky. - numbersBox = fmt.Sprintf("%d %s", p.Current, p.Units) - } - } - - if p.Current > 0 && p.Start > 0 && percentage < 50 { - fromStart := p.now().Sub(time.Unix(p.Start, 0)) - perEntry := fromStart / time.Duration(p.Current) - left := time.Duration(p.Total-p.Current) * perEntry - left = (left / time.Second) * time.Second - - if width > 50 { - timeLeftBox = " " + left.String() - } - } - return pbBox + numbersBox + timeLeftBox -} - -// shim for testing -func (p *JSONProgress) now() time.Time { - if p.nowFunc == nil { - p.nowFunc = func() time.Time { - return time.Now().UTC() - } - } - return p.nowFunc() -} - -// shim for testing -func (p *JSONProgress) width() int { - if p.winSize != 0 { - return p.winSize - } - ws, err := term.GetWinsize(p.terminalFd) - if err == nil { - return int(ws.Width) - } - return 200 -} - -// JSONMessage defines a message struct. It describes -// the created time, where it from, status, ID of the -// message. It's used for docker events. -type JSONMessage struct { - Stream string `json:"stream,omitempty"` - Status string `json:"status,omitempty"` - Progress *JSONProgress `json:"progressDetail,omitempty"` - ProgressMessage string `json:"progress,omitempty"` // deprecated - ID string `json:"id,omitempty"` - From string `json:"from,omitempty"` - Time int64 `json:"time,omitempty"` - TimeNano int64 `json:"timeNano,omitempty"` - Error *JSONError `json:"errorDetail,omitempty"` - ErrorMessage string `json:"error,omitempty"` // deprecated - // Aux contains out-of-band data, such as digests for push signing and image id after building. - Aux *json.RawMessage `json:"aux,omitempty"` -} - -func clearLine(out io.Writer) { - eraseMode := aec.EraseModes.All - cl := aec.EraseLine(eraseMode) - fmt.Fprint(out, cl) -} - -func cursorUp(out io.Writer, l uint) { - fmt.Fprint(out, aec.Up(l)) -} - -func cursorDown(out io.Writer, l uint) { - fmt.Fprint(out, aec.Down(l)) -} - -// Display displays the JSONMessage to `out`. If `isTerminal` is true, it will erase the -// entire current line when displaying the progressbar. -func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { - if jm.Error != nil { - if jm.Error.Code == 401 { - return fmt.Errorf("authentication is required") - } - return jm.Error - } - var endl string - if isTerminal && jm.Stream == "" && jm.Progress != nil { - clearLine(out) - endl = "\r" - fmt.Fprint(out, endl) - } else if jm.Progress != nil && jm.Progress.String() != "" { // disable progressbar in non-terminal - return nil - } - if jm.TimeNano != 0 { - fmt.Fprintf(out, "%s ", time.Unix(0, jm.TimeNano).Format(RFC3339NanoFixed)) - } else if jm.Time != 0 { - fmt.Fprintf(out, "%s ", time.Unix(jm.Time, 0).Format(RFC3339NanoFixed)) - } - if jm.ID != "" { - fmt.Fprintf(out, "%s: ", jm.ID) - } - if jm.From != "" { - fmt.Fprintf(out, "(from %s) ", jm.From) - } - if jm.Progress != nil && isTerminal { - fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl) - } else if jm.ProgressMessage != "" { // deprecated - fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl) - } else if jm.Stream != "" { - fmt.Fprintf(out, "%s%s", jm.Stream, endl) - } else { - fmt.Fprintf(out, "%s%s\n", jm.Status, endl) - } - return nil -} - -// DisplayJSONMessagesStream displays a json message stream from `in` to `out`, `isTerminal` -// describes if `out` is a terminal. If this is the case, it will print `\n` at the end of -// each line and move the cursor while displaying. -func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error { - var ( - dec = json.NewDecoder(in) - ids = make(map[string]uint) - ) - - for { - var diff uint - var jm JSONMessage - if err := dec.Decode(&jm); err != nil { - if err == io.EOF { - break - } - return err - } - - if jm.Aux != nil { - if auxCallback != nil { - auxCallback(jm) - } - continue - } - - if jm.Progress != nil { - jm.Progress.terminalFd = terminalFd - } - if jm.ID != "" && (jm.Progress != nil || jm.ProgressMessage != "") { - line, ok := ids[jm.ID] - if !ok { - // NOTE: This approach of using len(id) to - // figure out the number of lines of history - // only works as long as we clear the history - // when we output something that's not - // accounted for in the map, such as a line - // with no ID. - line = uint(len(ids)) - ids[jm.ID] = line - if isTerminal { - fmt.Fprintf(out, "\n") - } - } - diff = uint(len(ids)) - line - if isTerminal { - cursorUp(out, diff) - } - } else { - // When outputting something that isn't progress - // output, clear the history of previous lines. We - // don't want progress entries from some previous - // operation to be updated (for example, pull -a - // with multiple tags). - ids = make(map[string]uint) - } - err := jm.Display(out, isTerminal) - if jm.ID != "" && isTerminal { - cursorDown(out, diff) - } - if err != nil { - return err - } - } - return nil -} - -type stream interface { - io.Writer - FD() uintptr - IsTerminal() bool -} - -// DisplayJSONMessagesToStream prints json messages to the output stream -func DisplayJSONMessagesToStream(in io.Reader, stream stream, auxCallback func(JSONMessage)) error { - return DisplayJSONMessagesStream(in, stream, stream.FD(), stream.IsTerminal(), auxCallback) -} diff --git a/vendor/github.com/docker/docker/pkg/stringid/README.md b/vendor/github.com/docker/docker/pkg/stringid/README.md deleted file mode 100644 index 37a5098fd988..000000000000 --- a/vendor/github.com/docker/docker/pkg/stringid/README.md +++ /dev/null @@ -1 +0,0 @@ -This package provides helper functions for dealing with string identifiers diff --git a/vendor/github.com/docker/docker/pkg/stringid/stringid.go b/vendor/github.com/docker/docker/pkg/stringid/stringid.go deleted file mode 100644 index 5fe071d6284e..000000000000 --- a/vendor/github.com/docker/docker/pkg/stringid/stringid.go +++ /dev/null @@ -1,63 +0,0 @@ -// Package stringid provides helper functions for dealing with string identifiers -package stringid // import "github.com/docker/docker/pkg/stringid" - -import ( - "crypto/rand" - "encoding/hex" - "fmt" - "regexp" - "strconv" - "strings" -) - -const shortLen = 12 - -var ( - validShortID = regexp.MustCompile("^[a-f0-9]{12}$") - validHex = regexp.MustCompile(`^[a-f0-9]{64}$`) -) - -// IsShortID determines if an arbitrary string *looks like* a short ID. -func IsShortID(id string) bool { - return validShortID.MatchString(id) -} - -// TruncateID returns a shorthand version of a string identifier for convenience. -// A collision with other shorthands is very unlikely, but possible. -// In case of a collision a lookup with TruncIndex.Get() will fail, and the caller -// will need to use a longer prefix, or the full-length Id. -func TruncateID(id string) string { - if i := strings.IndexRune(id, ':'); i >= 0 { - id = id[i+1:] - } - if len(id) > shortLen { - id = id[:shortLen] - } - return id -} - -// GenerateRandomID returns a unique id. -func GenerateRandomID() string { - b := make([]byte, 32) - for { - if _, err := rand.Read(b); err != nil { - panic(err) // This shouldn't happen - } - id := hex.EncodeToString(b) - // if we try to parse the truncated for as an int and we don't have - // an error then the value is all numeric and causes issues when - // used as a hostname. ref #3869 - if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil { - continue - } - return id - } -} - -// ValidateID checks whether an ID string is a valid image ID. -func ValidateID(id string) error { - if ok := validHex.MatchString(id); !ok { - return fmt.Errorf("image ID %q is invalid", id) - } - return nil -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/config.go b/vendor/github.com/docker/docker/testutil/daemon/config.go deleted file mode 100644 index 1bf182ae2890..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/config.go +++ /dev/null @@ -1,72 +0,0 @@ -package daemon - -import ( - "context" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "gotest.tools/v3/assert" -) - -// ConfigConstructor defines a swarm config constructor -type ConfigConstructor func(*swarm.Config) - -// CreateConfig creates a config given the specified spec -func (d *Daemon) CreateConfig(t testing.TB, configSpec swarm.ConfigSpec) string { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - scr, err := cli.ConfigCreate(context.Background(), configSpec) - assert.NilError(t, err) - return scr.ID -} - -// ListConfigs returns the list of the current swarm configs -func (d *Daemon) ListConfigs(t testing.TB) []swarm.Config { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - configs, err := cli.ConfigList(context.Background(), types.ConfigListOptions{}) - assert.NilError(t, err) - return configs -} - -// GetConfig returns a swarm config identified by the specified id -func (d *Daemon) GetConfig(t testing.TB, id string) *swarm.Config { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - config, _, err := cli.ConfigInspectWithRaw(context.Background(), id) - assert.NilError(t, err) - return &config -} - -// DeleteConfig removes the swarm config identified by the specified id -func (d *Daemon) DeleteConfig(t testing.TB, id string) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - err := cli.ConfigRemove(context.Background(), id) - assert.NilError(t, err) -} - -// UpdateConfig updates the swarm config identified by the specified id -// Currently, only label update is supported. -func (d *Daemon) UpdateConfig(t testing.TB, id string, f ...ConfigConstructor) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - config := d.GetConfig(t, id) - for _, fn := range f { - fn(config) - } - - err := cli.ConfigUpdate(context.Background(), config.ID, config.Version, config.Spec) - assert.NilError(t, err) -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/container.go b/vendor/github.com/docker/docker/testutil/daemon/container.go deleted file mode 100644 index 8e88e7b202b8..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/container.go +++ /dev/null @@ -1,36 +0,0 @@ -package daemon - -import ( - "context" - "testing" - - "github.com/docker/docker/api/types" - "gotest.tools/v3/assert" -) - -// ActiveContainers returns the list of ids of the currently running containers -func (d *Daemon) ActiveContainers(t testing.TB) []string { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) - assert.NilError(t, err) - - ids := make([]string, len(containers)) - for i, c := range containers { - ids[i] = c.ID - } - return ids -} - -// FindContainerIP returns the ip of the specified container -func (d *Daemon) FindContainerIP(t testing.TB, id string) string { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - i, err := cli.ContainerInspect(context.Background(), id) - assert.NilError(t, err) - return i.NetworkSettings.IPAddress -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/daemon.go b/vendor/github.com/docker/docker/testutil/daemon/daemon.go deleted file mode 100644 index 9d9fa5e57e5f..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/daemon.go +++ /dev/null @@ -1,867 +0,0 @@ -package daemon // import "github.com/docker/docker/testutil/daemon" - -import ( - "context" - "encoding/json" - "net/http" - "os" - "os/exec" - "os/user" - "path/filepath" - "strconv" - "strings" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/testutil/request" - "github.com/docker/go-connections/sockets" - "github.com/docker/go-connections/tlsconfig" - "github.com/pkg/errors" - "gotest.tools/v3/assert" -) - -// LogT is the subset of the testing.TB interface used by the daemon. -type LogT interface { - Logf(string, ...interface{}) -} - -// nopLog is a no-op implementation of LogT that is used in daemons created by -// NewDaemon (where no testing.TB is available). -type nopLog struct{} - -func (nopLog) Logf(string, ...interface{}) {} - -const ( - defaultDockerdBinary = "dockerd" - defaultContainerdSocket = "/var/run/docker/containerd/containerd.sock" - defaultDockerdRootlessBinary = "dockerd-rootless.sh" - defaultUnixSocket = "/var/run/docker.sock" - defaultTLSHost = "localhost:2376" -) - -var errDaemonNotStarted = errors.New("daemon not started") - -// SockRoot holds the path of the default docker integration daemon socket -var SockRoot = filepath.Join(os.TempDir(), "docker-integration") - -type clientConfig struct { - transport *http.Transport - scheme string - addr string -} - -// Daemon represents a Docker daemon for the testing framework -type Daemon struct { - Root string - Folder string - Wait chan error - UseDefaultHost bool - UseDefaultTLSHost bool - - id string - logFile *os.File - cmd *exec.Cmd - storageDriver string - userlandProxy bool - defaultCgroupNamespaceMode string - execRoot string - experimental bool - init bool - dockerdBinary string - log LogT - pidFile string - args []string - containerdSocket string - rootlessUser *user.User - rootlessXDGRuntimeDir string - - // swarm related field - swarmListenAddr string - SwarmPort int // FIXME(vdemeester) should probably not be exported - DefaultAddrPool []string - SubnetSize uint32 - DataPathPort uint32 - OOMScoreAdjust int - // cached information - CachedInfo types.Info -} - -// NewDaemon returns a Daemon instance to be used for testing. -// The daemon will not automatically start. -// The daemon will modify and create files under workingDir. -func NewDaemon(workingDir string, ops ...Option) (*Daemon, error) { - storageDriver := os.Getenv("DOCKER_GRAPHDRIVER") - - if err := os.MkdirAll(SockRoot, 0700); err != nil { - return nil, errors.Wrapf(err, "failed to create daemon socket root %q", SockRoot) - } - - id := "d" + stringid.TruncateID(stringid.GenerateRandomID()) - dir := filepath.Join(workingDir, id) - daemonFolder, err := filepath.Abs(dir) - if err != nil { - return nil, err - } - daemonRoot := filepath.Join(daemonFolder, "root") - if err := os.MkdirAll(daemonRoot, 0755); err != nil { - return nil, errors.Wrapf(err, "failed to create daemon root %q", daemonRoot) - } - - userlandProxy := true - if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" { - if val, err := strconv.ParseBool(env); err != nil { - userlandProxy = val - } - } - d := &Daemon{ - id: id, - Folder: daemonFolder, - Root: daemonRoot, - storageDriver: storageDriver, - userlandProxy: userlandProxy, - // dxr stands for docker-execroot (shortened for avoiding unix(7) path length limitation) - execRoot: filepath.Join(os.TempDir(), "dxr", id), - dockerdBinary: defaultDockerdBinary, - swarmListenAddr: defaultSwarmListenAddr, - SwarmPort: DefaultSwarmPort, - log: nopLog{}, - containerdSocket: defaultContainerdSocket, - } - - for _, op := range ops { - op(d) - } - - if d.rootlessUser != nil { - if err := os.Chmod(SockRoot, 0777); err != nil { - return nil, err - } - uid, err := strconv.Atoi(d.rootlessUser.Uid) - if err != nil { - return nil, err - } - gid, err := strconv.Atoi(d.rootlessUser.Gid) - if err != nil { - return nil, err - } - if err := os.Chown(d.Folder, uid, gid); err != nil { - return nil, err - } - if err := os.Chown(d.Root, uid, gid); err != nil { - return nil, err - } - if err := os.MkdirAll(filepath.Dir(d.execRoot), 0700); err != nil { - return nil, err - } - if err := os.Chown(filepath.Dir(d.execRoot), uid, gid); err != nil { - return nil, err - } - if err := os.MkdirAll(d.execRoot, 0700); err != nil { - return nil, err - } - if err := os.Chown(d.execRoot, uid, gid); err != nil { - return nil, err - } - d.rootlessXDGRuntimeDir = filepath.Join(d.Folder, "xdgrun") - if err := os.MkdirAll(d.rootlessXDGRuntimeDir, 0700); err != nil { - return nil, err - } - if err := os.Chown(d.rootlessXDGRuntimeDir, uid, gid); err != nil { - return nil, err - } - d.containerdSocket = "" - } - - return d, nil -} - -// New returns a Daemon instance to be used for testing. -// This will create a directory such as d123456789 in the folder specified by -// $DOCKER_INTEGRATION_DAEMON_DEST or $DEST. -// The daemon will not automatically start. -func New(t testing.TB, ops ...Option) *Daemon { - t.Helper() - dest := os.Getenv("DOCKER_INTEGRATION_DAEMON_DEST") - if dest == "" { - dest = os.Getenv("DEST") - } - dest = filepath.Join(dest, t.Name()) - - assert.Check(t, dest != "", "Please set the DOCKER_INTEGRATION_DAEMON_DEST or the DEST environment variable") - - if os.Getenv("DOCKER_ROOTLESS") != "" { - if os.Getenv("DOCKER_REMAP_ROOT") != "" { - t.Skip("DOCKER_ROOTLESS doesn't support DOCKER_REMAP_ROOT currently") - } - if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" { - if val, err := strconv.ParseBool(env); err == nil && !val { - t.Skip("DOCKER_ROOTLESS doesn't support DOCKER_USERLANDPROXY=false") - } - } - ops = append(ops, WithRootlessUser("unprivilegeduser")) - } - ops = append(ops, WithOOMScoreAdjust(-500)) - - d, err := NewDaemon(dest, ops...) - assert.NilError(t, err, "could not create daemon at %q", dest) - if d.rootlessUser != nil && d.dockerdBinary != defaultDockerdBinary { - t.Skipf("DOCKER_ROOTLESS doesn't support specifying non-default dockerd binary path %q", d.dockerdBinary) - } - - return d -} - -// BinaryPath returns the binary and its arguments. -func (d *Daemon) BinaryPath() (string, error) { - dockerdBinary, err := exec.LookPath(d.dockerdBinary) - if err != nil { - return "", errors.Wrapf(err, "[%s] could not find docker binary in $PATH", d.id) - } - return dockerdBinary, nil -} - -// ContainersNamespace returns the containerd namespace used for containers. -func (d *Daemon) ContainersNamespace() string { - return d.id -} - -// RootDir returns the root directory of the daemon. -func (d *Daemon) RootDir() string { - return d.Root -} - -// ID returns the generated id of the daemon -func (d *Daemon) ID() string { - return d.id -} - -// StorageDriver returns the configured storage driver of the daemon -func (d *Daemon) StorageDriver() string { - return d.storageDriver -} - -// Sock returns the socket path of the daemon -func (d *Daemon) Sock() string { - return "unix://" + d.sockPath() -} - -func (d *Daemon) sockPath() string { - return filepath.Join(SockRoot, d.id+".sock") -} - -// LogFileName returns the path the daemon's log file -func (d *Daemon) LogFileName() string { - return d.logFile.Name() -} - -// ReadLogFile returns the content of the daemon log file -func (d *Daemon) ReadLogFile() ([]byte, error) { - _ = d.logFile.Sync() - return os.ReadFile(d.logFile.Name()) -} - -// NewClientT creates new client based on daemon's socket path -func (d *Daemon) NewClientT(t testing.TB, extraOpts ...client.Opt) *client.Client { - t.Helper() - - c, err := d.NewClient(extraOpts...) - assert.NilError(t, err, "[%s] could not create daemon client", d.id) - return c -} - -// NewClient creates new client based on daemon's socket path -func (d *Daemon) NewClient(extraOpts ...client.Opt) (*client.Client, error) { - clientOpts := []client.Opt{ - client.FromEnv, - client.WithHost(d.Sock()), - } - clientOpts = append(clientOpts, extraOpts...) - - return client.NewClientWithOpts(clientOpts...) -} - -// Cleanup cleans the daemon files : exec root (network namespaces, ...), swarmkit files -func (d *Daemon) Cleanup(t testing.TB) { - t.Helper() - cleanupMount(t, d) - cleanupRaftDir(t, d) - cleanupDaemonStorage(t, d) - cleanupNetworkNamespace(t, d) -} - -// Start starts the daemon and return once it is ready to receive requests. -func (d *Daemon) Start(t testing.TB, args ...string) { - t.Helper() - if err := d.StartWithError(args...); err != nil { - d.DumpStackAndQuit() // in case the daemon is stuck - t.Fatalf("[%s] failed to start daemon with arguments %v : %v", d.id, d.args, err) - } -} - -// StartWithError starts the daemon and return once it is ready to receive requests. -// It returns an error in case it couldn't start. -func (d *Daemon) StartWithError(args ...string) error { - logFile, err := os.OpenFile(filepath.Join(d.Folder, "docker.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600) - if err != nil { - return errors.Wrapf(err, "[%s] failed to create logfile", d.id) - } - - return d.StartWithLogFile(logFile, args...) -} - -// StartWithLogFile will start the daemon and attach its streams to a given file. -func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error { - d.handleUserns() - dockerdBinary, err := d.BinaryPath() - if err != nil { - return err - } - - if d.pidFile == "" { - d.pidFile = filepath.Join(d.Folder, "docker.pid") - } - - d.args = []string{} - if d.rootlessUser != nil { - if d.dockerdBinary != defaultDockerdBinary { - return errors.Errorf("[%s] DOCKER_ROOTLESS doesn't support non-default dockerd binary path %q", d.id, d.dockerdBinary) - } - dockerdBinary = "sudo" - d.args = append(d.args, - "-u", d.rootlessUser.Username, - "-E", "XDG_RUNTIME_DIR="+d.rootlessXDGRuntimeDir, - "-E", "HOME="+d.rootlessUser.HomeDir, - "-E", "PATH="+os.Getenv("PATH"), - "--", - defaultDockerdRootlessBinary, - ) - } - - d.args = append(d.args, - "--data-root", d.Root, - "--exec-root", d.execRoot, - "--pidfile", d.pidFile, - "--userland-proxy="+strconv.FormatBool(d.userlandProxy), - "--containerd-namespace", d.id, - "--containerd-plugins-namespace", d.id+"p", - ) - if d.containerdSocket != "" { - d.args = append(d.args, "--containerd", d.containerdSocket) - } - - if d.defaultCgroupNamespaceMode != "" { - d.args = append(d.args, "--default-cgroupns-mode", d.defaultCgroupNamespaceMode) - } - if d.experimental { - d.args = append(d.args, "--experimental") - } - if d.init { - d.args = append(d.args, "--init") - } - if !(d.UseDefaultHost || d.UseDefaultTLSHost) { - d.args = append(d.args, "--host", d.Sock()) - } - if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" { - d.args = append(d.args, "--userns-remap", root) - } - - // If we don't explicitly set the log-level or debug flag(-D) then - // turn on debug mode - foundLog := false - foundSd := false - for _, a := range providedArgs { - if strings.Contains(a, "--log-level") || strings.Contains(a, "-D") || strings.Contains(a, "--debug") { - foundLog = true - } - if strings.Contains(a, "--storage-driver") { - foundSd = true - } - } - if !foundLog { - d.args = append(d.args, "--debug") - } - if d.storageDriver != "" && !foundSd { - d.args = append(d.args, "--storage-driver", d.storageDriver) - } - - d.args = append(d.args, providedArgs...) - d.cmd = exec.Command(dockerdBinary, d.args...) - d.cmd.Env = append(os.Environ(), "DOCKER_SERVICE_PREFER_OFFLINE_IMAGE=1") - d.cmd.Stdout = out - d.cmd.Stderr = out - d.logFile = out - if d.rootlessUser != nil { - // sudo requires this for propagating signals - setsid(d.cmd) - } - - if err := d.cmd.Start(); err != nil { - return errors.Wrapf(err, "[%s] could not start daemon container", d.id) - } - - wait := make(chan error, 1) - - go func() { - ret := d.cmd.Wait() - d.log.Logf("[%s] exiting daemon", d.id) - // If we send before logging, we might accidentally log _after_ the test is done. - // As of Go 1.12, this incurs a panic instead of silently being dropped. - wait <- ret - close(wait) - }() - - d.Wait = wait - - clientConfig, err := d.getClientConfig() - if err != nil { - return err - } - client := &http.Client{ - Transport: clientConfig.transport, - } - - req, err := http.NewRequest(http.MethodGet, "/_ping", nil) - if err != nil { - return errors.Wrapf(err, "[%s] could not create new request", d.id) - } - req.URL.Host = clientConfig.addr - req.URL.Scheme = clientConfig.scheme - - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - defer cancel() - - // make sure daemon is ready to receive requests - for i := 0; ; i++ { - d.log.Logf("[%s] waiting for daemon to start", d.id) - - select { - case <-ctx.Done(): - return errors.Wrapf(ctx.Err(), "[%s] daemon exited and never started", d.id) - case err := <-d.Wait: - return errors.Wrapf(err, "[%s] daemon exited during startup", d.id) - default: - rctx, rcancel := context.WithTimeout(context.TODO(), 2*time.Second) - defer rcancel() - - resp, err := client.Do(req.WithContext(rctx)) - if err != nil { - if i > 2 { // don't log the first couple, this ends up just being noise - d.log.Logf("[%s] error pinging daemon on start: %v", d.id, err) - } - - select { - case <-ctx.Done(): - case <-time.After(500 * time.Millisecond): - } - continue - } - - resp.Body.Close() - if resp.StatusCode != http.StatusOK { - d.log.Logf("[%s] received status != 200 OK: %s\n", d.id, resp.Status) - } - d.log.Logf("[%s] daemon started\n", d.id) - d.Root, err = d.queryRootDir() - if err != nil { - return errors.Wrapf(err, "[%s] error querying daemon for root directory", d.id) - } - return nil - } - } -} - -// StartWithBusybox will first start the daemon with Daemon.Start() -// then save the busybox image from the main daemon and load it into this Daemon instance. -func (d *Daemon) StartWithBusybox(t testing.TB, arg ...string) { - t.Helper() - d.Start(t, arg...) - d.LoadBusybox(t) -} - -// Kill will send a SIGKILL to the daemon -func (d *Daemon) Kill() error { - if d.cmd == nil || d.Wait == nil { - return errDaemonNotStarted - } - - defer func() { - d.logFile.Close() - d.cmd = nil - }() - - if err := d.cmd.Process.Kill(); err != nil { - return err - } - - if d.pidFile != "" { - _ = os.Remove(d.pidFile) - } - return nil -} - -// Pid returns the pid of the daemon -func (d *Daemon) Pid() int { - return d.cmd.Process.Pid -} - -// Interrupt stops the daemon by sending it an Interrupt signal -func (d *Daemon) Interrupt() error { - return d.Signal(os.Interrupt) -} - -// Signal sends the specified signal to the daemon if running -func (d *Daemon) Signal(signal os.Signal) error { - if d.cmd == nil || d.Wait == nil { - return errDaemonNotStarted - } - return d.cmd.Process.Signal(signal) -} - -// DumpStackAndQuit sends SIGQUIT to the daemon, which triggers it to dump its -// stack to its log file and exit -// This is used primarily for gathering debug information on test timeout -func (d *Daemon) DumpStackAndQuit() { - if d.cmd == nil || d.cmd.Process == nil { - return - } - SignalDaemonDump(d.cmd.Process.Pid) -} - -// Stop will send a SIGINT every second and wait for the daemon to stop. -// If it times out, a SIGKILL is sent. -// Stop will not delete the daemon directory. If a purged daemon is needed, -// instantiate a new one with NewDaemon. -// If an error occurs while starting the daemon, the test will fail. -func (d *Daemon) Stop(t testing.TB) { - t.Helper() - err := d.StopWithError() - if err != nil { - if err != errDaemonNotStarted { - t.Fatalf("[%s] error while stopping the daemon: %v", d.id, err) - } else { - t.Logf("[%s] daemon is not started", d.id) - } - } -} - -// StopWithError will send a SIGINT every second and wait for the daemon to stop. -// If it timeouts, a SIGKILL is sent. -// Stop will not delete the daemon directory. If a purged daemon is needed, -// instantiate a new one with NewDaemon. -func (d *Daemon) StopWithError() (err error) { - if d.cmd == nil || d.Wait == nil { - return errDaemonNotStarted - } - defer func() { - if err != nil { - d.log.Logf("[%s] error while stopping daemon: %v", d.id, err) - } else { - d.log.Logf("[%s] daemon stopped", d.id) - if d.pidFile != "" { - _ = os.Remove(d.pidFile) - } - } - if err := d.logFile.Close(); err != nil { - d.log.Logf("[%s] failed to close daemon logfile: %v", d.id, err) - } - d.cmd = nil - }() - - i := 1 - ticker := time.NewTicker(time.Second) - defer ticker.Stop() - tick := ticker.C - - d.log.Logf("[%s] stopping daemon", d.id) - - if err := d.cmd.Process.Signal(os.Interrupt); err != nil { - if strings.Contains(err.Error(), "os: process already finished") { - return errDaemonNotStarted - } - return errors.Wrapf(err, "[%s] could not send signal", d.id) - } - -out1: - for { - select { - case err := <-d.Wait: - return err - case <-time.After(20 * time.Second): - // time for stopping jobs and run onShutdown hooks - d.log.Logf("[%s] daemon stop timed out after 20 seconds", d.id) - break out1 - } - } - -out2: - for { - select { - case err := <-d.Wait: - return err - case <-tick: - i++ - if i > 5 { - d.log.Logf("[%s] tried to interrupt daemon for %d times, now try to kill it", d.id, i) - break out2 - } - d.log.Logf("[%d] attempt #%d/5: daemon is still running with pid %d", i, d.cmd.Process.Pid) - if err := d.cmd.Process.Signal(os.Interrupt); err != nil { - return errors.Wrapf(err, "[%s] attempt #%d/5 could not send signal", d.id, i) - } - } - } - - if err := d.cmd.Process.Kill(); err != nil { - d.log.Logf("[%s] failed to kill daemon: %v", d.id, err) - return err - } - - return nil -} - -// Restart will restart the daemon by first stopping it and the starting it. -// If an error occurs while starting the daemon, the test will fail. -func (d *Daemon) Restart(t testing.TB, args ...string) { - t.Helper() - d.Stop(t) - d.Start(t, args...) -} - -// RestartWithError will restart the daemon by first stopping it and then starting it. -func (d *Daemon) RestartWithError(arg ...string) error { - if err := d.StopWithError(); err != nil { - return err - } - return d.StartWithError(arg...) -} - -func (d *Daemon) handleUserns() { - // in the case of tests running a user namespace-enabled daemon, we have resolved - // d.Root to be the actual final path of the graph dir after the "uid.gid" of - // remapped root is added--we need to subtract it from the path before calling - // start or else we will continue making subdirectories rather than truly restarting - // with the same location/root: - if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" { - d.Root = filepath.Dir(d.Root) - } -} - -// ReloadConfig asks the daemon to reload its configuration -func (d *Daemon) ReloadConfig() error { - if d.cmd == nil || d.cmd.Process == nil { - return errors.New("daemon is not running") - } - - errCh := make(chan error, 1) - started := make(chan struct{}) - go func() { - _, body, err := request.Get("/events", request.Host(d.Sock())) - close(started) - if err != nil { - errCh <- err - return - } - defer body.Close() - dec := json.NewDecoder(body) - for { - var e events.Message - if err := dec.Decode(&e); err != nil { - errCh <- err - return - } - if e.Type != events.DaemonEventType { - continue - } - if e.Action != "reload" { - continue - } - close(errCh) // notify that we are done - return - } - }() - - <-started - if err := signalDaemonReload(d.cmd.Process.Pid); err != nil { - return errors.Wrapf(err, "[%s] error signaling daemon reload", d.id) - } - select { - case err := <-errCh: - if err != nil { - return errors.Wrapf(err, "[%s] error waiting for daemon reload event", d.id) - } - case <-time.After(30 * time.Second): - return errors.Errorf("[%s] daemon reload event timed out after 30 seconds", d.id) - } - return nil -} - -// LoadBusybox image into the daemon -func (d *Daemon) LoadBusybox(t testing.TB) { - t.Helper() - clientHost, err := client.NewClientWithOpts(client.FromEnv) - assert.NilError(t, err, "[%s] failed to create client", d.id) - defer clientHost.Close() - - ctx := context.Background() - reader, err := clientHost.ImageSave(ctx, []string{"busybox:latest"}) - assert.NilError(t, err, "[%s] failed to download busybox", d.id) - defer reader.Close() - - c := d.NewClientT(t) - defer c.Close() - - resp, err := c.ImageLoad(ctx, reader, true) - assert.NilError(t, err, "[%s] failed to load busybox", d.id) - defer resp.Body.Close() -} - -func (d *Daemon) getClientConfig() (*clientConfig, error) { - var ( - transport *http.Transport - scheme string - addr string - proto string - ) - if d.UseDefaultTLSHost { - option := &tlsconfig.Options{ - CAFile: "fixtures/https/ca.pem", - CertFile: "fixtures/https/client-cert.pem", - KeyFile: "fixtures/https/client-key.pem", - } - tlsConfig, err := tlsconfig.Client(*option) - if err != nil { - return nil, err - } - transport = &http.Transport{ - TLSClientConfig: tlsConfig, - } - addr = defaultTLSHost - scheme = "https" - proto = "tcp" - } else if d.UseDefaultHost { - addr = defaultUnixSocket - proto = "unix" - scheme = "http" - transport = &http.Transport{} - } else { - addr = d.sockPath() - proto = "unix" - scheme = "http" - transport = &http.Transport{} - } - - if err := sockets.ConfigureTransport(transport, proto, addr); err != nil { - return nil, err - } - transport.DisableKeepAlives = true - if proto == "unix" { - addr = filepath.Base(addr) - } - return &clientConfig{ - transport: transport, - scheme: scheme, - addr: addr, - }, nil -} - -func (d *Daemon) queryRootDir() (string, error) { - // update daemon root by asking /info endpoint (to support user - // namespaced daemon with root remapped uid.gid directory) - clientConfig, err := d.getClientConfig() - if err != nil { - return "", err - } - - c := &http.Client{ - Transport: clientConfig.transport, - } - - req, err := http.NewRequest(http.MethodGet, "/info", nil) - if err != nil { - return "", err - } - req.Header.Set("Content-Type", "application/json") - req.URL.Host = clientConfig.addr - req.URL.Scheme = clientConfig.scheme - - resp, err := c.Do(req) - if err != nil { - return "", err - } - body := ioutils.NewReadCloserWrapper(resp.Body, func() error { - return resp.Body.Close() - }) - - type Info struct { - DockerRootDir string - } - var b []byte - var i Info - b, err = request.ReadBody(body) - if err == nil && resp.StatusCode == http.StatusOK { - // read the docker root dir - if err = json.Unmarshal(b, &i); err == nil { - return i.DockerRootDir, nil - } - } - return "", err -} - -// Info returns the info struct for this daemon -func (d *Daemon) Info(t testing.TB) types.Info { - t.Helper() - c := d.NewClientT(t) - info, err := c.Info(context.Background()) - assert.NilError(t, err) - assert.NilError(t, c.Close()) - return info -} - -// cleanupRaftDir removes swarmkit wal files if present -func cleanupRaftDir(t testing.TB, d *Daemon) { - t.Helper() - for _, p := range []string{"wal", "wal-v3-encrypted", "snap-v3-encrypted"} { - dir := filepath.Join(d.Root, "swarm/raft", p) - if err := os.RemoveAll(dir); err != nil { - t.Logf("[%s] error removing %v: %v", d.id, dir, err) - } - } -} - -// cleanupDaemonStorage removes the daemon's storage directory. -// -// Note that we don't delete the whole directory, as some files (e.g. daemon -// logs) are collected for inclusion in the "bundles" that are stored as Jenkins -// artifacts. -// -// We currently do not include container logs in the bundles, so this also -// removes the "containers" sub-directory. -func cleanupDaemonStorage(t testing.TB, d *Daemon) { - t.Helper() - dirs := []string{ - "builder", - "buildkit", - "containers", - "image", - "network", - "plugins", - "tmp", - "trust", - "volumes", - // note: this assumes storage-driver name matches the subdirectory, - // which is currently true, but not guaranteed. - d.storageDriver, - } - - for _, p := range dirs { - dir := filepath.Join(d.Root, p) - if err := os.RemoveAll(dir); err != nil { - t.Logf("[%s] error removing %v: %v", d.id, dir, err) - } - } -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/daemon_freebsd.go b/vendor/github.com/docker/docker/testutil/daemon/daemon_freebsd.go deleted file mode 100644 index 0d182d4fb9a7..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/daemon_freebsd.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build freebsd -// +build freebsd - -package daemon // import "github.com/docker/docker/testutil/daemon" - -import ( - "testing" - - "gotest.tools/v3/assert" -) - -func cleanupNetworkNamespace(_ testing.TB, _ *Daemon) {} - -// CgroupNamespace returns the cgroup namespace the daemon is running in -func (d *Daemon) CgroupNamespace(t testing.TB) string { - assert.Assert(t, false, "cgroup namespaces are not supported on FreeBSD") - return "" -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/daemon_linux.go b/vendor/github.com/docker/docker/testutil/daemon/daemon_linux.go deleted file mode 100644 index 720c52a4364e..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/daemon_linux.go +++ /dev/null @@ -1,37 +0,0 @@ -package daemon // import "github.com/docker/docker/testutil/daemon" - -import ( - "fmt" - "os" - "path/filepath" - "strings" - "testing" - - "golang.org/x/sys/unix" - "gotest.tools/v3/assert" -) - -func cleanupNetworkNamespace(t testing.TB, d *Daemon) { - t.Helper() - // Cleanup network namespaces in the exec root of this - // daemon because this exec root is specific to this - // daemon instance and has no chance of getting - // cleaned up when a new daemon is instantiated with a - // new exec root. - netnsPath := filepath.Join(d.execRoot, "netns") - filepath.Walk(netnsPath, func(path string, info os.FileInfo, err error) error { - if err := unix.Unmount(path, unix.MNT_DETACH); err != nil && err != unix.EINVAL && err != unix.ENOENT { - t.Logf("[%s] unmount of %s failed: %v", d.id, path, err) - } - os.Remove(path) - return nil - }) -} - -// CgroupNamespace returns the cgroup namespace the daemon is running in -func (d *Daemon) CgroupNamespace(t testing.TB) string { - link, err := os.Readlink(fmt.Sprintf("/proc/%d/ns/cgroup", d.Pid())) - assert.NilError(t, err) - - return strings.TrimSpace(link) -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/daemon_unix.go b/vendor/github.com/docker/docker/testutil/daemon/daemon_unix.go deleted file mode 100644 index 5ad7812b0440..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/daemon_unix.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build !windows -// +build !windows - -package daemon // import "github.com/docker/docker/testutil/daemon" - -import ( - "os/exec" - "syscall" - "testing" - - "github.com/moby/sys/mount" - "golang.org/x/sys/unix" -) - -// cleanupMount unmounts the daemon root directory, or logs a message if -// unmounting failed. -func cleanupMount(t testing.TB, d *Daemon) { - t.Helper() - if err := mount.Unmount(d.Root); err != nil { - d.log.Logf("[%s] unable to unmount daemon root (%s): %v", d.id, d.Root, err) - } -} - -// SignalDaemonDump sends a signal to the daemon to write a dump file -func SignalDaemonDump(pid int) { - unix.Kill(pid, unix.SIGQUIT) -} - -func signalDaemonReload(pid int) error { - return unix.Kill(pid, unix.SIGHUP) -} - -func setsid(cmd *exec.Cmd) { - if cmd.SysProcAttr == nil { - cmd.SysProcAttr = &syscall.SysProcAttr{} - } - cmd.SysProcAttr.Setsid = true -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/daemon_windows.go b/vendor/github.com/docker/docker/testutil/daemon/daemon_windows.go deleted file mode 100644 index be94b5283839..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/daemon_windows.go +++ /dev/null @@ -1,38 +0,0 @@ -package daemon - -import ( - "fmt" - "os/exec" - "strconv" - "testing" - - "golang.org/x/sys/windows" - "gotest.tools/v3/assert" -) - -// SignalDaemonDump sends a signal to the daemon to write a dump file -func SignalDaemonDump(pid int) { - ev, _ := windows.UTF16PtrFromString("Global\\docker-daemon-" + strconv.Itoa(pid)) - h2, err := windows.OpenEvent(0x0002, false, ev) - if h2 == 0 || err != nil { - return - } - windows.PulseEvent(h2) -} - -func signalDaemonReload(pid int) error { - return fmt.Errorf("daemon reload not supported") -} - -func cleanupMount(_ testing.TB, _ *Daemon) {} - -func cleanupNetworkNamespace(_ testing.TB, _ *Daemon) {} - -// CgroupNamespace returns the cgroup namespace the daemon is running in -func (d *Daemon) CgroupNamespace(t testing.TB) string { - assert.Assert(t, false) - return "cgroup namespaces are not supported on Windows" -} - -func setsid(cmd *exec.Cmd) { -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/doc.go b/vendor/github.com/docker/docker/testutil/daemon/doc.go deleted file mode 100644 index add30e3cfb4a..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package daemon launches dockerd for testing purposes. -package daemon // import "github.com/docker/docker/testutil/daemon" diff --git a/vendor/github.com/docker/docker/testutil/daemon/node.go b/vendor/github.com/docker/docker/testutil/daemon/node.go deleted file mode 100644 index 89d0817b0030..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/node.go +++ /dev/null @@ -1,81 +0,0 @@ -package daemon - -import ( - "context" - "strings" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "gotest.tools/v3/assert" -) - -// NodeConstructor defines a swarm node constructor -type NodeConstructor func(*swarm.Node) - -// GetNode returns a swarm node identified by the specified id -func (d *Daemon) GetNode(t testing.TB, id string, errCheck ...func(error) bool) *swarm.Node { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - node, _, err := cli.NodeInspectWithRaw(context.Background(), id) - if err != nil { - for _, f := range errCheck { - if f(err) { - return nil - } - } - } - assert.NilError(t, err, "[%s] (*Daemon).GetNode: NodeInspectWithRaw(%q) failed", d.id, id) - assert.Check(t, node.ID == id) - return &node -} - -// RemoveNode removes the specified node -func (d *Daemon) RemoveNode(t testing.TB, id string, force bool) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - options := types.NodeRemoveOptions{ - Force: force, - } - err := cli.NodeRemove(context.Background(), id, options) - assert.NilError(t, err) -} - -// UpdateNode updates a swarm node with the specified node constructor -func (d *Daemon) UpdateNode(t testing.TB, id string, f ...NodeConstructor) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - for i := 0; ; i++ { - node := d.GetNode(t, id) - for _, fn := range f { - fn(node) - } - - err := cli.NodeUpdate(context.Background(), node.ID, node.Version, node.Spec) - if i < 10 && err != nil && strings.Contains(err.Error(), "update out of sequence") { - time.Sleep(100 * time.Millisecond) - continue - } - assert.NilError(t, err) - return - } -} - -// ListNodes returns the list of the current swarm nodes -func (d *Daemon) ListNodes(t testing.TB) []swarm.Node { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - nodes, err := cli.NodeList(context.Background(), types.NodeListOptions{}) - assert.NilError(t, err) - - return nodes -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/ops.go b/vendor/github.com/docker/docker/testutil/daemon/ops.go deleted file mode 100644 index c977dcef44f7..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/ops.go +++ /dev/null @@ -1,124 +0,0 @@ -package daemon - -import ( - "os/user" - - "github.com/docker/docker/testutil/environment" -) - -// Option is used to configure a daemon. -type Option func(*Daemon) - -// WithContainerdSocket sets the --containerd option on the daemon. -// Use an empty string to remove the option. -// -// If unset the --containerd option will be used with a default value. -func WithContainerdSocket(socket string) Option { - return func(d *Daemon) { - d.containerdSocket = socket - } -} - -// WithDefaultCgroupNamespaceMode sets the default cgroup namespace mode for the daemon -func WithDefaultCgroupNamespaceMode(mode string) Option { - return func(d *Daemon) { - d.defaultCgroupNamespaceMode = mode - } -} - -// WithTestLogger causes the daemon to log certain actions to the provided test. -func WithTestLogger(t LogT) Option { - return func(d *Daemon) { - d.log = t - } -} - -// WithExperimental sets the daemon in experimental mode -func WithExperimental() Option { - return func(d *Daemon) { - d.experimental = true - } -} - -// WithInit sets the daemon init -func WithInit() Option { - return func(d *Daemon) { - d.init = true - } -} - -// WithDockerdBinary sets the dockerd binary to the specified one -func WithDockerdBinary(dockerdBinary string) Option { - return func(d *Daemon) { - d.dockerdBinary = dockerdBinary - } -} - -// WithSwarmPort sets the swarm port to use for swarm mode -func WithSwarmPort(port int) Option { - return func(d *Daemon) { - d.SwarmPort = port - } -} - -// WithSwarmListenAddr sets the swarm listen addr to use for swarm mode -func WithSwarmListenAddr(listenAddr string) Option { - return func(d *Daemon) { - d.swarmListenAddr = listenAddr - } -} - -// WithSwarmDefaultAddrPool sets the swarm default address pool to use for swarm mode -func WithSwarmDefaultAddrPool(defaultAddrPool []string) Option { - return func(d *Daemon) { - d.DefaultAddrPool = defaultAddrPool - } -} - -// WithSwarmDefaultAddrPoolSubnetSize sets the subnet length mask of swarm default address pool to use for swarm mode -func WithSwarmDefaultAddrPoolSubnetSize(subnetSize uint32) Option { - return func(d *Daemon) { - d.SubnetSize = subnetSize - } -} - -// WithSwarmDataPathPort sets the swarm datapath port to use for swarm mode -func WithSwarmDataPathPort(datapathPort uint32) Option { - return func(d *Daemon) { - d.DataPathPort = datapathPort - } -} - -// WithEnvironment sets options from testutil/environment.Execution struct -func WithEnvironment(e environment.Execution) Option { - return func(d *Daemon) { - if e.DaemonInfo.ExperimentalBuild { - d.experimental = true - } - } -} - -// WithStorageDriver sets store driver option -func WithStorageDriver(driver string) Option { - return func(d *Daemon) { - d.storageDriver = driver - } -} - -// WithRootlessUser sets the daemon to be rootless -func WithRootlessUser(username string) Option { - return func(d *Daemon) { - u, err := user.Lookup(username) - if err != nil { - panic(err) - } - d.rootlessUser = u - } -} - -// WithOOMScoreAdjust sets OOM score for the daemon -func WithOOMScoreAdjust(score int) Option { - return func(d *Daemon) { - d.OOMScoreAdjust = score - } -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/plugin.go b/vendor/github.com/docker/docker/testutil/daemon/plugin.go deleted file mode 100644 index 98aa6063a902..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/plugin.go +++ /dev/null @@ -1,75 +0,0 @@ -package daemon - -import ( - "context" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "gotest.tools/v3/poll" -) - -// PluginIsRunning provides a poller to check if the specified plugin is running -func (d *Daemon) PluginIsRunning(t testing.TB, name string) func(poll.LogT) poll.Result { - return withClient(t, d, withPluginInspect(name, func(plugin *types.Plugin, t poll.LogT) poll.Result { - if plugin.Enabled { - return poll.Success() - } - return poll.Continue("plugin %q is not enabled", name) - })) -} - -// PluginIsNotRunning provides a poller to check if the specified plugin is not running -func (d *Daemon) PluginIsNotRunning(t testing.TB, name string) func(poll.LogT) poll.Result { - return withClient(t, d, withPluginInspect(name, func(plugin *types.Plugin, t poll.LogT) poll.Result { - if !plugin.Enabled { - return poll.Success() - } - return poll.Continue("plugin %q is enabled", name) - })) -} - -// PluginIsNotPresent provides a poller to check if the specified plugin is not present -func (d *Daemon) PluginIsNotPresent(t testing.TB, name string) func(poll.LogT) poll.Result { - return withClient(t, d, func(c client.APIClient, t poll.LogT) poll.Result { - _, _, err := c.PluginInspectWithRaw(context.Background(), name) - if client.IsErrNotFound(err) { - return poll.Success() - } - if err != nil { - return poll.Error(err) - } - return poll.Continue("plugin %q exists", name) - }) -} - -// PluginReferenceIs provides a poller to check if the specified plugin has the specified reference -func (d *Daemon) PluginReferenceIs(t testing.TB, name, expectedRef string) func(poll.LogT) poll.Result { - return withClient(t, d, withPluginInspect(name, func(plugin *types.Plugin, t poll.LogT) poll.Result { - if plugin.PluginReference == expectedRef { - return poll.Success() - } - return poll.Continue("plugin %q reference is not %q", name, expectedRef) - })) -} - -func withPluginInspect(name string, f func(*types.Plugin, poll.LogT) poll.Result) func(client.APIClient, poll.LogT) poll.Result { - return func(c client.APIClient, t poll.LogT) poll.Result { - plugin, _, err := c.PluginInspectWithRaw(context.Background(), name) - if client.IsErrNotFound(err) { - return poll.Continue("plugin %q not found", name) - } - if err != nil { - return poll.Error(err) - } - return f(plugin, t) - } - -} - -func withClient(t testing.TB, d *Daemon, f func(client.APIClient, poll.LogT) poll.Result) func(poll.LogT) poll.Result { - return func(pt poll.LogT) poll.Result { - c := d.NewClientT(t) - return f(c, pt) - } -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/secret.go b/vendor/github.com/docker/docker/testutil/daemon/secret.go deleted file mode 100644 index 099fdf33f118..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/secret.go +++ /dev/null @@ -1,74 +0,0 @@ -package daemon - -import ( - "context" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "gotest.tools/v3/assert" -) - -// SecretConstructor defines a swarm secret constructor -type SecretConstructor func(*swarm.Secret) - -// CreateSecret creates a secret given the specified spec -func (d *Daemon) CreateSecret(t testing.TB, secretSpec swarm.SecretSpec) string { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - scr, err := cli.SecretCreate(context.Background(), secretSpec) - assert.NilError(t, err) - - return scr.ID -} - -// ListSecrets returns the list of the current swarm secrets -func (d *Daemon) ListSecrets(t testing.TB) []swarm.Secret { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - secrets, err := cli.SecretList(context.Background(), types.SecretListOptions{}) - assert.NilError(t, err) - return secrets -} - -// GetSecret returns a swarm secret identified by the specified id -func (d *Daemon) GetSecret(t testing.TB, id string) *swarm.Secret { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - secret, _, err := cli.SecretInspectWithRaw(context.Background(), id) - assert.NilError(t, err) - return &secret -} - -// DeleteSecret removes the swarm secret identified by the specified id -func (d *Daemon) DeleteSecret(t testing.TB, id string) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - err := cli.SecretRemove(context.Background(), id) - assert.NilError(t, err) -} - -// UpdateSecret updates the swarm secret identified by the specified id -// Currently, only label update is supported. -func (d *Daemon) UpdateSecret(t testing.TB, id string, f ...SecretConstructor) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - secret := d.GetSecret(t, id) - for _, fn := range f { - fn(secret) - } - - err := cli.SecretUpdate(context.Background(), secret.ID, secret.Version, secret.Spec) - - assert.NilError(t, err) -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/service.go b/vendor/github.com/docker/docker/testutil/daemon/service.go deleted file mode 100644 index 0fb49b5f5b39..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/service.go +++ /dev/null @@ -1,118 +0,0 @@ -package daemon - -import ( - "context" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "gotest.tools/v3/assert" -) - -// ServiceConstructor defines a swarm service constructor function -type ServiceConstructor func(*swarm.Service) - -func (d *Daemon) createServiceWithOptions(t testing.TB, opts types.ServiceCreateOptions, f ...ServiceConstructor) string { - t.Helper() - var service swarm.Service - for _, fn := range f { - fn(&service) - } - - cli := d.NewClientT(t) - defer cli.Close() - - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - res, err := cli.ServiceCreate(ctx, service.Spec, opts) - assert.NilError(t, err) - return res.ID -} - -// CreateService creates a swarm service given the specified service constructor -func (d *Daemon) CreateService(t testing.TB, f ...ServiceConstructor) string { - t.Helper() - return d.createServiceWithOptions(t, types.ServiceCreateOptions{}, f...) -} - -// GetService returns the swarm service corresponding to the specified id -func (d *Daemon) GetService(t testing.TB, id string) *swarm.Service { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - service, _, err := cli.ServiceInspectWithRaw(context.Background(), id, types.ServiceInspectOptions{}) - assert.NilError(t, err) - return &service -} - -// GetServiceTasks returns the swarm tasks for the specified service -func (d *Daemon) GetServiceTasks(t testing.TB, service string, additionalFilters ...filters.KeyValuePair) []swarm.Task { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - filterArgs := filters.NewArgs() - filterArgs.Add("desired-state", "running") - filterArgs.Add("service", service) - for _, filter := range additionalFilters { - filterArgs.Add(filter.Key, filter.Value) - } - - options := types.TaskListOptions{ - Filters: filterArgs, - } - - tasks, err := cli.TaskList(context.Background(), options) - assert.NilError(t, err) - return tasks -} - -// UpdateService updates a swarm service with the specified service constructor -func (d *Daemon) UpdateService(t testing.TB, service *swarm.Service, f ...ServiceConstructor) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - for _, fn := range f { - fn(service) - } - - _, err := cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) - assert.NilError(t, err) -} - -// RemoveService removes the specified service -func (d *Daemon) RemoveService(t testing.TB, id string) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - err := cli.ServiceRemove(context.Background(), id) - assert.NilError(t, err) -} - -// ListServices returns the list of the current swarm services -func (d *Daemon) ListServices(t testing.TB) []swarm.Service { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - services, err := cli.ServiceList(context.Background(), types.ServiceListOptions{}) - assert.NilError(t, err) - return services -} - -// GetTask returns the swarm task identified by the specified id -func (d *Daemon) GetTask(t testing.TB, id string) swarm.Task { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - task, _, err := cli.TaskInspectWithRaw(context.Background(), id) - assert.NilError(t, err) - return task -} diff --git a/vendor/github.com/docker/docker/testutil/daemon/swarm.go b/vendor/github.com/docker/docker/testutil/daemon/swarm.go deleted file mode 100644 index 8746a0e8a6fc..000000000000 --- a/vendor/github.com/docker/docker/testutil/daemon/swarm.go +++ /dev/null @@ -1,201 +0,0 @@ -package daemon - -import ( - "context" - "fmt" - "testing" - - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "gotest.tools/v3/assert" -) - -const ( - // DefaultSwarmPort is the default port use for swarm in the tests - DefaultSwarmPort = 2477 - defaultSwarmListenAddr = "0.0.0.0" -) - -var ( - startArgs = []string{"--iptables=false", "--swarm-default-advertise-addr=lo"} -) - -// StartNode (re)starts the daemon -func (d *Daemon) StartNode(t testing.TB) { - t.Helper() - d.Start(t, startArgs...) -} - -// StartNodeWithBusybox starts daemon to be used as a swarm node, and loads the busybox image -func (d *Daemon) StartNodeWithBusybox(t testing.TB) { - t.Helper() - d.StartWithBusybox(t, startArgs...) -} - -// RestartNode restarts a daemon to be used as a swarm node -func (d *Daemon) RestartNode(t testing.TB) { - t.Helper() - // avoid networking conflicts - d.Stop(t) - d.Start(t, startArgs...) -} - -// StartAndSwarmInit starts the daemon (with busybox) and init the swarm -func (d *Daemon) StartAndSwarmInit(t testing.TB) { - d.StartNodeWithBusybox(t) - d.SwarmInit(t, swarm.InitRequest{}) -} - -// StartAndSwarmJoin starts the daemon (with busybox) and join the specified swarm as worker or manager -func (d *Daemon) StartAndSwarmJoin(t testing.TB, leader *Daemon, manager bool) { - t.Helper() - d.StartNodeWithBusybox(t) - - tokens := leader.JoinTokens(t) - token := tokens.Worker - if manager { - token = tokens.Manager - } - t.Logf("[%s] joining swarm manager [%s]@%s, swarm listen addr %s", d.id, leader.id, leader.SwarmListenAddr(), d.SwarmListenAddr()) - d.SwarmJoin(t, swarm.JoinRequest{ - RemoteAddrs: []string{leader.SwarmListenAddr()}, - JoinToken: token, - }) -} - -// SpecConstructor defines a swarm spec constructor -type SpecConstructor func(*swarm.Spec) - -// SwarmListenAddr returns the listen-addr used for the daemon -func (d *Daemon) SwarmListenAddr() string { - return fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort) -} - -// NodeID returns the swarm mode node ID -func (d *Daemon) NodeID() string { - return d.CachedInfo.Swarm.NodeID -} - -// SwarmInit initializes a new swarm cluster. -func (d *Daemon) SwarmInit(t testing.TB, req swarm.InitRequest) { - t.Helper() - if req.ListenAddr == "" { - req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort) - } - if req.DefaultAddrPool == nil { - req.DefaultAddrPool = d.DefaultAddrPool - req.SubnetSize = d.SubnetSize - } - if d.DataPathPort > 0 { - req.DataPathPort = d.DataPathPort - } - cli := d.NewClientT(t) - defer cli.Close() - _, err := cli.SwarmInit(context.Background(), req) - assert.NilError(t, err, "initializing swarm") - d.CachedInfo = d.Info(t) -} - -// SwarmJoin joins a daemon to an existing cluster. -func (d *Daemon) SwarmJoin(t testing.TB, req swarm.JoinRequest) { - t.Helper() - if req.ListenAddr == "" { - req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort) - } - cli := d.NewClientT(t) - defer cli.Close() - err := cli.SwarmJoin(context.Background(), req) - assert.NilError(t, err, "[%s] joining swarm", d.id) - d.CachedInfo = d.Info(t) -} - -// SwarmLeave forces daemon to leave current cluster. -// -// The passed in testing.TB is only used to validate that the client was successfully created -// Some tests rely on error checking the result of the actual unlock, so allow -// the error to be returned. -func (d *Daemon) SwarmLeave(t testing.TB, force bool) error { - cli := d.NewClientT(t) - defer cli.Close() - return cli.SwarmLeave(context.Background(), force) -} - -// SwarmInfo returns the swarm information of the daemon -func (d *Daemon) SwarmInfo(t testing.TB) swarm.Info { - t.Helper() - cli := d.NewClientT(t) - info, err := cli.Info(context.Background()) - assert.NilError(t, err, "get swarm info") - return info.Swarm -} - -// SwarmUnlock tries to unlock a locked swarm -// -// The passed in testing.TB is only used to validate that the client was successfully created -// Some tests rely on error checking the result of the actual unlock, so allow -// the error to be returned. -func (d *Daemon) SwarmUnlock(t testing.TB, req swarm.UnlockRequest) error { - cli := d.NewClientT(t) - defer cli.Close() - - err := cli.SwarmUnlock(context.Background(), req) - if err != nil { - err = errors.Wrap(err, "unlocking swarm") - } - return err -} - -// GetSwarm returns the current swarm object -func (d *Daemon) GetSwarm(t testing.TB) swarm.Swarm { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - sw, err := cli.SwarmInspect(context.Background()) - assert.NilError(t, err) - return sw -} - -// UpdateSwarm updates the current swarm object with the specified spec constructors -func (d *Daemon) UpdateSwarm(t testing.TB, f ...SpecConstructor) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - sw := d.GetSwarm(t) - for _, fn := range f { - fn(&sw.Spec) - } - - err := cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{}) - assert.NilError(t, err) -} - -// RotateTokens update the swarm to rotate tokens -func (d *Daemon) RotateTokens(t testing.TB) { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - sw, err := cli.SwarmInspect(context.Background()) - assert.NilError(t, err) - - flags := swarm.UpdateFlags{ - RotateManagerToken: true, - RotateWorkerToken: true, - } - - err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags) - assert.NilError(t, err) -} - -// JoinTokens returns the current swarm join tokens -func (d *Daemon) JoinTokens(t testing.TB) swarm.JoinTokens { - t.Helper() - cli := d.NewClientT(t) - defer cli.Close() - - sw, err := cli.SwarmInspect(context.Background()) - assert.NilError(t, err) - return sw.JoinTokens -} diff --git a/vendor/github.com/docker/docker/testutil/environment/clean.go b/vendor/github.com/docker/docker/testutil/environment/clean.go deleted file mode 100644 index 415615e8774e..000000000000 --- a/vendor/github.com/docker/docker/testutil/environment/clean.go +++ /dev/null @@ -1,185 +0,0 @@ -package environment // import "github.com/docker/docker/testutil/environment" - -import ( - "context" - "regexp" - "strings" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" - "gotest.tools/v3/assert" -) - -// Clean the environment, preserving protected objects (images, containers, ...) -// and removing everything else. It's meant to run after any tests so that they don't -// depend on each others. -func (e *Execution) Clean(t testing.TB) { - t.Helper() - client := e.APIClient() - - platform := e.OSType - if (platform != "windows") || (platform == "windows" && e.DaemonInfo.Isolation == "hyperv") { - unpauseAllContainers(t, client) - } - deleteAllContainers(t, client, e.protectedElements.containers) - deleteAllImages(t, client, e.protectedElements.images) - deleteAllVolumes(t, client, e.protectedElements.volumes) - deleteAllNetworks(t, client, platform, e.protectedElements.networks) - if platform == "linux" { - deleteAllPlugins(t, client, e.protectedElements.plugins) - } -} - -func unpauseAllContainers(t testing.TB, client client.ContainerAPIClient) { - t.Helper() - ctx := context.Background() - containers := getPausedContainers(ctx, t, client) - if len(containers) > 0 { - for _, container := range containers { - err := client.ContainerUnpause(ctx, container.ID) - assert.Check(t, err, "failed to unpause container %s", container.ID) - } - } -} - -func getPausedContainers(ctx context.Context, t testing.TB, client client.ContainerAPIClient) []types.Container { - t.Helper() - filter := filters.NewArgs() - filter.Add("status", "paused") - containers, err := client.ContainerList(ctx, types.ContainerListOptions{ - Filters: filter, - All: true, - }) - assert.Check(t, err, "failed to list containers") - return containers -} - -var alreadyExists = regexp.MustCompile(`Error response from daemon: removal of container (\w+) is already in progress`) - -func deleteAllContainers(t testing.TB, apiclient client.ContainerAPIClient, protectedContainers map[string]struct{}) { - t.Helper() - ctx := context.Background() - containers := getAllContainers(ctx, t, apiclient) - if len(containers) == 0 { - return - } - - for _, container := range containers { - if _, ok := protectedContainers[container.ID]; ok { - continue - } - err := apiclient.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{ - Force: true, - RemoveVolumes: true, - }) - if err == nil || client.IsErrNotFound(err) || alreadyExists.MatchString(err.Error()) || isErrNotFoundSwarmClassic(err) { - continue - } - assert.Check(t, err, "failed to remove %s", container.ID) - } -} - -func getAllContainers(ctx context.Context, t testing.TB, client client.ContainerAPIClient) []types.Container { - t.Helper() - containers, err := client.ContainerList(ctx, types.ContainerListOptions{ - All: true, - }) - assert.Check(t, err, "failed to list containers") - return containers -} - -func deleteAllImages(t testing.TB, apiclient client.ImageAPIClient, protectedImages map[string]struct{}) { - t.Helper() - images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{}) - assert.Check(t, err, "failed to list images") - - ctx := context.Background() - for _, image := range images { - tags := tagsFromImageSummary(image) - if len(tags) == 0 { - removeImage(ctx, t, apiclient, image.ID) - continue - } - for _, tag := range tags { - if _, ok := protectedImages[tag]; !ok { - removeImage(ctx, t, apiclient, tag) - } - } - } -} - -func removeImage(ctx context.Context, t testing.TB, apiclient client.ImageAPIClient, ref string) { - t.Helper() - _, err := apiclient.ImageRemove(ctx, ref, types.ImageRemoveOptions{ - Force: true, - }) - if client.IsErrNotFound(err) { - return - } - assert.Check(t, err, "failed to remove image %s", ref) -} - -func deleteAllVolumes(t testing.TB, c client.VolumeAPIClient, protectedVolumes map[string]struct{}) { - t.Helper() - volumes, err := c.VolumeList(context.Background(), filters.Args{}) - assert.Check(t, err, "failed to list volumes") - - for _, v := range volumes.Volumes { - if _, ok := protectedVolumes[v.Name]; ok { - continue - } - err := c.VolumeRemove(context.Background(), v.Name, true) - // Docker EE may list volumes that no longer exist. - if isErrNotFoundSwarmClassic(err) { - continue - } - assert.Check(t, err, "failed to remove volume %s", v.Name) - } -} - -func deleteAllNetworks(t testing.TB, c client.NetworkAPIClient, daemonPlatform string, protectedNetworks map[string]struct{}) { - t.Helper() - networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{}) - assert.Check(t, err, "failed to list networks") - - for _, n := range networks { - if n.Name == "bridge" || n.Name == "none" || n.Name == "host" { - continue - } - if _, ok := protectedNetworks[n.ID]; ok { - continue - } - if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" { - // nat is a pre-defined network on Windows and cannot be removed - continue - } - err := c.NetworkRemove(context.Background(), n.ID) - assert.Check(t, err, "failed to remove network %s", n.ID) - } -} - -func deleteAllPlugins(t testing.TB, c client.PluginAPIClient, protectedPlugins map[string]struct{}) { - t.Helper() - plugins, err := c.PluginList(context.Background(), filters.Args{}) - // Docker EE does not allow cluster-wide plugin management. - if client.IsErrNotImplemented(err) { - return - } - assert.Check(t, err, "failed to list plugins") - - for _, p := range plugins { - if _, ok := protectedPlugins[p.Name]; ok { - continue - } - err := c.PluginRemove(context.Background(), p.Name, types.PluginRemoveOptions{Force: true}) - assert.Check(t, err, "failed to remove plugin %s", p.ID) - } -} - -// Swarm classic aggregates node errors and returns a 500 so we need to check -// the error string instead of just IsErrNotFound(). -func isErrNotFoundSwarmClassic(err error) bool { - return err != nil && strings.Contains(strings.ToLower(err.Error()), "no such") -} diff --git a/vendor/github.com/docker/docker/testutil/environment/environment.go b/vendor/github.com/docker/docker/testutil/environment/environment.go deleted file mode 100644 index 8af8ca8d6f1a..000000000000 --- a/vendor/github.com/docker/docker/testutil/environment/environment.go +++ /dev/null @@ -1,223 +0,0 @@ -package environment // import "github.com/docker/docker/testutil/environment" - -import ( - "context" - "fmt" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" - "github.com/docker/docker/testutil/fixtures/load" - "github.com/pkg/errors" - "gotest.tools/v3/assert" -) - -// Execution contains information about the current test execution and daemon -// under test -type Execution struct { - client client.APIClient - DaemonInfo types.Info - OSType string - PlatformDefaults PlatformDefaults - protectedElements protectedElements -} - -// PlatformDefaults are defaults values for the platform of the daemon under test -type PlatformDefaults struct { - BaseImage string - VolumesConfigPath string - ContainerStoragePath string -} - -// New creates a new Execution struct -// This is configured using the env client (see client.FromEnv) -func New() (*Execution, error) { - c, err := client.NewClientWithOpts(client.FromEnv) - if err != nil { - return nil, errors.Wrapf(err, "failed to create client") - } - return FromClient(c) -} - -// FromClient creates a new Execution environment from the passed in client -func FromClient(c *client.Client) (*Execution, error) { - info, err := c.Info(context.Background()) - if err != nil { - return nil, errors.Wrapf(err, "failed to get info from daemon") - } - - osType := getOSType(info) - - return &Execution{ - client: c, - DaemonInfo: info, - OSType: osType, - PlatformDefaults: getPlatformDefaults(info, osType), - protectedElements: newProtectedElements(), - }, nil -} - -func getOSType(info types.Info) string { - // Docker EE does not set the OSType so allow the user to override this value. - userOsType := os.Getenv("TEST_OSTYPE") - if userOsType != "" { - return userOsType - } - return info.OSType -} - -func getPlatformDefaults(info types.Info, osType string) PlatformDefaults { - volumesPath := filepath.Join(info.DockerRootDir, "volumes") - containersPath := filepath.Join(info.DockerRootDir, "containers") - - switch osType { - case "linux": - return PlatformDefaults{ - BaseImage: "scratch", - VolumesConfigPath: toSlash(volumesPath), - ContainerStoragePath: toSlash(containersPath), - } - case "windows": - baseImage := "microsoft/windowsservercore" - if overrideBaseImage := os.Getenv("WINDOWS_BASE_IMAGE"); overrideBaseImage != "" { - baseImage = overrideBaseImage - if overrideBaseImageTag := os.Getenv("WINDOWS_BASE_IMAGE_TAG"); overrideBaseImageTag != "" { - baseImage = baseImage + ":" + overrideBaseImageTag - } - } - fmt.Println("INFO: Windows Base image is ", baseImage) - return PlatformDefaults{ - BaseImage: baseImage, - VolumesConfigPath: filepath.FromSlash(volumesPath), - ContainerStoragePath: filepath.FromSlash(containersPath), - } - default: - panic(fmt.Sprintf("unknown OSType for daemon: %s", osType)) - } -} - -// Make sure in context of daemon, not the local platform. Note we can't -// use filepath.FromSlash or ToSlash here as they are a no-op on Unix. -func toSlash(path string) string { - return strings.Replace(path, `\`, `/`, -1) -} - -// IsLocalDaemon is true if the daemon under test is on the same -// host as the test process. -// -// Deterministically working out the environment in which CI is running -// to evaluate whether the daemon is local or remote is not possible through -// a build tag. -// -// For example Windows to Linux CI under Jenkins tests the 64-bit -// Windows binary build with the daemon build tag, but calls a remote -// Linux daemon. -// -// We can't just say if Windows then assume the daemon is local as at -// some point, we will be testing the Windows CLI against a Windows daemon. -// -// Similarly, it will be perfectly valid to also run CLI tests from -// a Linux CLI (built with the daemon tag) against a Windows daemon. -func (e *Execution) IsLocalDaemon() bool { - return os.Getenv("DOCKER_REMOTE_DAEMON") == "" -} - -// IsRemoteDaemon is true if the daemon under test is on different host -// as the test process. -func (e *Execution) IsRemoteDaemon() bool { - return !e.IsLocalDaemon() -} - -// DaemonAPIVersion returns the negotiated daemon api version -func (e *Execution) DaemonAPIVersion() string { - version, err := e.APIClient().ServerVersion(context.TODO()) - if err != nil { - return "" - } - return version.APIVersion -} - -// Print the execution details to stdout -// TODO: print everything -func (e *Execution) Print() { - if e.IsLocalDaemon() { - fmt.Println("INFO: Testing against a local daemon") - } else { - fmt.Println("INFO: Testing against a remote daemon") - } -} - -// APIClient returns an APIClient connected to the daemon under test -func (e *Execution) APIClient() client.APIClient { - return e.client -} - -// IsUserNamespace returns whether the user namespace remapping is enabled -func (e *Execution) IsUserNamespace() bool { - root := os.Getenv("DOCKER_REMAP_ROOT") - return root != "" -} - -// RuntimeIsWindowsContainerd returns whether containerd runtime is used on Windows -func (e *Execution) RuntimeIsWindowsContainerd() bool { - return os.Getenv("DOCKER_WINDOWS_CONTAINERD_RUNTIME") == "1" -} - -// IsRootless returns whether the rootless mode is enabled -func (e *Execution) IsRootless() bool { - return os.Getenv("DOCKER_ROOTLESS") != "" -} - -// IsUserNamespaceInKernel returns whether the kernel supports user namespaces -func (e *Execution) IsUserNamespaceInKernel() bool { - if _, err := os.Stat("/proc/self/uid_map"); os.IsNotExist(err) { - /* - * This kernel-provided file only exists if user namespaces are - * supported - */ - return false - } - - // We need extra check on redhat based distributions - if f, err := os.Open("/sys/module/user_namespace/parameters/enable"); err == nil { - defer f.Close() - b := make([]byte, 1) - _, _ = f.Read(b) - return string(b) != "N" - } - - return true -} - -// HasExistingImage checks whether there is an image with the given reference. -// Note that this is done by filtering and then checking whether there were any -// results -- so ambiguous references might result in false-positives. -func (e *Execution) HasExistingImage(t testing.TB, reference string) bool { - client := e.APIClient() - filter := filters.NewArgs() - filter.Add("dangling", "false") - filter.Add("reference", reference) - imageList, err := client.ImageList(context.Background(), types.ImageListOptions{ - All: true, - Filters: filter, - }) - assert.NilError(t, err, "failed to list images") - - return len(imageList) > 0 -} - -// EnsureFrozenImagesLinux loads frozen test images into the daemon -// if they aren't already loaded -func EnsureFrozenImagesLinux(testEnv *Execution) error { - if testEnv.OSType == "linux" { - err := load.FrozenImagesLinux(testEnv.APIClient(), frozenImages...) - if err != nil { - return errors.Wrap(err, "error loading frozen images") - } - } - return nil -} diff --git a/vendor/github.com/docker/docker/testutil/environment/protect.go b/vendor/github.com/docker/docker/testutil/environment/protect.go deleted file mode 100644 index d790106128fb..000000000000 --- a/vendor/github.com/docker/docker/testutil/environment/protect.go +++ /dev/null @@ -1,222 +0,0 @@ -package environment - -import ( - "context" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - dclient "github.com/docker/docker/client" - "gotest.tools/v3/assert" -) - -var frozenImages = []string{"busybox:latest", "busybox:glibc", "hello-world:frozen", "debian:bullseye-slim"} - -type protectedElements struct { - containers map[string]struct{} - images map[string]struct{} - networks map[string]struct{} - plugins map[string]struct{} - volumes map[string]struct{} -} - -func newProtectedElements() protectedElements { - return protectedElements{ - containers: map[string]struct{}{}, - images: map[string]struct{}{}, - networks: map[string]struct{}{}, - plugins: map[string]struct{}{}, - volumes: map[string]struct{}{}, - } -} - -// ProtectAll protects the existing environment (containers, images, networks, -// volumes, and, on Linux, plugins) from being cleaned up at the end of test -// runs -func ProtectAll(t testing.TB, testEnv *Execution) { - t.Helper() - ProtectContainers(t, testEnv) - ProtectImages(t, testEnv) - ProtectNetworks(t, testEnv) - ProtectVolumes(t, testEnv) - if testEnv.OSType == "linux" { - ProtectPlugins(t, testEnv) - } -} - -// ProtectContainer adds the specified container(s) to be protected in case of -// clean -func (e *Execution) ProtectContainer(t testing.TB, containers ...string) { - t.Helper() - for _, container := range containers { - e.protectedElements.containers[container] = struct{}{} - } -} - -// ProtectContainers protects existing containers from being cleaned up at the -// end of test runs -func ProtectContainers(t testing.TB, testEnv *Execution) { - t.Helper() - containers := getExistingContainers(t, testEnv) - testEnv.ProtectContainer(t, containers...) -} - -func getExistingContainers(t testing.TB, testEnv *Execution) []string { - t.Helper() - client := testEnv.APIClient() - containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{ - All: true, - }) - assert.NilError(t, err, "failed to list containers") - - var containers []string - for _, container := range containerList { - containers = append(containers, container.ID) - } - return containers -} - -// ProtectImage adds the specified image(s) to be protected in case of clean -func (e *Execution) ProtectImage(t testing.TB, images ...string) { - t.Helper() - for _, image := range images { - e.protectedElements.images[image] = struct{}{} - } -} - -// ProtectImages protects existing images and on linux frozen images from being -// cleaned up at the end of test runs -func ProtectImages(t testing.TB, testEnv *Execution) { - t.Helper() - images := getExistingImages(t, testEnv) - - if testEnv.OSType == "linux" { - images = append(images, frozenImages...) - } - testEnv.ProtectImage(t, images...) -} - -func getExistingImages(t testing.TB, testEnv *Execution) []string { - t.Helper() - client := testEnv.APIClient() - filter := filters.NewArgs() - filter.Add("dangling", "false") - imageList, err := client.ImageList(context.Background(), types.ImageListOptions{ - All: true, - Filters: filter, - }) - assert.NilError(t, err, "failed to list images") - - var images []string - for _, image := range imageList { - images = append(images, tagsFromImageSummary(image)...) - } - return images -} - -func tagsFromImageSummary(image types.ImageSummary) []string { - var result []string - for _, tag := range image.RepoTags { - if tag != ":" { - result = append(result, tag) - } - } - for _, digest := range image.RepoDigests { - if digest != "@" { - result = append(result, digest) - } - } - return result -} - -// ProtectNetwork adds the specified network(s) to be protected in case of -// clean -func (e *Execution) ProtectNetwork(t testing.TB, networks ...string) { - t.Helper() - for _, network := range networks { - e.protectedElements.networks[network] = struct{}{} - } -} - -// ProtectNetworks protects existing networks from being cleaned up at the end -// of test runs -func ProtectNetworks(t testing.TB, testEnv *Execution) { - t.Helper() - networks := getExistingNetworks(t, testEnv) - testEnv.ProtectNetwork(t, networks...) -} - -func getExistingNetworks(t testing.TB, testEnv *Execution) []string { - t.Helper() - client := testEnv.APIClient() - networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{}) - assert.NilError(t, err, "failed to list networks") - - var networks []string - for _, network := range networkList { - networks = append(networks, network.ID) - } - return networks -} - -// ProtectPlugin adds the specified plugin(s) to be protected in case of clean -func (e *Execution) ProtectPlugin(t testing.TB, plugins ...string) { - t.Helper() - for _, plugin := range plugins { - e.protectedElements.plugins[plugin] = struct{}{} - } -} - -// ProtectPlugins protects existing plugins from being cleaned up at the end of -// test runs -func ProtectPlugins(t testing.TB, testEnv *Execution) { - t.Helper() - plugins := getExistingPlugins(t, testEnv) - testEnv.ProtectPlugin(t, plugins...) -} - -func getExistingPlugins(t testing.TB, testEnv *Execution) []string { - t.Helper() - client := testEnv.APIClient() - pluginList, err := client.PluginList(context.Background(), filters.Args{}) - // Docker EE does not allow cluster-wide plugin management. - if dclient.IsErrNotImplemented(err) { - return []string{} - } - assert.NilError(t, err, "failed to list plugins") - - var plugins []string - for _, plugin := range pluginList { - plugins = append(plugins, plugin.Name) - } - return plugins -} - -// ProtectVolume adds the specified volume(s) to be protected in case of clean -func (e *Execution) ProtectVolume(t testing.TB, volumes ...string) { - t.Helper() - for _, volume := range volumes { - e.protectedElements.volumes[volume] = struct{}{} - } -} - -// ProtectVolumes protects existing volumes from being cleaned up at the end of -// test runs -func ProtectVolumes(t testing.TB, testEnv *Execution) { - t.Helper() - volumes := getExistingVolumes(t, testEnv) - testEnv.ProtectVolume(t, volumes...) -} - -func getExistingVolumes(t testing.TB, testEnv *Execution) []string { - t.Helper() - client := testEnv.APIClient() - volumeList, err := client.VolumeList(context.Background(), filters.Args{}) - assert.NilError(t, err, "failed to list volumes") - - var volumes []string - for _, volume := range volumeList.Volumes { - volumes = append(volumes, volume.Name) - } - return volumes -} diff --git a/vendor/github.com/docker/docker/testutil/fixtures/load/frozen.go b/vendor/github.com/docker/docker/testutil/fixtures/load/frozen.go deleted file mode 100644 index 6ea591b4f224..000000000000 --- a/vendor/github.com/docker/docker/testutil/fixtures/load/frozen.go +++ /dev/null @@ -1,196 +0,0 @@ -package load // import "github.com/docker/docker/testutil/fixtures/load" - -import ( - "bufio" - "bytes" - "context" - "os" - "os/exec" - "path/filepath" - "strings" - "sync" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/moby/term" - "github.com/pkg/errors" -) - -const frozenImgDir = "/docker-frozen-images" - -// FrozenImagesLinux loads the frozen image set for the integration suite -// If the images are not available locally it will download them -// TODO: This loads whatever is in the frozen image dir, regardless of what -// images were passed in. If the images need to be downloaded, then it will respect -// the passed in images -func FrozenImagesLinux(client client.APIClient, images ...string) error { - var loadImages []struct{ srcName, destName string } - for _, img := range images { - if !imageExists(client, img) { - srcName := img - // hello-world:latest gets re-tagged as hello-world:frozen - // there are some tests that use hello-world:latest specifically so it pulls - // the image and hello-world:frozen is used for when we just want a super - // small image - if img == "hello-world:frozen" { - srcName = "hello-world:latest" - } - loadImages = append(loadImages, struct{ srcName, destName string }{ - srcName: srcName, - destName: img, - }) - } - } - if len(loadImages) == 0 { - // everything is loaded, we're done - return nil - } - - ctx := context.Background() - fi, err := os.Stat(frozenImgDir) - if err != nil || !fi.IsDir() { - srcImages := make([]string, 0, len(loadImages)) - for _, img := range loadImages { - srcImages = append(srcImages, img.srcName) - } - if err := pullImages(ctx, client, srcImages); err != nil { - return errors.Wrap(err, "error pulling image list") - } - } else { - if err := loadFrozenImages(ctx, client); err != nil { - return err - } - } - - for _, img := range loadImages { - if img.srcName != img.destName { - if err := client.ImageTag(ctx, img.srcName, img.destName); err != nil { - return errors.Wrapf(err, "failed to tag %s as %s", img.srcName, img.destName) - } - if _, err := client.ImageRemove(ctx, img.srcName, types.ImageRemoveOptions{}); err != nil { - return errors.Wrapf(err, "failed to remove %s", img.srcName) - } - } - } - return nil -} - -func imageExists(client client.APIClient, name string) bool { - _, _, err := client.ImageInspectWithRaw(context.Background(), name) - return err == nil -} - -func loadFrozenImages(ctx context.Context, client client.APIClient) error { - tar, err := exec.LookPath("tar") - if err != nil { - return errors.Wrap(err, "could not find tar binary") - } - tarCmd := exec.Command(tar, "-cC", frozenImgDir, ".") - out, err := tarCmd.StdoutPipe() - if err != nil { - return errors.Wrap(err, "error getting stdout pipe for tar command") - } - - errBuf := bytes.NewBuffer(nil) - tarCmd.Stderr = errBuf - tarCmd.Start() - defer tarCmd.Wait() - - resp, err := client.ImageLoad(ctx, out, true) - if err != nil { - return errors.Wrap(err, "failed to load frozen images") - } - defer resp.Body.Close() - fd, isTerminal := term.GetFdInfo(os.Stdout) - return jsonmessage.DisplayJSONMessagesStream(resp.Body, os.Stdout, fd, isTerminal, nil) -} - -func pullImages(ctx context.Context, client client.APIClient, images []string) error { - cwd, err := os.Getwd() - if err != nil { - return errors.Wrap(err, "error getting path to dockerfile") - } - dockerfile := os.Getenv("DOCKERFILE") - if dockerfile == "" { - dockerfile = "Dockerfile" - } - dockerfilePath := filepath.Join(filepath.Dir(filepath.Clean(cwd)), dockerfile) - pullRefs, err := readFrozenImageList(dockerfilePath, images) - if err != nil { - return errors.Wrap(err, "error reading frozen image list") - } - - var wg sync.WaitGroup - chErr := make(chan error, len(images)) - for tag, ref := range pullRefs { - wg.Add(1) - go func(tag, ref string) { - defer wg.Done() - if err := pullTagAndRemove(ctx, client, ref, tag); err != nil { - chErr <- err - return - } - }(tag, ref) - } - wg.Wait() - close(chErr) - return <-chErr -} - -func pullTagAndRemove(ctx context.Context, client client.APIClient, ref string, tag string) error { - resp, err := client.ImagePull(ctx, ref, types.ImagePullOptions{}) - if err != nil { - return errors.Wrapf(err, "failed to pull %s", ref) - } - defer resp.Close() - fd, isTerminal := term.GetFdInfo(os.Stdout) - if err := jsonmessage.DisplayJSONMessagesStream(resp, os.Stdout, fd, isTerminal, nil); err != nil { - return err - } - - if err := client.ImageTag(ctx, ref, tag); err != nil { - return errors.Wrapf(err, "failed to tag %s as %s", ref, tag) - } - _, err = client.ImageRemove(ctx, ref, types.ImageRemoveOptions{}) - return errors.Wrapf(err, "failed to remove %s", ref) - -} - -func readFrozenImageList(dockerfilePath string, images []string) (map[string]string, error) { - f, err := os.Open(dockerfilePath) - if err != nil { - return nil, errors.Wrap(err, "error reading dockerfile") - } - defer f.Close() - ls := make(map[string]string) - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := strings.Fields(scanner.Text()) - if len(line) < 3 { - continue - } - if !(line[0] == "RUN" && line[1] == "./contrib/download-frozen-image-v2.sh") { - continue - } - - for scanner.Scan() { - img := strings.TrimSpace(scanner.Text()) - img = strings.TrimSuffix(img, "\\") - img = strings.TrimSpace(img) - split := strings.Split(img, "@") - if len(split) < 2 { - break - } - - for _, i := range images { - if split[0] == i { - ls[i] = img - break - } - } - } - } - return ls, nil -} diff --git a/vendor/github.com/docker/docker/testutil/request/npipe.go b/vendor/github.com/docker/docker/testutil/request/npipe.go deleted file mode 100644 index e827ad6b8006..000000000000 --- a/vendor/github.com/docker/docker/testutil/request/npipe.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !windows -// +build !windows - -package request - -import ( - "net" - "time" -) - -func npipeDial(path string, timeout time.Duration) (net.Conn, error) { - panic("npipe protocol only supported on Windows") -} diff --git a/vendor/github.com/docker/docker/testutil/request/npipe_windows.go b/vendor/github.com/docker/docker/testutil/request/npipe_windows.go deleted file mode 100644 index 9741ae64c653..000000000000 --- a/vendor/github.com/docker/docker/testutil/request/npipe_windows.go +++ /dev/null @@ -1,12 +0,0 @@ -package request - -import ( - "net" - "time" - - winio "github.com/Microsoft/go-winio" -) - -func npipeDial(path string, timeout time.Duration) (net.Conn, error) { - return winio.DialPipe(path, &timeout) -} diff --git a/vendor/github.com/docker/docker/testutil/request/ops.go b/vendor/github.com/docker/docker/testutil/request/ops.go deleted file mode 100644 index be4e502ccb6b..000000000000 --- a/vendor/github.com/docker/docker/testutil/request/ops.go +++ /dev/null @@ -1,77 +0,0 @@ -package request - -import ( - "bytes" - "encoding/json" - "io" - "net/http" - "strings" -) - -// Options defines request options, like request modifiers and which host to target -type Options struct { - host string - requestModifiers []func(*http.Request) error -} - -// Host creates a modifier that sets the specified host as the request URL host -func Host(host string) func(*Options) { - return func(o *Options) { - o.host = host - } -} - -// With adds a request modifier to the options -func With(f func(*http.Request) error) func(*Options) { - return func(o *Options) { - o.requestModifiers = append(o.requestModifiers, f) - } -} - -// Method creates a modifier that sets the specified string as the request method -func Method(method string) func(*Options) { - return With(func(req *http.Request) error { - req.Method = method - return nil - }) -} - -// RawString sets the specified string as body for the request -func RawString(content string) func(*Options) { - return RawContent(io.NopCloser(strings.NewReader(content))) -} - -// RawContent sets the specified reader as body for the request -func RawContent(reader io.ReadCloser) func(*Options) { - return With(func(req *http.Request) error { - req.Body = reader - return nil - }) -} - -// ContentType sets the specified Content-Type request header -func ContentType(contentType string) func(*Options) { - return With(func(req *http.Request) error { - req.Header.Set("Content-Type", contentType) - return nil - }) -} - -// JSON sets the Content-Type request header to json -func JSON(o *Options) { - ContentType("application/json")(o) -} - -// JSONBody creates a modifier that encodes the specified data to a JSON string and set it as request body. It also sets -// the Content-Type header of the request. -func JSONBody(data interface{}) func(*Options) { - return With(func(req *http.Request) error { - jsonData := bytes.NewBuffer(nil) - if err := json.NewEncoder(jsonData).Encode(data); err != nil { - return err - } - req.Body = io.NopCloser(jsonData) - req.Header.Set("Content-Type", "application/json") - return nil - }) -} diff --git a/vendor/github.com/docker/docker/testutil/request/request.go b/vendor/github.com/docker/docker/testutil/request/request.go deleted file mode 100644 index d5f559c66637..000000000000 --- a/vendor/github.com/docker/docker/testutil/request/request.go +++ /dev/null @@ -1,215 +0,0 @@ -package request // import "github.com/docker/docker/testutil/request" - -import ( - "context" - "crypto/tls" - "fmt" - "io" - "net" - "net/http" - "net/url" - "os" - "path/filepath" - "testing" - "time" - - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/testutil/environment" - "github.com/docker/go-connections/sockets" - "github.com/docker/go-connections/tlsconfig" - "github.com/pkg/errors" - "gotest.tools/v3/assert" -) - -// NewAPIClient returns a docker API client configured from environment variables -func NewAPIClient(t testing.TB, ops ...client.Opt) client.APIClient { - t.Helper() - ops = append([]client.Opt{client.FromEnv}, ops...) - clt, err := client.NewClientWithOpts(ops...) - assert.NilError(t, err) - return clt -} - -// DaemonTime provides the current time on the daemon host -func DaemonTime(ctx context.Context, t testing.TB, client client.APIClient, testEnv *environment.Execution) time.Time { - t.Helper() - if testEnv.IsLocalDaemon() { - return time.Now() - } - - info, err := client.Info(ctx) - assert.NilError(t, err) - - dt, err := time.Parse(time.RFC3339Nano, info.SystemTime) - assert.NilError(t, err, "invalid time format in GET /info response") - return dt -} - -// DaemonUnixTime returns the current time on the daemon host with nanoseconds precision. -// It return the time formatted how the client sends timestamps to the server. -func DaemonUnixTime(ctx context.Context, t testing.TB, client client.APIClient, testEnv *environment.Execution) string { - t.Helper() - dt := DaemonTime(ctx, t, client, testEnv) - return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond())) -} - -// Post creates and execute a POST request on the specified host and endpoint, with the specified request modifiers -func Post(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, append(modifiers, Method(http.MethodPost))...) -} - -// Delete creates and execute a DELETE request on the specified host and endpoint, with the specified request modifiers -func Delete(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, append(modifiers, Method(http.MethodDelete))...) -} - -// Get creates and execute a GET request on the specified host and endpoint, with the specified request modifiers -func Get(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, modifiers...) -} - -// Head creates and execute a HEAD request on the specified host and endpoint, with the specified request modifiers -func Head(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, append(modifiers, Method(http.MethodHead))...) -} - -// Do creates and execute a request on the specified endpoint, with the specified request modifiers -func Do(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - opts := &Options{ - host: DaemonHost(), - } - for _, mod := range modifiers { - mod(opts) - } - req, err := newRequest(endpoint, opts) - if err != nil { - return nil, nil, err - } - client, err := newHTTPClient(opts.host) - if err != nil { - return nil, nil, err - } - resp, err := client.Do(req) - var body io.ReadCloser - if resp != nil { - body = ioutils.NewReadCloserWrapper(resp.Body, func() error { - defer resp.Body.Close() - return nil - }) - } - return resp, body, err -} - -// ReadBody read the specified ReadCloser content and returns it -func ReadBody(b io.ReadCloser) ([]byte, error) { - defer b.Close() - return io.ReadAll(b) -} - -// newRequest creates a new http Request to the specified host and endpoint, with the specified request modifiers -func newRequest(endpoint string, opts *Options) (*http.Request, error) { - hostURL, err := client.ParseHostURL(opts.host) - if err != nil { - return nil, errors.Wrapf(err, "failed parsing url %q", opts.host) - } - req, err := http.NewRequest(http.MethodGet, endpoint, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to create request") - } - - if os.Getenv("DOCKER_TLS_VERIFY") != "" { - req.URL.Scheme = "https" - } else { - req.URL.Scheme = "http" - } - req.URL.Host = hostURL.Host - - for _, config := range opts.requestModifiers { - if err := config(req); err != nil { - return nil, err - } - } - - return req, nil -} - -// newHTTPClient creates an http client for the specific host -// TODO: Share more code with client.defaultHTTPClient -func newHTTPClient(host string) (*http.Client, error) { - // FIXME(vdemeester) 10*time.Second timeout of SockRequest… ? - hostURL, err := client.ParseHostURL(host) - if err != nil { - return nil, err - } - transport := new(http.Transport) - if hostURL.Scheme == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" { - // Setup the socket TLS configuration. - tlsConfig, err := getTLSConfig() - if err != nil { - return nil, err - } - transport = &http.Transport{TLSClientConfig: tlsConfig} - } - transport.DisableKeepAlives = true - err = sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host) - return &http.Client{Transport: transport}, err -} - -func getTLSConfig() (*tls.Config, error) { - dockerCertPath := os.Getenv("DOCKER_CERT_PATH") - - if dockerCertPath == "" { - return nil, errors.New("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable") - } - - option := &tlsconfig.Options{ - CAFile: filepath.Join(dockerCertPath, "ca.pem"), - CertFile: filepath.Join(dockerCertPath, "cert.pem"), - KeyFile: filepath.Join(dockerCertPath, "key.pem"), - } - tlsConfig, err := tlsconfig.Client(*option) - if err != nil { - return nil, err - } - - return tlsConfig, nil -} - -// DaemonHost return the daemon host string for this test execution -func DaemonHost() string { - daemonURLStr := client.DefaultDockerHost - if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" { - daemonURLStr = daemonHostVar - } - return daemonURLStr -} - -// SockConn opens a connection on the specified socket -func SockConn(timeout time.Duration, daemon string) (net.Conn, error) { - daemonURL, err := url.Parse(daemon) - if err != nil { - return nil, errors.Wrapf(err, "could not parse url %q", daemon) - } - - var c net.Conn - switch daemonURL.Scheme { - case "npipe": - return npipeDial(daemonURL.Path, timeout) - case "unix": - return net.DialTimeout(daemonURL.Scheme, daemonURL.Path, timeout) - case "tcp": - if os.Getenv("DOCKER_TLS_VERIFY") != "" { - // Setup the socket TLS configuration. - tlsConfig, err := getTLSConfig() - if err != nil { - return nil, err - } - dialer := &net.Dialer{Timeout: timeout} - return tls.DialWithDialer(dialer, daemonURL.Scheme, daemonURL.Host, tlsConfig) - } - return net.DialTimeout(daemonURL.Scheme, daemonURL.Host, timeout) - default: - return c, errors.Errorf("unknown scheme %v (%s)", daemonURL.Scheme, daemon) - } -} diff --git a/vendor/github.com/moby/term/.gitignore b/vendor/github.com/moby/term/.gitignore deleted file mode 100644 index b0747ff010a7..000000000000 --- a/vendor/github.com/moby/term/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# if you want to ignore files created by your editor/tools, consider using a -# global .gitignore or .git/info/exclude see https://help.github.com/articles/ignoring-files -.* -!.github -!.gitignore -profile.out -# support running go modules in vendor mode for local development -vendor/ diff --git a/vendor/github.com/moby/term/LICENSE b/vendor/github.com/moby/term/LICENSE deleted file mode 100644 index 6d8d58fb676b..000000000000 --- a/vendor/github.com/moby/term/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2013-2018 Docker, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/moby/term/README.md b/vendor/github.com/moby/term/README.md deleted file mode 100644 index 0ce92cc33980..000000000000 --- a/vendor/github.com/moby/term/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# term - utilities for dealing with terminals - -![Test](https://github.com/moby/term/workflows/Test/badge.svg) [![GoDoc](https://godoc.org/github.com/moby/term?status.svg)](https://godoc.org/github.com/moby/term) [![Go Report Card](https://goreportcard.com/badge/github.com/moby/term)](https://goreportcard.com/report/github.com/moby/term) - -term provides structures and helper functions to work with terminal (state, sizes). - -#### Using term - -```go -package main - -import ( - "log" - "os" - - "github.com/moby/term" -) - -func main() { - fd := os.Stdin.Fd() - if term.IsTerminal(fd) { - ws, err := term.GetWinsize(fd) - if err != nil { - log.Fatalf("term.GetWinsize: %s", err) - } - log.Printf("%d:%d\n", ws.Height, ws.Width) - } -} -``` - -## Contributing - -Want to hack on term? [Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) apply. - -## Copyright and license -Code and documentation copyright 2015 Docker, inc. Code released under the Apache 2.0 license. Docs released under Creative commons. diff --git a/vendor/github.com/moby/term/ascii.go b/vendor/github.com/moby/term/ascii.go deleted file mode 100644 index 55873c0556c9..000000000000 --- a/vendor/github.com/moby/term/ascii.go +++ /dev/null @@ -1,66 +0,0 @@ -package term - -import ( - "fmt" - "strings" -) - -// ASCII list the possible supported ASCII key sequence -var ASCII = []string{ - "ctrl-@", - "ctrl-a", - "ctrl-b", - "ctrl-c", - "ctrl-d", - "ctrl-e", - "ctrl-f", - "ctrl-g", - "ctrl-h", - "ctrl-i", - "ctrl-j", - "ctrl-k", - "ctrl-l", - "ctrl-m", - "ctrl-n", - "ctrl-o", - "ctrl-p", - "ctrl-q", - "ctrl-r", - "ctrl-s", - "ctrl-t", - "ctrl-u", - "ctrl-v", - "ctrl-w", - "ctrl-x", - "ctrl-y", - "ctrl-z", - "ctrl-[", - "ctrl-\\", - "ctrl-]", - "ctrl-^", - "ctrl-_", -} - -// ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code. -func ToBytes(keys string) ([]byte, error) { - codes := []byte{} -next: - for _, key := range strings.Split(keys, ",") { - if len(key) != 1 { - for code, ctrl := range ASCII { - if ctrl == key { - codes = append(codes, byte(code)) - continue next - } - } - if key == "DEL" { - codes = append(codes, 127) - } else { - return nil, fmt.Errorf("Unknown character: '%s'", key) - } - } else { - codes = append(codes, key[0]) - } - } - return codes, nil -} diff --git a/vendor/github.com/moby/term/proxy.go b/vendor/github.com/moby/term/proxy.go deleted file mode 100644 index c47756b89a9c..000000000000 --- a/vendor/github.com/moby/term/proxy.go +++ /dev/null @@ -1,88 +0,0 @@ -package term - -import ( - "io" -) - -// EscapeError is special error which returned by a TTY proxy reader's Read() -// method in case its detach escape sequence is read. -type EscapeError struct{} - -func (EscapeError) Error() string { - return "read escape sequence" -} - -// escapeProxy is used only for attaches with a TTY. It is used to proxy -// stdin keypresses from the underlying reader and look for the passed in -// escape key sequence to signal a detach. -type escapeProxy struct { - escapeKeys []byte - escapeKeyPos int - r io.Reader - buf []byte -} - -// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader -// and detects when the specified escape keys are read, in which case the Read -// method will return an error of type EscapeError. -func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader { - return &escapeProxy{ - escapeKeys: escapeKeys, - r: r, - } -} - -func (r *escapeProxy) Read(buf []byte) (n int, err error) { - if len(r.escapeKeys) > 0 && r.escapeKeyPos == len(r.escapeKeys) { - return 0, EscapeError{} - } - - if len(r.buf) > 0 { - n = copy(buf, r.buf) - r.buf = r.buf[n:] - } - - nr, err := r.r.Read(buf[n:]) - n += nr - if len(r.escapeKeys) == 0 { - return n, err - } - - for i := 0; i < n; i++ { - if buf[i] == r.escapeKeys[r.escapeKeyPos] { - r.escapeKeyPos++ - - // Check if the full escape sequence is matched. - if r.escapeKeyPos == len(r.escapeKeys) { - n = i + 1 - r.escapeKeyPos - if n < 0 { - n = 0 - } - return n, EscapeError{} - } - continue - } - - // If we need to prepend a partial escape sequence from the previous - // read, make sure the new buffer size doesn't exceed len(buf). - // Otherwise, preserve any extra data in a buffer for the next read. - if i < r.escapeKeyPos { - preserve := make([]byte, 0, r.escapeKeyPos+n) - preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...) - preserve = append(preserve, buf[:n]...) - n = copy(buf, preserve) - i += r.escapeKeyPos - r.buf = append(r.buf, preserve[n:]...) - } - r.escapeKeyPos = 0 - } - - // If we're in the middle of reading an escape sequence, make sure we don't - // let the caller read it. If later on we find that this is not the escape - // sequence, we'll prepend it back to buf. - n -= r.escapeKeyPos - if n < 0 { - n = 0 - } - return n, err -} diff --git a/vendor/github.com/moby/term/tc.go b/vendor/github.com/moby/term/tc.go deleted file mode 100644 index 65556027a6d3..000000000000 --- a/vendor/github.com/moby/term/tc.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package term - -import ( - "golang.org/x/sys/unix" -) - -func tcget(fd uintptr) (*Termios, error) { - p, err := unix.IoctlGetTermios(int(fd), getTermios) - if err != nil { - return nil, err - } - return p, nil -} - -func tcset(fd uintptr, p *Termios) error { - return unix.IoctlSetTermios(int(fd), setTermios, p) -} diff --git a/vendor/github.com/moby/term/term.go b/vendor/github.com/moby/term/term.go deleted file mode 100644 index 29c6acf1c7ef..000000000000 --- a/vendor/github.com/moby/term/term.go +++ /dev/null @@ -1,120 +0,0 @@ -// +build !windows - -// Package term provides structures and helper functions to work with -// terminal (state, sizes). -package term - -import ( - "errors" - "fmt" - "io" - "os" - "os/signal" - - "golang.org/x/sys/unix" -) - -var ( - // ErrInvalidState is returned if the state of the terminal is invalid. - ErrInvalidState = errors.New("Invalid terminal state") -) - -// State represents the state of the terminal. -type State struct { - termios Termios -} - -// Winsize represents the size of the terminal window. -type Winsize struct { - Height uint16 - Width uint16 - x uint16 - y uint16 -} - -// StdStreams returns the standard streams (stdin, stdout, stderr). -func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { - return os.Stdin, os.Stdout, os.Stderr -} - -// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. -func GetFdInfo(in interface{}) (uintptr, bool) { - var inFd uintptr - var isTerminalIn bool - if file, ok := in.(*os.File); ok { - inFd = file.Fd() - isTerminalIn = IsTerminal(inFd) - } - return inFd, isTerminalIn -} - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd uintptr) bool { - _, err := tcget(fd) - return err == nil -} - -// RestoreTerminal restores the terminal connected to the given file descriptor -// to a previous state. -func RestoreTerminal(fd uintptr, state *State) error { - if state == nil { - return ErrInvalidState - } - return tcset(fd, &state.termios) -} - -// SaveState saves the state of the terminal connected to the given file descriptor. -func SaveState(fd uintptr) (*State, error) { - termios, err := tcget(fd) - if err != nil { - return nil, err - } - return &State{termios: *termios}, nil -} - -// DisableEcho applies the specified state to the terminal connected to the file -// descriptor, with echo disabled. -func DisableEcho(fd uintptr, state *State) error { - newState := state.termios - newState.Lflag &^= unix.ECHO - - if err := tcset(fd, &newState); err != nil { - return err - } - handleInterrupt(fd, state) - return nil -} - -// SetRawTerminal puts the terminal connected to the given file descriptor into -// raw mode and returns the previous state. On UNIX, this puts both the input -// and output into raw mode. On Windows, it only puts the input into raw mode. -func SetRawTerminal(fd uintptr) (*State, error) { - oldState, err := MakeRaw(fd) - if err != nil { - return nil, err - } - handleInterrupt(fd, oldState) - return oldState, err -} - -// SetRawTerminalOutput puts the output of terminal connected to the given file -// descriptor into raw mode. On UNIX, this does nothing and returns nil for the -// state. On Windows, it disables LF -> CRLF translation. -func SetRawTerminalOutput(fd uintptr) (*State, error) { - return nil, nil -} - -func handleInterrupt(fd uintptr, state *State) { - sigchan := make(chan os.Signal, 1) - signal.Notify(sigchan, os.Interrupt) - go func() { - for range sigchan { - // quit cleanly and the new terminal item is on a new line - fmt.Println() - signal.Stop(sigchan) - close(sigchan) - RestoreTerminal(fd, state) - os.Exit(1) - } - }() -} diff --git a/vendor/github.com/moby/term/term_windows.go b/vendor/github.com/moby/term/term_windows.go deleted file mode 100644 index ba82960d4a6d..000000000000 --- a/vendor/github.com/moby/term/term_windows.go +++ /dev/null @@ -1,231 +0,0 @@ -package term - -import ( - "io" - "os" - "os/signal" - - windowsconsole "github.com/moby/term/windows" - "golang.org/x/sys/windows" -) - -// State holds the console mode for the terminal. -type State struct { - mode uint32 -} - -// Winsize is used for window size. -type Winsize struct { - Height uint16 - Width uint16 -} - -// vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console -var vtInputSupported bool - -// StdStreams returns the standard streams (stdin, stdout, stderr). -func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { - // Turn on VT handling on all std handles, if possible. This might - // fail, in which case we will fall back to terminal emulation. - var ( - emulateStdin, emulateStdout, emulateStderr bool - - mode uint32 - ) - - fd := windows.Handle(os.Stdin.Fd()) - if err := windows.GetConsoleMode(fd, &mode); err == nil { - // Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it. - if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil { - emulateStdin = true - } else { - vtInputSupported = true - } - // Unconditionally set the console mode back even on failure because SetConsoleMode - // remembers invalid bits on input handles. - _ = windows.SetConsoleMode(fd, mode) - } - - fd = windows.Handle(os.Stdout.Fd()) - if err := windows.GetConsoleMode(fd, &mode); err == nil { - // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it. - if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil { - emulateStdout = true - } else { - _ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) - } - } - - fd = windows.Handle(os.Stderr.Fd()) - if err := windows.GetConsoleMode(fd, &mode); err == nil { - // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it. - if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil { - emulateStderr = true - } else { - _ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) - } - } - - // Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and - // STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as - // go-ansiterm hasn't switch to x/sys/windows. - // TODO: switch back to x/sys/windows once go-ansiterm has switched - if emulateStdin { - h := uint32(windows.STD_INPUT_HANDLE) - stdIn = windowsconsole.NewAnsiReader(int(h)) - } else { - stdIn = os.Stdin - } - - if emulateStdout { - h := uint32(windows.STD_OUTPUT_HANDLE) - stdOut = windowsconsole.NewAnsiWriter(int(h)) - } else { - stdOut = os.Stdout - } - - if emulateStderr { - h := uint32(windows.STD_ERROR_HANDLE) - stdErr = windowsconsole.NewAnsiWriter(int(h)) - } else { - stdErr = os.Stderr - } - - return -} - -// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. -func GetFdInfo(in interface{}) (uintptr, bool) { - return windowsconsole.GetHandleInfo(in) -} - -// GetWinsize returns the window size based on the specified file descriptor. -func GetWinsize(fd uintptr) (*Winsize, error) { - var info windows.ConsoleScreenBufferInfo - if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { - return nil, err - } - - winsize := &Winsize{ - Width: uint16(info.Window.Right - info.Window.Left + 1), - Height: uint16(info.Window.Bottom - info.Window.Top + 1), - } - - return winsize, nil -} - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd uintptr) bool { - var mode uint32 - err := windows.GetConsoleMode(windows.Handle(fd), &mode) - return err == nil -} - -// RestoreTerminal restores the terminal connected to the given file descriptor -// to a previous state. -func RestoreTerminal(fd uintptr, state *State) error { - return windows.SetConsoleMode(windows.Handle(fd), state.mode) -} - -// SaveState saves the state of the terminal connected to the given file descriptor. -func SaveState(fd uintptr) (*State, error) { - var mode uint32 - - if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil { - return nil, err - } - - return &State{mode: mode}, nil -} - -// DisableEcho disables echo for the terminal connected to the given file descriptor. -// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx -func DisableEcho(fd uintptr, state *State) error { - mode := state.mode - mode &^= windows.ENABLE_ECHO_INPUT - mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT - err := windows.SetConsoleMode(windows.Handle(fd), mode) - if err != nil { - return err - } - - // Register an interrupt handler to catch and restore prior state - restoreAtInterrupt(fd, state) - return nil -} - -// SetRawTerminal puts the terminal connected to the given file descriptor into -// raw mode and returns the previous state. On UNIX, this puts both the input -// and output into raw mode. On Windows, it only puts the input into raw mode. -func SetRawTerminal(fd uintptr) (*State, error) { - state, err := MakeRaw(fd) - if err != nil { - return nil, err - } - - // Register an interrupt handler to catch and restore prior state - restoreAtInterrupt(fd, state) - return state, err -} - -// SetRawTerminalOutput puts the output of terminal connected to the given file -// descriptor into raw mode. On UNIX, this does nothing and returns nil for the -// state. On Windows, it disables LF -> CRLF translation. -func SetRawTerminalOutput(fd uintptr) (*State, error) { - state, err := SaveState(fd) - if err != nil { - return nil, err - } - - // Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this - // version of Windows. - _ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN) - return state, err -} - -// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be restored. -func MakeRaw(fd uintptr) (*State, error) { - state, err := SaveState(fd) - if err != nil { - return nil, err - } - - mode := state.mode - - // See - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx - - // Disable these modes - mode &^= windows.ENABLE_ECHO_INPUT - mode &^= windows.ENABLE_LINE_INPUT - mode &^= windows.ENABLE_MOUSE_INPUT - mode &^= windows.ENABLE_WINDOW_INPUT - mode &^= windows.ENABLE_PROCESSED_INPUT - - // Enable these modes - mode |= windows.ENABLE_EXTENDED_FLAGS - mode |= windows.ENABLE_INSERT_MODE - mode |= windows.ENABLE_QUICK_EDIT_MODE - if vtInputSupported { - mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT - } - - err = windows.SetConsoleMode(windows.Handle(fd), mode) - if err != nil { - return nil, err - } - return state, nil -} - -func restoreAtInterrupt(fd uintptr, state *State) { - sigchan := make(chan os.Signal, 1) - signal.Notify(sigchan, os.Interrupt) - - go func() { - _ = <-sigchan - _ = RestoreTerminal(fd, state) - os.Exit(0) - }() -} diff --git a/vendor/github.com/moby/term/termios.go b/vendor/github.com/moby/term/termios.go deleted file mode 100644 index 0f028e2273ac..000000000000 --- a/vendor/github.com/moby/term/termios.go +++ /dev/null @@ -1,35 +0,0 @@ -// +build !windows - -package term - -import ( - "golang.org/x/sys/unix" -) - -// Termios is the Unix API for terminal I/O. -type Termios = unix.Termios - -// MakeRaw puts the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd uintptr) (*State, error) { - termios, err := tcget(fd) - if err != nil { - return nil, err - } - - oldState := State{termios: *termios} - - termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) - termios.Oflag &^= unix.OPOST - termios.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) - termios.Cflag &^= (unix.CSIZE | unix.PARENB) - termios.Cflag |= unix.CS8 - termios.Cc[unix.VMIN] = 1 - termios.Cc[unix.VTIME] = 0 - - if err := tcset(fd, termios); err != nil { - return nil, err - } - return &oldState, nil -} diff --git a/vendor/github.com/moby/term/termios_bsd.go b/vendor/github.com/moby/term/termios_bsd.go deleted file mode 100644 index 922dd4baab04..000000000000 --- a/vendor/github.com/moby/term/termios_bsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build darwin freebsd openbsd netbsd - -package term - -import ( - "golang.org/x/sys/unix" -) - -const ( - getTermios = unix.TIOCGETA - setTermios = unix.TIOCSETA -) diff --git a/vendor/github.com/moby/term/termios_nonbsd.go b/vendor/github.com/moby/term/termios_nonbsd.go deleted file mode 100644 index 038fd61ba1eb..000000000000 --- a/vendor/github.com/moby/term/termios_nonbsd.go +++ /dev/null @@ -1,12 +0,0 @@ -//+build !darwin,!freebsd,!netbsd,!openbsd,!windows - -package term - -import ( - "golang.org/x/sys/unix" -) - -const ( - getTermios = unix.TCGETS - setTermios = unix.TCSETS -) diff --git a/vendor/github.com/moby/term/windows/ansi_reader.go b/vendor/github.com/moby/term/windows/ansi_reader.go deleted file mode 100644 index 155251521b09..000000000000 --- a/vendor/github.com/moby/term/windows/ansi_reader.go +++ /dev/null @@ -1,252 +0,0 @@ -// +build windows - -package windowsconsole - -import ( - "bytes" - "errors" - "fmt" - "io" - "os" - "strings" - "unsafe" - - ansiterm "github.com/Azure/go-ansiterm" - "github.com/Azure/go-ansiterm/winterm" -) - -const ( - escapeSequence = ansiterm.KEY_ESC_CSI -) - -// ansiReader wraps a standard input file (e.g., os.Stdin) providing ANSI sequence translation. -type ansiReader struct { - file *os.File - fd uintptr - buffer []byte - cbBuffer int - command []byte -} - -// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a -// Windows console input handle. -func NewAnsiReader(nFile int) io.ReadCloser { - file, fd := winterm.GetStdFile(nFile) - return &ansiReader{ - file: file, - fd: fd, - command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), - buffer: make([]byte, 0), - } -} - -// Close closes the wrapped file. -func (ar *ansiReader) Close() (err error) { - return ar.file.Close() -} - -// Fd returns the file descriptor of the wrapped file. -func (ar *ansiReader) Fd() uintptr { - return ar.fd -} - -// Read reads up to len(p) bytes of translated input events into p. -func (ar *ansiReader) Read(p []byte) (int, error) { - if len(p) == 0 { - return 0, nil - } - - // Previously read bytes exist, read as much as we can and return - if len(ar.buffer) > 0 { - originalLength := len(ar.buffer) - copiedLength := copy(p, ar.buffer) - - if copiedLength == originalLength { - ar.buffer = make([]byte, 0, len(p)) - } else { - ar.buffer = ar.buffer[copiedLength:] - } - - return copiedLength, nil - } - - // Read and translate key events - events, err := readInputEvents(ar, len(p)) - if err != nil { - return 0, err - } else if len(events) == 0 { - return 0, nil - } - - keyBytes := translateKeyEvents(events, []byte(escapeSequence)) - - // Save excess bytes and right-size keyBytes - if len(keyBytes) > len(p) { - ar.buffer = keyBytes[len(p):] - keyBytes = keyBytes[:len(p)] - } else if len(keyBytes) == 0 { - return 0, nil - } - - copiedLength := copy(p, keyBytes) - if copiedLength != len(keyBytes) { - return 0, errors.New("unexpected copy length encountered") - } - - return copiedLength, nil -} - -// readInputEvents polls until at least one event is available. -func readInputEvents(ar *ansiReader, maxBytes int) ([]winterm.INPUT_RECORD, error) { - // Determine the maximum number of records to retrieve - // -- Cast around the type system to obtain the size of a single INPUT_RECORD. - // unsafe.Sizeof requires an expression vs. a type-reference; the casting - // tricks the type system into believing it has such an expression. - recordSize := int(unsafe.Sizeof(*((*winterm.INPUT_RECORD)(unsafe.Pointer(&maxBytes))))) - countRecords := maxBytes / recordSize - if countRecords > ansiterm.MAX_INPUT_EVENTS { - countRecords = ansiterm.MAX_INPUT_EVENTS - } else if countRecords == 0 { - countRecords = 1 - } - - // Wait for and read input events - events := make([]winterm.INPUT_RECORD, countRecords) - nEvents := uint32(0) - eventsExist, err := winterm.WaitForSingleObject(ar.fd, winterm.WAIT_INFINITE) - if err != nil { - return nil, err - } - - if eventsExist { - err = winterm.ReadConsoleInput(ar.fd, events, &nEvents) - if err != nil { - return nil, err - } - } - - // Return a slice restricted to the number of returned records - return events[:nEvents], nil -} - -// KeyEvent Translation Helpers - -var arrowKeyMapPrefix = map[uint16]string{ - winterm.VK_UP: "%s%sA", - winterm.VK_DOWN: "%s%sB", - winterm.VK_RIGHT: "%s%sC", - winterm.VK_LEFT: "%s%sD", -} - -var keyMapPrefix = map[uint16]string{ - winterm.VK_UP: "\x1B[%sA", - winterm.VK_DOWN: "\x1B[%sB", - winterm.VK_RIGHT: "\x1B[%sC", - winterm.VK_LEFT: "\x1B[%sD", - winterm.VK_HOME: "\x1B[1%s~", // showkey shows ^[[1 - winterm.VK_END: "\x1B[4%s~", // showkey shows ^[[4 - winterm.VK_INSERT: "\x1B[2%s~", - winterm.VK_DELETE: "\x1B[3%s~", - winterm.VK_PRIOR: "\x1B[5%s~", - winterm.VK_NEXT: "\x1B[6%s~", - winterm.VK_F1: "", - winterm.VK_F2: "", - winterm.VK_F3: "\x1B[13%s~", - winterm.VK_F4: "\x1B[14%s~", - winterm.VK_F5: "\x1B[15%s~", - winterm.VK_F6: "\x1B[17%s~", - winterm.VK_F7: "\x1B[18%s~", - winterm.VK_F8: "\x1B[19%s~", - winterm.VK_F9: "\x1B[20%s~", - winterm.VK_F10: "\x1B[21%s~", - winterm.VK_F11: "\x1B[23%s~", - winterm.VK_F12: "\x1B[24%s~", -} - -// translateKeyEvents converts the input events into the appropriate ANSI string. -func translateKeyEvents(events []winterm.INPUT_RECORD, escapeSequence []byte) []byte { - var buffer bytes.Buffer - for _, event := range events { - if event.EventType == winterm.KEY_EVENT && event.KeyEvent.KeyDown != 0 { - buffer.WriteString(keyToString(&event.KeyEvent, escapeSequence)) - } - } - - return buffer.Bytes() -} - -// keyToString maps the given input event record to the corresponding string. -func keyToString(keyEvent *winterm.KEY_EVENT_RECORD, escapeSequence []byte) string { - if keyEvent.UnicodeChar == 0 { - return formatVirtualKey(keyEvent.VirtualKeyCode, keyEvent.ControlKeyState, escapeSequence) - } - - _, alt, control := getControlKeys(keyEvent.ControlKeyState) - if control { - // TODO(azlinux): Implement following control sequences - // -D Signals the end of input from the keyboard; also exits current shell. - // -H Deletes the first character to the left of the cursor. Also called the ERASE key. - // -Q Restarts printing after it has been stopped with -s. - // -S Suspends printing on the screen (does not stop the program). - // -U Deletes all characters on the current line. Also called the KILL key. - // -E Quits current command and creates a core - - } - - // +Key generates ESC N Key - if !control && alt { - return ansiterm.KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar)) - } - - return string(keyEvent.UnicodeChar) -} - -// formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string. -func formatVirtualKey(key uint16, controlState uint32, escapeSequence []byte) string { - shift, alt, control := getControlKeys(controlState) - modifier := getControlKeysModifier(shift, alt, control) - - if format, ok := arrowKeyMapPrefix[key]; ok { - return fmt.Sprintf(format, escapeSequence, modifier) - } - - if format, ok := keyMapPrefix[key]; ok { - return fmt.Sprintf(format, modifier) - } - - return "" -} - -// getControlKeys extracts the shift, alt, and ctrl key states. -func getControlKeys(controlState uint32) (shift, alt, control bool) { - shift = 0 != (controlState & winterm.SHIFT_PRESSED) - alt = 0 != (controlState & (winterm.LEFT_ALT_PRESSED | winterm.RIGHT_ALT_PRESSED)) - control = 0 != (controlState & (winterm.LEFT_CTRL_PRESSED | winterm.RIGHT_CTRL_PRESSED)) - return shift, alt, control -} - -// getControlKeysModifier returns the ANSI modifier for the given combination of control keys. -func getControlKeysModifier(shift, alt, control bool) string { - if shift && alt && control { - return ansiterm.KEY_CONTROL_PARAM_8 - } - if alt && control { - return ansiterm.KEY_CONTROL_PARAM_7 - } - if shift && control { - return ansiterm.KEY_CONTROL_PARAM_6 - } - if control { - return ansiterm.KEY_CONTROL_PARAM_5 - } - if shift && alt { - return ansiterm.KEY_CONTROL_PARAM_4 - } - if alt { - return ansiterm.KEY_CONTROL_PARAM_3 - } - if shift { - return ansiterm.KEY_CONTROL_PARAM_2 - } - return "" -} diff --git a/vendor/github.com/moby/term/windows/ansi_writer.go b/vendor/github.com/moby/term/windows/ansi_writer.go deleted file mode 100644 index ccb5ef07757f..000000000000 --- a/vendor/github.com/moby/term/windows/ansi_writer.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build windows - -package windowsconsole - -import ( - "io" - "os" - - ansiterm "github.com/Azure/go-ansiterm" - "github.com/Azure/go-ansiterm/winterm" -) - -// ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation. -type ansiWriter struct { - file *os.File - fd uintptr - infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO - command []byte - escapeSequence []byte - inAnsiSequence bool - parser *ansiterm.AnsiParser -} - -// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a -// Windows console output handle. -func NewAnsiWriter(nFile int) io.Writer { - file, fd := winterm.GetStdFile(nFile) - info, err := winterm.GetConsoleScreenBufferInfo(fd) - if err != nil { - return nil - } - - parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file)) - - return &ansiWriter{ - file: file, - fd: fd, - infoReset: info, - command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), - escapeSequence: []byte(ansiterm.KEY_ESC_CSI), - parser: parser, - } -} - -func (aw *ansiWriter) Fd() uintptr { - return aw.fd -} - -// Write writes len(p) bytes from p to the underlying data stream. -func (aw *ansiWriter) Write(p []byte) (total int, err error) { - if len(p) == 0 { - return 0, nil - } - - return aw.parser.Parse(p) -} diff --git a/vendor/github.com/moby/term/windows/console.go b/vendor/github.com/moby/term/windows/console.go deleted file mode 100644 index 993694ddcd99..000000000000 --- a/vendor/github.com/moby/term/windows/console.go +++ /dev/null @@ -1,39 +0,0 @@ -// +build windows - -package windowsconsole - -import ( - "os" - - "golang.org/x/sys/windows" -) - -// GetHandleInfo returns file descriptor and bool indicating whether the file is a console. -func GetHandleInfo(in interface{}) (uintptr, bool) { - switch t := in.(type) { - case *ansiReader: - return t.Fd(), true - case *ansiWriter: - return t.Fd(), true - } - - var inFd uintptr - var isTerminal bool - - if file, ok := in.(*os.File); ok { - inFd = file.Fd() - isTerminal = isConsole(inFd) - } - return inFd, isTerminal -} - -// IsConsole returns true if the given file descriptor is a Windows Console. -// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console. -// Deprecated: use golang.org/x/sys/windows.GetConsoleMode() or golang.org/x/term.IsTerminal() -var IsConsole = isConsole - -func isConsole(fd uintptr) bool { - var mode uint32 - err := windows.GetConsoleMode(windows.Handle(fd), &mode) - return err == nil -} diff --git a/vendor/github.com/moby/term/windows/doc.go b/vendor/github.com/moby/term/windows/doc.go deleted file mode 100644 index 54265fffaffd..000000000000 --- a/vendor/github.com/moby/term/windows/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// These files implement ANSI-aware input and output streams for use by the Docker Windows client. -// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create -// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls. - -package windowsconsole diff --git a/vendor/github.com/moby/term/winsize.go b/vendor/github.com/moby/term/winsize.go deleted file mode 100644 index 1ef98d59961e..000000000000 --- a/vendor/github.com/moby/term/winsize.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build !windows - -package term - -import ( - "golang.org/x/sys/unix" -) - -// GetWinsize returns the window size based on the specified file descriptor. -func GetWinsize(fd uintptr) (*Winsize, error) { - uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) - ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} - return ws, err -} - -// SetWinsize tries to set the specified window size for the specified file descriptor. -func SetWinsize(fd uintptr, ws *Winsize) error { - uws := &unix.Winsize{Row: ws.Height, Col: ws.Width, Xpixel: ws.x, Ypixel: ws.y} - return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, uws) -} diff --git a/vendor/gotest.tools/v3/LICENSE b/vendor/gotest.tools/v3/LICENSE deleted file mode 100644 index aeaa2fac3dcb..000000000000 --- a/vendor/gotest.tools/v3/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2018 gotest.tools authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/gotest.tools/v3/assert/assert.go b/vendor/gotest.tools/v3/assert/assert.go deleted file mode 100644 index f3f805dde9c9..000000000000 --- a/vendor/gotest.tools/v3/assert/assert.go +++ /dev/null @@ -1,219 +0,0 @@ -/*Package assert provides assertions for comparing expected values to actual -values. When an assertion fails a helpful error message is printed. - -Assert and Check - -Assert() and Check() both accept a Comparison, and fail the test when the -comparison fails. The one difference is that Assert() will end the test execution -immediately (using t.FailNow()) whereas Check() will fail the test (using t.Fail()), -return the value of the comparison, then proceed with the rest of the test case. - -Example usage - -The example below shows assert used with some common types. - - - import ( - "testing" - - "gotest.tools/assert" - is "gotest.tools/assert/cmp" - ) - - func TestEverything(t *testing.T) { - // booleans - assert.Assert(t, ok) - assert.Assert(t, !missing) - - // primitives - assert.Equal(t, count, 1) - assert.Equal(t, msg, "the message") - assert.Assert(t, total != 10) // NotEqual - - // errors - assert.NilError(t, closer.Close()) - assert.Error(t, err, "the exact error message") - assert.ErrorContains(t, err, "includes this") - assert.ErrorType(t, err, os.IsNotExist) - - // complex types - assert.DeepEqual(t, result, myStruct{Name: "title"}) - assert.Assert(t, is.Len(items, 3)) - assert.Assert(t, len(sequence) != 0) // NotEmpty - assert.Assert(t, is.Contains(mapping, "key")) - - // pointers and interface - assert.Assert(t, is.Nil(ref)) - assert.Assert(t, ref != nil) // NotNil - } - -Comparisons - -Package http://pkg.go.dev/gotest.tools/v3/assert/cmp provides -many common comparisons. Additional comparisons can be written to compare -values in other ways. See the example Assert (CustomComparison). - -Automated migration from testify - -gty-migrate-from-testify is a command which translates Go source code from -testify assertions to the assertions provided by this package. - -See http://pkg.go.dev/gotest.tools/v3/assert/cmd/gty-migrate-from-testify. - - -*/ -package assert // import "gotest.tools/v3/assert" - -import ( - gocmp "github.com/google/go-cmp/cmp" - "gotest.tools/v3/assert/cmp" - "gotest.tools/v3/internal/assert" -) - -// BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage. -type BoolOrComparison interface{} - -// TestingT is the subset of testing.T used by the assert package. -type TestingT interface { - FailNow() - Fail() - Log(args ...interface{}) -} - -type helperT interface { - Helper() -} - -// Assert performs a comparison. If the comparison fails, the test is marked as -// failed, a failure message is logged, and execution is stopped immediately. -// -// The comparison argument may be one of three types: -// bool -// True is success. False is a failure. -// The failure message will contain the literal source code of the expression. -// cmp.Comparison -// Uses cmp.Result.Success() to check for success of failure. -// The comparison is responsible for producing a helpful failure message. -// http://pkg.go.dev/gotest.tools/v3/assert/cmp provides many common comparisons. -// error -// A nil value is considered success. -// A non-nil error is a failure, err.Error() is used as the failure message. -func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) { - t.FailNow() - } -} - -// Check performs a comparison. If the comparison fails the test is marked as -// failed, a failure message is logged, and Check returns false. Otherwise returns -// true. -// -// See Assert for details about the comparison arg and failure messages. -func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) bool { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsFromComparisonCall, comparison, msgAndArgs...) { - t.Fail() - return false - } - return true -} - -// NilError fails the test immediately if err is not nil. -// This is equivalent to Assert(t, err) -func NilError(t TestingT, err error, msgAndArgs ...interface{}) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsAfterT, err, msgAndArgs...) { - t.FailNow() - } -} - -// Equal uses the == operator to assert two values are equal and fails the test -// if they are not equal. -// -// If the comparison fails Equal will use the variable names for x and y as part -// of the failure message to identify the actual and expected values. -// -// If either x or y are a multi-line string the failure message will include a -// unified diff of the two values. If the values only differ by whitespace -// the unified diff will be augmented by replacing whitespace characters with -// visible characters to identify the whitespace difference. -// -// This is equivalent to Assert(t, cmp.Equal(x, y)). -func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsAfterT, cmp.Equal(x, y), msgAndArgs...) { - t.FailNow() - } -} - -// DeepEqual uses google/go-cmp (https://godoc.org/github.com/google/go-cmp/cmp) -// to assert two values are equal and fails the test if they are not equal. -// -// Package http://pkg.go.dev/gotest.tools/v3/assert/opt provides some additional -// commonly used Options. -// -// This is equivalent to Assert(t, cmp.DeepEqual(x, y)). -func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsAfterT, cmp.DeepEqual(x, y, opts...)) { - t.FailNow() - } -} - -// Error fails the test if err is nil, or the error message is not the expected -// message. -// Equivalent to Assert(t, cmp.Error(err, message)). -func Error(t TestingT, err error, message string, msgAndArgs ...interface{}) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsAfterT, cmp.Error(err, message), msgAndArgs...) { - t.FailNow() - } -} - -// ErrorContains fails the test if err is nil, or the error message does not -// contain the expected substring. -// Equivalent to Assert(t, cmp.ErrorContains(err, substring)). -func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interface{}) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) { - t.FailNow() - } -} - -// ErrorType fails the test if err is nil, or err is not the expected type. -// Equivalent to Assert(t, cmp.ErrorType(err, expected)). -// -// Expected can be one of: -// func(error) bool -// Function should return true if the error is the expected type. -// type struct{}, type &struct{} -// A struct or a pointer to a struct. -// Fails if the error is not of the same type as expected. -// type &interface{} -// A pointer to an interface type. -// Fails if err does not implement the interface. -// reflect.Type -// Fails if err does not implement the reflect.Type -func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interface{}) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if !assert.Eval(t, assert.ArgsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) { - t.FailNow() - } -} diff --git a/vendor/gotest.tools/v3/assert/cmp/compare.go b/vendor/gotest.tools/v3/assert/cmp/compare.go deleted file mode 100644 index 3c0e05ab5fe9..000000000000 --- a/vendor/gotest.tools/v3/assert/cmp/compare.go +++ /dev/null @@ -1,365 +0,0 @@ -/*Package cmp provides Comparisons for Assert and Check*/ -package cmp // import "gotest.tools/v3/assert/cmp" - -import ( - "fmt" - "reflect" - "regexp" - "strings" - - "github.com/google/go-cmp/cmp" - "gotest.tools/v3/internal/format" -) - -// Comparison is a function which compares values and returns ResultSuccess if -// the actual value matches the expected value. If the values do not match the -// Result will contain a message about why it failed. -type Comparison func() Result - -// DeepEqual compares two values using google/go-cmp -// (https://godoc.org/github.com/google/go-cmp/cmp) -// and succeeds if the values are equal. -// -// The comparison can be customized using comparison Options. -// Package http://pkg.go.dev/gotest.tools/v3/assert/opt provides some additional -// commonly used Options. -func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison { - return func() (result Result) { - defer func() { - if panicmsg, handled := handleCmpPanic(recover()); handled { - result = ResultFailure(panicmsg) - } - }() - diff := cmp.Diff(x, y, opts...) - if diff == "" { - return ResultSuccess - } - return multiLineDiffResult(diff) - } -} - -func handleCmpPanic(r interface{}) (string, bool) { - if r == nil { - return "", false - } - panicmsg, ok := r.(string) - if !ok { - panic(r) - } - switch { - case strings.HasPrefix(panicmsg, "cannot handle unexported field"): - return panicmsg, true - } - panic(r) -} - -func toResult(success bool, msg string) Result { - if success { - return ResultSuccess - } - return ResultFailure(msg) -} - -// RegexOrPattern may be either a *regexp.Regexp or a string that is a valid -// regexp pattern. -type RegexOrPattern interface{} - -// Regexp succeeds if value v matches regular expression re. -// -// Example: -// assert.Assert(t, cmp.Regexp("^[0-9a-f]{32}$", str)) -// r := regexp.MustCompile("^[0-9a-f]{32}$") -// assert.Assert(t, cmp.Regexp(r, str)) -func Regexp(re RegexOrPattern, v string) Comparison { - match := func(re *regexp.Regexp) Result { - return toResult( - re.MatchString(v), - fmt.Sprintf("value %q does not match regexp %q", v, re.String())) - } - - return func() Result { - switch regex := re.(type) { - case *regexp.Regexp: - return match(regex) - case string: - re, err := regexp.Compile(regex) - if err != nil { - return ResultFailure(err.Error()) - } - return match(re) - default: - return ResultFailure(fmt.Sprintf("invalid type %T for regex pattern", regex)) - } - } -} - -// Equal succeeds if x == y. See assert.Equal for full documentation. -func Equal(x, y interface{}) Comparison { - return func() Result { - switch { - case x == y: - return ResultSuccess - case isMultiLineStringCompare(x, y): - diff := format.UnifiedDiff(format.DiffConfig{A: x.(string), B: y.(string)}) - return multiLineDiffResult(diff) - } - return ResultFailureTemplate(` - {{- printf "%v" .Data.x}} ( - {{- with callArg 0 }}{{ formatNode . }} {{end -}} - {{- printf "%T" .Data.x -}} - ) != {{ printf "%v" .Data.y}} ( - {{- with callArg 1 }}{{ formatNode . }} {{end -}} - {{- printf "%T" .Data.y -}} - )`, - map[string]interface{}{"x": x, "y": y}) - } -} - -func isMultiLineStringCompare(x, y interface{}) bool { - strX, ok := x.(string) - if !ok { - return false - } - strY, ok := y.(string) - if !ok { - return false - } - return strings.Contains(strX, "\n") || strings.Contains(strY, "\n") -} - -func multiLineDiffResult(diff string) Result { - return ResultFailureTemplate(` ---- {{ with callArg 0 }}{{ formatNode . }}{{else}}←{{end}} -+++ {{ with callArg 1 }}{{ formatNode . }}{{else}}→{{end}} -{{ .Data.diff }}`, - map[string]interface{}{"diff": diff}) -} - -// Len succeeds if the sequence has the expected length. -func Len(seq interface{}, expected int) Comparison { - return func() (result Result) { - defer func() { - if e := recover(); e != nil { - result = ResultFailure(fmt.Sprintf("type %T does not have a length", seq)) - } - }() - value := reflect.ValueOf(seq) - length := value.Len() - if length == expected { - return ResultSuccess - } - msg := fmt.Sprintf("expected %s (length %d) to have length %d", seq, length, expected) - return ResultFailure(msg) - } -} - -// Contains succeeds if item is in collection. Collection may be a string, map, -// slice, or array. -// -// If collection is a string, item must also be a string, and is compared using -// strings.Contains(). -// If collection is a Map, contains will succeed if item is a key in the map. -// If collection is a slice or array, item is compared to each item in the -// sequence using reflect.DeepEqual(). -func Contains(collection interface{}, item interface{}) Comparison { - return func() Result { - colValue := reflect.ValueOf(collection) - if !colValue.IsValid() { - return ResultFailure(fmt.Sprintf("nil does not contain items")) - } - msg := fmt.Sprintf("%v does not contain %v", collection, item) - - itemValue := reflect.ValueOf(item) - switch colValue.Type().Kind() { - case reflect.String: - if itemValue.Type().Kind() != reflect.String { - return ResultFailure("string may only contain strings") - } - return toResult( - strings.Contains(colValue.String(), itemValue.String()), - fmt.Sprintf("string %q does not contain %q", collection, item)) - - case reflect.Map: - if itemValue.Type() != colValue.Type().Key() { - return ResultFailure(fmt.Sprintf( - "%v can not contain a %v key", colValue.Type(), itemValue.Type())) - } - return toResult(colValue.MapIndex(itemValue).IsValid(), msg) - - case reflect.Slice, reflect.Array: - for i := 0; i < colValue.Len(); i++ { - if reflect.DeepEqual(colValue.Index(i).Interface(), item) { - return ResultSuccess - } - } - return ResultFailure(msg) - default: - return ResultFailure(fmt.Sprintf("type %T does not contain items", collection)) - } - } -} - -// Panics succeeds if f() panics. -func Panics(f func()) Comparison { - return func() (result Result) { - defer func() { - if err := recover(); err != nil { - result = ResultSuccess - } - }() - f() - return ResultFailure("did not panic") - } -} - -// Error succeeds if err is a non-nil error, and the error message equals the -// expected message. -func Error(err error, message string) Comparison { - return func() Result { - switch { - case err == nil: - return ResultFailure("expected an error, got nil") - case err.Error() != message: - return ResultFailure(fmt.Sprintf( - "expected error %q, got %s", message, formatErrorMessage(err))) - } - return ResultSuccess - } -} - -// ErrorContains succeeds if err is a non-nil error, and the error message contains -// the expected substring. -func ErrorContains(err error, substring string) Comparison { - return func() Result { - switch { - case err == nil: - return ResultFailure("expected an error, got nil") - case !strings.Contains(err.Error(), substring): - return ResultFailure(fmt.Sprintf( - "expected error to contain %q, got %s", substring, formatErrorMessage(err))) - } - return ResultSuccess - } -} - -type causer interface { - Cause() error -} - -func formatErrorMessage(err error) string { - if _, ok := err.(causer); ok { - return fmt.Sprintf("%q\n%+v", err, err) - } - // This error was not wrapped with github.com/pkg/errors - return fmt.Sprintf("%q", err) -} - -// Nil succeeds if obj is a nil interface, pointer, or function. -// -// Use NilError() for comparing errors. Use Len(obj, 0) for comparing slices, -// maps, and channels. -func Nil(obj interface{}) Comparison { - msgFunc := func(value reflect.Value) string { - return fmt.Sprintf("%v (type %s) is not nil", reflect.Indirect(value), value.Type()) - } - return isNil(obj, msgFunc) -} - -func isNil(obj interface{}, msgFunc func(reflect.Value) string) Comparison { - return func() Result { - if obj == nil { - return ResultSuccess - } - value := reflect.ValueOf(obj) - kind := value.Type().Kind() - if kind >= reflect.Chan && kind <= reflect.Slice { - if value.IsNil() { - return ResultSuccess - } - return ResultFailure(msgFunc(value)) - } - - return ResultFailure(fmt.Sprintf("%v (type %s) can not be nil", value, value.Type())) - } -} - -// ErrorType succeeds if err is not nil and is of the expected type. -// -// Expected can be one of: -// func(error) bool -// Function should return true if the error is the expected type. -// type struct{}, type &struct{} -// A struct or a pointer to a struct. -// Fails if the error is not of the same type as expected. -// type &interface{} -// A pointer to an interface type. -// Fails if err does not implement the interface. -// reflect.Type -// Fails if err does not implement the reflect.Type -func ErrorType(err error, expected interface{}) Comparison { - return func() Result { - switch expectedType := expected.(type) { - case func(error) bool: - return cmpErrorTypeFunc(err, expectedType) - case reflect.Type: - if expectedType.Kind() == reflect.Interface { - return cmpErrorTypeImplementsType(err, expectedType) - } - return cmpErrorTypeEqualType(err, expectedType) - case nil: - return ResultFailure(fmt.Sprintf("invalid type for expected: nil")) - } - - expectedType := reflect.TypeOf(expected) - switch { - case expectedType.Kind() == reflect.Struct, isPtrToStruct(expectedType): - return cmpErrorTypeEqualType(err, expectedType) - case isPtrToInterface(expectedType): - return cmpErrorTypeImplementsType(err, expectedType.Elem()) - } - return ResultFailure(fmt.Sprintf("invalid type for expected: %T", expected)) - } -} - -func cmpErrorTypeFunc(err error, f func(error) bool) Result { - if f(err) { - return ResultSuccess - } - actual := "nil" - if err != nil { - actual = fmt.Sprintf("%s (%T)", err, err) - } - return ResultFailureTemplate(`error is {{ .Data.actual }} - {{- with callArg 1 }}, not {{ formatNode . }}{{end -}}`, - map[string]interface{}{"actual": actual}) -} - -func cmpErrorTypeEqualType(err error, expectedType reflect.Type) Result { - if err == nil { - return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType)) - } - errValue := reflect.ValueOf(err) - if errValue.Type() == expectedType { - return ResultSuccess - } - return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType)) -} - -func cmpErrorTypeImplementsType(err error, expectedType reflect.Type) Result { - if err == nil { - return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType)) - } - errValue := reflect.ValueOf(err) - if errValue.Type().Implements(expectedType) { - return ResultSuccess - } - return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType)) -} - -func isPtrToInterface(typ reflect.Type) bool { - return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Interface -} - -func isPtrToStruct(typ reflect.Type) bool { - return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct -} diff --git a/vendor/gotest.tools/v3/assert/cmp/result.go b/vendor/gotest.tools/v3/assert/cmp/result.go deleted file mode 100644 index 3b48d9bf0c0c..000000000000 --- a/vendor/gotest.tools/v3/assert/cmp/result.go +++ /dev/null @@ -1,99 +0,0 @@ -package cmp - -import ( - "bytes" - "fmt" - "go/ast" - "text/template" - - "gotest.tools/v3/internal/source" -) - -// A Result of a Comparison. -type Result interface { - Success() bool -} - -// StringResult is an implementation of Result that reports the error message -// string verbatim and does not provide any templating or formatting of the -// message. -type StringResult struct { - success bool - message string -} - -// Success returns true if the comparison was successful. -func (r StringResult) Success() bool { - return r.success -} - -// FailureMessage returns the message used to provide additional information -// about the failure. -func (r StringResult) FailureMessage() string { - return r.message -} - -// ResultSuccess is a constant which is returned by a ComparisonWithResult to -// indicate success. -var ResultSuccess = StringResult{success: true} - -// ResultFailure returns a failed Result with a failure message. -func ResultFailure(message string) StringResult { - return StringResult{message: message} -} - -// ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure -// is returned with the error message as the failure message. -func ResultFromError(err error) Result { - if err == nil { - return ResultSuccess - } - return ResultFailure(err.Error()) -} - -type templatedResult struct { - template string - data map[string]interface{} -} - -func (r templatedResult) Success() bool { - return false -} - -func (r templatedResult) FailureMessage(args []ast.Expr) string { - msg, err := renderMessage(r, args) - if err != nil { - return fmt.Sprintf("failed to render failure message: %s", err) - } - return msg -} - -// ResultFailureTemplate returns a Result with a template string and data which -// can be used to format a failure message. The template may access data from .Data, -// the comparison args with the callArg function, and the formatNode function may -// be used to format the call args. -func ResultFailureTemplate(template string, data map[string]interface{}) Result { - return templatedResult{template: template, data: data} -} - -func renderMessage(result templatedResult, args []ast.Expr) (string, error) { - tmpl := template.New("failure").Funcs(template.FuncMap{ - "formatNode": source.FormatNode, - "callArg": func(index int) ast.Expr { - if index >= len(args) { - return nil - } - return args[index] - }, - }) - var err error - tmpl, err = tmpl.Parse(result.template) - if err != nil { - return "", err - } - buf := new(bytes.Buffer) - err = tmpl.Execute(buf, map[string]interface{}{ - "Data": result.data, - }) - return buf.String(), err -} diff --git a/vendor/gotest.tools/v3/internal/assert/assert.go b/vendor/gotest.tools/v3/internal/assert/assert.go deleted file mode 100644 index 8dc01f4b5e08..000000000000 --- a/vendor/gotest.tools/v3/internal/assert/assert.go +++ /dev/null @@ -1,143 +0,0 @@ -package assert - -import ( - "fmt" - "go/ast" - "go/token" - "reflect" - - "gotest.tools/v3/assert/cmp" - "gotest.tools/v3/internal/format" - "gotest.tools/v3/internal/source" -) - -// LogT is the subset of testing.T used by the assert package. -type LogT interface { - Log(args ...interface{}) -} - -type helperT interface { - Helper() -} - -const failureMessage = "assertion failed: " - -// Eval the comparison and print a failure messages if the comparison has failed. -// nolint: gocyclo -func Eval( - t LogT, - argSelector argSelector, - comparison interface{}, - msgAndArgs ...interface{}, -) bool { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - var success bool - switch check := comparison.(type) { - case bool: - if check { - return true - } - logFailureFromBool(t, msgAndArgs...) - - // Undocumented legacy comparison without Result type - case func() (success bool, message string): - success = runCompareFunc(t, check, msgAndArgs...) - - case nil: - return true - - case error: - msg := failureMsgFromError(check) - t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...)) - - case cmp.Comparison: - success = RunComparison(t, argSelector, check, msgAndArgs...) - - case func() cmp.Result: - success = RunComparison(t, argSelector, check, msgAndArgs...) - - default: - t.Log(fmt.Sprintf("invalid Comparison: %v (%T)", check, check)) - } - return success -} - -func runCompareFunc( - t LogT, - f func() (success bool, message string), - msgAndArgs ...interface{}, -) bool { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - if success, message := f(); !success { - t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) - return false - } - return true -} - -func logFailureFromBool(t LogT, msgAndArgs ...interface{}) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - const stackIndex = 3 // Assert()/Check(), assert(), logFailureFromBool() - args, err := source.CallExprArgs(stackIndex) - if err != nil { - t.Log(err.Error()) - return - } - - const comparisonArgIndex = 1 // Assert(t, comparison) - if len(args) <= comparisonArgIndex { - t.Log(failureMessage + "but assert failed to find the expression to print") - return - } - - msg, err := boolFailureMessage(args[comparisonArgIndex]) - if err != nil { - t.Log(err.Error()) - msg = "expression is false" - } - - t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...)) -} - -func failureMsgFromError(err error) string { - // Handle errors with non-nil types - v := reflect.ValueOf(err) - if v.Kind() == reflect.Ptr && v.IsNil() { - return fmt.Sprintf("error is not nil: error has type %T", err) - } - return "error is not nil: " + err.Error() -} - -func boolFailureMessage(expr ast.Expr) (string, error) { - if binaryExpr, ok := expr.(*ast.BinaryExpr); ok && binaryExpr.Op == token.NEQ { - x, err := source.FormatNode(binaryExpr.X) - if err != nil { - return "", err - } - y, err := source.FormatNode(binaryExpr.Y) - if err != nil { - return "", err - } - return x + " is " + y, nil - } - - if unaryExpr, ok := expr.(*ast.UnaryExpr); ok && unaryExpr.Op == token.NOT { - x, err := source.FormatNode(unaryExpr.X) - if err != nil { - return "", err - } - return x + " is true", nil - } - - formatted, err := source.FormatNode(expr) - if err != nil { - return "", err - } - return "expression is false: " + formatted, nil -} diff --git a/vendor/gotest.tools/v3/internal/assert/result.go b/vendor/gotest.tools/v3/internal/assert/result.go deleted file mode 100644 index 20cd54129ed3..000000000000 --- a/vendor/gotest.tools/v3/internal/assert/result.go +++ /dev/null @@ -1,125 +0,0 @@ -package assert - -import ( - "fmt" - "go/ast" - - "gotest.tools/v3/assert/cmp" - "gotest.tools/v3/internal/format" - "gotest.tools/v3/internal/source" -) - -// RunComparison and return Comparison.Success. If the comparison fails a messages -// will be printed using t.Log. -func RunComparison( - t LogT, - argSelector argSelector, - f cmp.Comparison, - msgAndArgs ...interface{}, -) bool { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - result := f() - if result.Success() { - return true - } - - var message string - switch typed := result.(type) { - case resultWithComparisonArgs: - const stackIndex = 3 // Assert/Check, assert, RunComparison - args, err := source.CallExprArgs(stackIndex) - if err != nil { - t.Log(err.Error()) - } - message = typed.FailureMessage(filterPrintableExpr(argSelector(args))) - case resultBasic: - message = typed.FailureMessage() - default: - message = fmt.Sprintf("comparison returned invalid Result type: %T", result) - } - - t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) - return false -} - -type resultWithComparisonArgs interface { - FailureMessage(args []ast.Expr) string -} - -type resultBasic interface { - FailureMessage() string -} - -// filterPrintableExpr filters the ast.Expr slice to only include Expr that are -// easy to read when printed and contain relevant information to an assertion. -// -// Ident and SelectorExpr are included because they print nicely and the variable -// names may provide additional context to their values. -// BasicLit and CompositeLit are excluded because their source is equivalent to -// their value, which is already available. -// Other types are ignored for now, but could be added if they are relevant. -func filterPrintableExpr(args []ast.Expr) []ast.Expr { - result := make([]ast.Expr, len(args)) - for i, arg := range args { - if isShortPrintableExpr(arg) { - result[i] = arg - continue - } - - if starExpr, ok := arg.(*ast.StarExpr); ok { - result[i] = starExpr.X - continue - } - } - return result -} - -func isShortPrintableExpr(expr ast.Expr) bool { - switch expr.(type) { - case *ast.Ident, *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr: - return true - case *ast.BinaryExpr, *ast.UnaryExpr: - return true - default: - // CallExpr, ParenExpr, TypeAssertExpr, KeyValueExpr, StarExpr - return false - } -} - -type argSelector func([]ast.Expr) []ast.Expr - -// ArgsAfterT selects args starting at position 1. Used when the caller has a -// testing.T as the first argument, and the args to select should follow it. -func ArgsAfterT(args []ast.Expr) []ast.Expr { - if len(args) < 1 { - return nil - } - return args[1:] -} - -// ArgsFromComparisonCall selects args from the CallExpression at position 1. -// Used when the caller has a testing.T as the first argument, and the args to -// select are passed to the cmp.Comparison at position 1. -func ArgsFromComparisonCall(args []ast.Expr) []ast.Expr { - if len(args) <= 1 { - return nil - } - if callExpr, ok := args[1].(*ast.CallExpr); ok { - return callExpr.Args - } - return nil -} - -// ArgsAtZeroIndex selects args from the CallExpression at position 1. -// Used when the caller accepts a single cmp.Comparison argument. -func ArgsAtZeroIndex(args []ast.Expr) []ast.Expr { - if len(args) == 0 { - return nil - } - if callExpr, ok := args[0].(*ast.CallExpr); ok { - return callExpr.Args - } - return nil -} diff --git a/vendor/gotest.tools/v3/internal/difflib/LICENSE b/vendor/gotest.tools/v3/internal/difflib/LICENSE deleted file mode 100644 index c67dad612a3d..000000000000 --- a/vendor/gotest.tools/v3/internal/difflib/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2013, Patrick Mezard -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - The names of its contributors may not be used to endorse or promote -products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/gotest.tools/v3/internal/difflib/difflib.go b/vendor/gotest.tools/v3/internal/difflib/difflib.go deleted file mode 100644 index 9bf506b6be0e..000000000000 --- a/vendor/gotest.tools/v3/internal/difflib/difflib.go +++ /dev/null @@ -1,423 +0,0 @@ -/*Package difflib is a partial port of Python difflib module. - -Original source: https://github.com/pmezard/go-difflib - -This file is trimmed to only the parts used by this repository. -*/ -package difflib // import "gotest.tools/v3/internal/difflib" - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -// Match stores line numbers of size of match -type Match struct { - A int - B int - Size int -} - -// OpCode identifies the type of diff -type OpCode struct { - Tag byte - I1 int - I2 int - J1 int - J2 int -} - -// SequenceMatcher compares sequence of strings. The basic -// algorithm predates, and is a little fancier than, an algorithm -// published in the late 1980's by Ratcliff and Obershelp under the -// hyperbolic name "gestalt pattern matching". The basic idea is to find -// the longest contiguous matching subsequence that contains no "junk" -// elements (R-O doesn't address junk). The same idea is then applied -// recursively to the pieces of the sequences to the left and to the right -// of the matching subsequence. This does not yield minimal edit -// sequences, but does tend to yield matches that "look right" to people. -// -// SequenceMatcher tries to compute a "human-friendly diff" between two -// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the -// longest *contiguous* & junk-free matching subsequence. That's what -// catches peoples' eyes. The Windows(tm) windiff has another interesting -// notion, pairing up elements that appear uniquely in each sequence. -// That, and the method here, appear to yield more intuitive difference -// reports than does diff. This method appears to be the least vulnerable -// to synching up on blocks of "junk lines", though (like blank lines in -// ordinary text files, or maybe "

" lines in HTML files). That may be -// because this is the only method of the 3 that has a *concept* of -// "junk" . -// -// Timing: Basic R-O is cubic time worst case and quadratic time expected -// case. SequenceMatcher is quadratic time for the worst case and has -// expected-case behavior dependent in a complicated way on how many -// elements the sequences have in common; best case time is linear. -type SequenceMatcher struct { - a []string - b []string - b2j map[string][]int - IsJunk func(string) bool - autoJunk bool - bJunk map[string]struct{} - matchingBlocks []Match - fullBCount map[string]int - bPopular map[string]struct{} - opCodes []OpCode -} - -// NewMatcher returns a new SequenceMatcher -func NewMatcher(a, b []string) *SequenceMatcher { - m := SequenceMatcher{autoJunk: true} - m.SetSeqs(a, b) - return &m -} - -// SetSeqs sets two sequences to be compared. -func (m *SequenceMatcher) SetSeqs(a, b []string) { - m.SetSeq1(a) - m.SetSeq2(b) -} - -// SetSeq1 sets the first sequence to be compared. The second sequence to be compared is -// not changed. -// -// SequenceMatcher computes and caches detailed information about the second -// sequence, so if you want to compare one sequence S against many sequences, -// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other -// sequences. -// -// See also SetSeqs() and SetSeq2(). -func (m *SequenceMatcher) SetSeq1(a []string) { - if &a == &m.a { - return - } - m.a = a - m.matchingBlocks = nil - m.opCodes = nil -} - -// SetSeq2 sets the second sequence to be compared. The first sequence to be compared is -// not changed. -func (m *SequenceMatcher) SetSeq2(b []string) { - if &b == &m.b { - return - } - m.b = b - m.matchingBlocks = nil - m.opCodes = nil - m.fullBCount = nil - m.chainB() -} - -func (m *SequenceMatcher) chainB() { - // Populate line -> index mapping - b2j := map[string][]int{} - for i, s := range m.b { - indices := b2j[s] - indices = append(indices, i) - b2j[s] = indices - } - - // Purge junk elements - m.bJunk = map[string]struct{}{} - if m.IsJunk != nil { - junk := m.bJunk - for s := range b2j { - if m.IsJunk(s) { - junk[s] = struct{}{} - } - } - for s := range junk { - delete(b2j, s) - } - } - - // Purge remaining popular elements - popular := map[string]struct{}{} - n := len(m.b) - if m.autoJunk && n >= 200 { - ntest := n/100 + 1 - for s, indices := range b2j { - if len(indices) > ntest { - popular[s] = struct{}{} - } - } - for s := range popular { - delete(b2j, s) - } - } - m.bPopular = popular - m.b2j = b2j -} - -func (m *SequenceMatcher) isBJunk(s string) bool { - _, ok := m.bJunk[s] - return ok -} - -// Find longest matching block in a[alo:ahi] and b[blo:bhi]. -// -// If IsJunk is not defined: -// -// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where -// alo <= i <= i+k <= ahi -// blo <= j <= j+k <= bhi -// and for all (i',j',k') meeting those conditions, -// k >= k' -// i <= i' -// and if i == i', j <= j' -// -// In other words, of all maximal matching blocks, return one that -// starts earliest in a, and of all those maximal matching blocks that -// start earliest in a, return the one that starts earliest in b. -// -// If IsJunk is defined, first the longest matching block is -// determined as above, but with the additional restriction that no -// junk element appears in the block. Then that block is extended as -// far as possible by matching (only) junk elements on both sides. So -// the resulting block never matches on junk except as identical junk -// happens to be adjacent to an "interesting" match. -// -// If no blocks match, return (alo, blo, 0). -func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { - // CAUTION: stripping common prefix or suffix would be incorrect. - // E.g., - // ab - // acab - // Longest matching block is "ab", but if common prefix is - // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so - // strip, so ends up claiming that ab is changed to acab by - // inserting "ca" in the middle. That's minimal but unintuitive: - // "it's obvious" that someone inserted "ac" at the front. - // Windiff ends up at the same place as diff, but by pairing up - // the unique 'b's and then matching the first two 'a's. - besti, bestj, bestsize := alo, blo, 0 - - // find longest junk-free match - // during an iteration of the loop, j2len[j] = length of longest - // junk-free match ending with a[i-1] and b[j] - j2len := map[int]int{} - for i := alo; i != ahi; i++ { - // look at all instances of a[i] in b; note that because - // b2j has no junk keys, the loop is skipped if a[i] is junk - newj2len := map[int]int{} - for _, j := range m.b2j[m.a[i]] { - // a[i] matches b[j] - if j < blo { - continue - } - if j >= bhi { - break - } - k := j2len[j-1] + 1 - newj2len[j] = k - if k > bestsize { - besti, bestj, bestsize = i-k+1, j-k+1, k - } - } - j2len = newj2len - } - - // Extend the best by non-junk elements on each end. In particular, - // "popular" non-junk elements aren't in b2j, which greatly speeds - // the inner loop above, but also means "the best" match so far - // doesn't contain any junk *or* popular non-junk elements. - for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - !m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - // Now that we have a wholly interesting match (albeit possibly - // empty!), we may as well suck up the matching junk on each - // side of it too. Can't think of a good reason not to, and it - // saves post-processing the (possibly considerable) expense of - // figuring out what to do with it. In the case of an empty - // interesting match, this is clearly the right thing to do, - // because no other kind of match is possible in the regions. - for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - return Match{A: besti, B: bestj, Size: bestsize} -} - -// GetMatchingBlocks returns a list of triples describing matching subsequences. -// -// Each triple is of the form (i, j, n), and means that -// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in -// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are -// adjacent triples in the list, and the second is not the last triple in the -// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe -// adjacent equal blocks. -// -// The last triple is a dummy, (len(a), len(b), 0), and is the only -// triple with n==0. -func (m *SequenceMatcher) GetMatchingBlocks() []Match { - if m.matchingBlocks != nil { - return m.matchingBlocks - } - - var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match - matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { - match := m.findLongestMatch(alo, ahi, blo, bhi) - i, j, k := match.A, match.B, match.Size - if match.Size > 0 { - if alo < i && blo < j { - matched = matchBlocks(alo, i, blo, j, matched) - } - matched = append(matched, match) - if i+k < ahi && j+k < bhi { - matched = matchBlocks(i+k, ahi, j+k, bhi, matched) - } - } - return matched - } - matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) - - // It's possible that we have adjacent equal blocks in the - // matching_blocks list now. - nonAdjacent := []Match{} - i1, j1, k1 := 0, 0, 0 - for _, b := range matched { - // Is this block adjacent to i1, j1, k1? - i2, j2, k2 := b.A, b.B, b.Size - if i1+k1 == i2 && j1+k1 == j2 { - // Yes, so collapse them -- this just increases the length of - // the first block by the length of the second, and the first - // block so lengthened remains the block to compare against. - k1 += k2 - } else { - // Not adjacent. Remember the first block (k1==0 means it's - // the dummy we started with), and make the second block the - // new block to compare against. - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - i1, j1, k1 = i2, j2, k2 - } - } - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - - nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) - m.matchingBlocks = nonAdjacent - return m.matchingBlocks -} - -// GetOpCodes returns a list of 5-tuples describing how to turn a into b. -// -// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple -// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the -// tuple preceding it, and likewise for j1 == the previous j2. -// -// The tags are characters, with these meanings: -// -// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] -// -// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. -// -// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. -// -// 'e' (equal): a[i1:i2] == b[j1:j2] -func (m *SequenceMatcher) GetOpCodes() []OpCode { - if m.opCodes != nil { - return m.opCodes - } - i, j := 0, 0 - matching := m.GetMatchingBlocks() - opCodes := make([]OpCode, 0, len(matching)) - for _, m := range matching { - // invariant: we've pumped out correct diffs to change - // a[:i] into b[:j], and the next matching block is - // a[ai:ai+size] == b[bj:bj+size]. So we need to pump - // out a diff to change a[i:ai] into b[j:bj], pump out - // the matching block, and move (i,j) beyond the match - ai, bj, size := m.A, m.B, m.Size - tag := byte(0) - if i < ai && j < bj { - tag = 'r' - } else if i < ai { - tag = 'd' - } else if j < bj { - tag = 'i' - } - if tag > 0 { - opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) - } - i, j = ai+size, bj+size - // the list of matching blocks is terminated by a - // sentinel with size 0 - if size > 0 { - opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) - } - } - m.opCodes = opCodes - return m.opCodes -} - -// GetGroupedOpCodes isolates change clusters by eliminating ranges with no changes. -// -// Return a generator of groups with up to n lines of context. -// Each group is in the same format as returned by GetOpCodes(). -func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { - if n < 0 { - n = 3 - } - codes := m.GetOpCodes() - if len(codes) == 0 { - codes = []OpCode{{'e', 0, 1, 0, 1}} - } - // Fixup leading and trailing groups if they show no changes. - if codes[0].Tag == 'e' { - c := codes[0] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} - } - if codes[len(codes)-1].Tag == 'e' { - c := codes[len(codes)-1] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} - } - nn := n + n - groups := [][]OpCode{} - group := []OpCode{} - for _, c := range codes { - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - // End the current group and start a new one whenever - // there is a large range with no changes. - if c.Tag == 'e' && i2-i1 > nn { - group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), - j1, min(j2, j1+n)}) - groups = append(groups, group) - group = []OpCode{} - i1, j1 = max(i1, i2-n), max(j1, j2-n) - } - group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) - } - if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { - groups = append(groups, group) - } - return groups -} diff --git a/vendor/gotest.tools/v3/internal/format/diff.go b/vendor/gotest.tools/v3/internal/format/diff.go deleted file mode 100644 index 9897d4b9d9e5..000000000000 --- a/vendor/gotest.tools/v3/internal/format/diff.go +++ /dev/null @@ -1,161 +0,0 @@ -package format - -import ( - "bytes" - "fmt" - "strings" - "unicode" - - "gotest.tools/v3/internal/difflib" -) - -const ( - contextLines = 2 -) - -// DiffConfig for a unified diff -type DiffConfig struct { - A string - B string - From string - To string -} - -// UnifiedDiff is a modified version of difflib.WriteUnifiedDiff with better -// support for showing the whitespace differences. -func UnifiedDiff(conf DiffConfig) string { - a := strings.SplitAfter(conf.A, "\n") - b := strings.SplitAfter(conf.B, "\n") - groups := difflib.NewMatcher(a, b).GetGroupedOpCodes(contextLines) - if len(groups) == 0 { - return "" - } - - buf := new(bytes.Buffer) - writeFormat := func(format string, args ...interface{}) { - buf.WriteString(fmt.Sprintf(format, args...)) - } - writeLine := func(prefix string, s string) { - buf.WriteString(prefix + s) - } - if hasWhitespaceDiffLines(groups, a, b) { - writeLine = visibleWhitespaceLine(writeLine) - } - formatHeader(writeFormat, conf) - for _, group := range groups { - formatRangeLine(writeFormat, group) - for _, opCode := range group { - in, out := a[opCode.I1:opCode.I2], b[opCode.J1:opCode.J2] - switch opCode.Tag { - case 'e': - formatLines(writeLine, " ", in) - case 'r': - formatLines(writeLine, "-", in) - formatLines(writeLine, "+", out) - case 'd': - formatLines(writeLine, "-", in) - case 'i': - formatLines(writeLine, "+", out) - } - } - } - return buf.String() -} - -// hasWhitespaceDiffLines returns true if any diff groups is only different -// because of whitespace characters. -func hasWhitespaceDiffLines(groups [][]difflib.OpCode, a, b []string) bool { - for _, group := range groups { - in, out := new(bytes.Buffer), new(bytes.Buffer) - for _, opCode := range group { - if opCode.Tag == 'e' { - continue - } - for _, line := range a[opCode.I1:opCode.I2] { - in.WriteString(line) - } - for _, line := range b[opCode.J1:opCode.J2] { - out.WriteString(line) - } - } - if removeWhitespace(in.String()) == removeWhitespace(out.String()) { - return true - } - } - return false -} - -func removeWhitespace(s string) string { - var result []rune - for _, r := range s { - if !unicode.IsSpace(r) { - result = append(result, r) - } - } - return string(result) -} - -func visibleWhitespaceLine(ws func(string, string)) func(string, string) { - mapToVisibleSpace := func(r rune) rune { - switch r { - case '\n': - case ' ': - return '·' - case '\t': - return '▷' - case '\v': - return '▽' - case '\r': - return '↵' - case '\f': - return '↓' - default: - if unicode.IsSpace(r) { - return '�' - } - } - return r - } - return func(prefix, s string) { - ws(prefix, strings.Map(mapToVisibleSpace, s)) - } -} - -func formatHeader(wf func(string, ...interface{}), conf DiffConfig) { - if conf.From != "" || conf.To != "" { - wf("--- %s\n", conf.From) - wf("+++ %s\n", conf.To) - } -} - -func formatRangeLine(wf func(string, ...interface{}), group []difflib.OpCode) { - first, last := group[0], group[len(group)-1] - range1 := formatRangeUnified(first.I1, last.I2) - range2 := formatRangeUnified(first.J1, last.J2) - wf("@@ -%s +%s @@\n", range1, range2) -} - -// Convert range to the "ed" format -func formatRangeUnified(start, stop int) string { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning := start + 1 // lines start numbering with one - length := stop - start - if length == 1 { - return fmt.Sprintf("%d", beginning) - } - if length == 0 { - beginning-- // empty ranges begin at line just before the range - } - return fmt.Sprintf("%d,%d", beginning, length) -} - -func formatLines(writeLine func(string, string), prefix string, lines []string) { - for _, line := range lines { - writeLine(prefix, line) - } - // Add a newline if the last line is missing one so that the diff displays - // properly. - if !strings.HasSuffix(lines[len(lines)-1], "\n") { - writeLine("", "\n") - } -} diff --git a/vendor/gotest.tools/v3/internal/format/format.go b/vendor/gotest.tools/v3/internal/format/format.go deleted file mode 100644 index 5097e4bd6eb5..000000000000 --- a/vendor/gotest.tools/v3/internal/format/format.go +++ /dev/null @@ -1,27 +0,0 @@ -package format // import "gotest.tools/v3/internal/format" - -import "fmt" - -// Message accepts a msgAndArgs varargs and formats it using fmt.Sprintf -func Message(msgAndArgs ...interface{}) string { - switch len(msgAndArgs) { - case 0: - return "" - case 1: - return fmt.Sprintf("%v", msgAndArgs[0]) - default: - return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) - } -} - -// WithCustomMessage accepts one or two messages and formats them appropriately -func WithCustomMessage(source string, msgAndArgs ...interface{}) string { - custom := Message(msgAndArgs...) - switch { - case custom == "": - return source - case source == "": - return custom - } - return fmt.Sprintf("%s: %s", source, custom) -} diff --git a/vendor/gotest.tools/v3/internal/source/defers.go b/vendor/gotest.tools/v3/internal/source/defers.go deleted file mode 100644 index 66cfafbb648a..000000000000 --- a/vendor/gotest.tools/v3/internal/source/defers.go +++ /dev/null @@ -1,53 +0,0 @@ -package source - -import ( - "go/ast" - "go/token" - - "github.com/pkg/errors" -) - -func scanToDeferLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { - var matchedNode ast.Node - ast.Inspect(node, func(node ast.Node) bool { - switch { - case node == nil || matchedNode != nil: - return false - case fileset.Position(node.End()).Line == lineNum: - if funcLit, ok := node.(*ast.FuncLit); ok { - matchedNode = funcLit - return false - } - } - return true - }) - debug("defer line node: %s", debugFormatNode{matchedNode}) - return matchedNode -} - -func guessDefer(node ast.Node) (ast.Node, error) { - defers := collectDefers(node) - switch len(defers) { - case 0: - return nil, errors.New("failed to expression in defer") - case 1: - return defers[0].Call, nil - default: - return nil, errors.Errorf( - "ambiguous call expression: multiple (%d) defers in call block", - len(defers)) - } -} - -func collectDefers(node ast.Node) []*ast.DeferStmt { - var defers []*ast.DeferStmt - ast.Inspect(node, func(node ast.Node) bool { - if d, ok := node.(*ast.DeferStmt); ok { - defers = append(defers, d) - debug("defer: %s", debugFormatNode{d}) - return false - } - return true - }) - return defers -} diff --git a/vendor/gotest.tools/v3/internal/source/source.go b/vendor/gotest.tools/v3/internal/source/source.go deleted file mode 100644 index c2eef0337375..000000000000 --- a/vendor/gotest.tools/v3/internal/source/source.go +++ /dev/null @@ -1,181 +0,0 @@ -package source // import "gotest.tools/v3/internal/source" - -import ( - "bytes" - "fmt" - "go/ast" - "go/format" - "go/parser" - "go/token" - "os" - "runtime" - "strconv" - "strings" - - "github.com/pkg/errors" -) - -const baseStackIndex = 1 - -// FormattedCallExprArg returns the argument from an ast.CallExpr at the -// index in the call stack. The argument is formatted using FormatNode. -func FormattedCallExprArg(stackIndex int, argPos int) (string, error) { - args, err := CallExprArgs(stackIndex + 1) - if err != nil { - return "", err - } - if argPos >= len(args) { - return "", errors.New("failed to find expression") - } - return FormatNode(args[argPos]) -} - -// CallExprArgs returns the ast.Expr slice for the args of an ast.CallExpr at -// the index in the call stack. -func CallExprArgs(stackIndex int) ([]ast.Expr, error) { - _, filename, lineNum, ok := runtime.Caller(baseStackIndex + stackIndex) - if !ok { - return nil, errors.New("failed to get call stack") - } - debug("call stack position: %s:%d", filename, lineNum) - - node, err := getNodeAtLine(filename, lineNum) - if err != nil { - return nil, err - } - debug("found node: %s", debugFormatNode{node}) - - return getCallExprArgs(node) -} - -func getNodeAtLine(filename string, lineNum int) (ast.Node, error) { - fileset := token.NewFileSet() - astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse source file: %s", filename) - } - - if node := scanToLine(fileset, astFile, lineNum); node != nil { - return node, nil - } - if node := scanToDeferLine(fileset, astFile, lineNum); node != nil { - node, err := guessDefer(node) - if err != nil || node != nil { - return node, err - } - } - return nil, errors.Errorf( - "failed to find an expression on line %d in %s", lineNum, filename) -} - -func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { - var matchedNode ast.Node - ast.Inspect(node, func(node ast.Node) bool { - switch { - case node == nil || matchedNode != nil: - return false - case nodePosition(fileset, node).Line == lineNum: - matchedNode = node - return false - } - return true - }) - return matchedNode -} - -// In golang 1.9 the line number changed from being the line where the statement -// ended to the line where the statement began. -func nodePosition(fileset *token.FileSet, node ast.Node) token.Position { - if goVersionBefore19 { - return fileset.Position(node.End()) - } - return fileset.Position(node.Pos()) -} - -// GoVersionLessThan returns true if runtime.Version() is semantically less than -// version major.minor. Returns false if a release version can not be parsed from -// runtime.Version(). -func GoVersionLessThan(major, minor int64) bool { - version := runtime.Version() - // not a release version - if !strings.HasPrefix(version, "go") { - return false - } - version = strings.TrimPrefix(version, "go") - parts := strings.Split(version, ".") - if len(parts) < 2 { - return false - } - rMajor, err := strconv.ParseInt(parts[0], 10, 32) - if err != nil { - return false - } - if rMajor != major { - return rMajor < major - } - rMinor, err := strconv.ParseInt(parts[1], 10, 32) - if err != nil { - return false - } - return rMinor < minor -} - -var goVersionBefore19 = GoVersionLessThan(1, 9) - -func getCallExprArgs(node ast.Node) ([]ast.Expr, error) { - visitor := &callExprVisitor{} - ast.Walk(visitor, node) - if visitor.expr == nil { - return nil, errors.New("failed to find call expression") - } - debug("callExpr: %s", debugFormatNode{visitor.expr}) - return visitor.expr.Args, nil -} - -type callExprVisitor struct { - expr *ast.CallExpr -} - -func (v *callExprVisitor) Visit(node ast.Node) ast.Visitor { - if v.expr != nil || node == nil { - return nil - } - debug("visit: %s", debugFormatNode{node}) - - switch typed := node.(type) { - case *ast.CallExpr: - v.expr = typed - return nil - case *ast.DeferStmt: - ast.Walk(v, typed.Call.Fun) - return nil - } - return v -} - -// FormatNode using go/format.Node and return the result as a string -func FormatNode(node ast.Node) (string, error) { - buf := new(bytes.Buffer) - err := format.Node(buf, token.NewFileSet(), node) - return buf.String(), err -} - -var debugEnabled = os.Getenv("GOTESTTOOLS_DEBUG") != "" - -func debug(format string, args ...interface{}) { - if debugEnabled { - fmt.Fprintf(os.Stderr, "DEBUG: "+format+"\n", args...) - } -} - -type debugFormatNode struct { - ast.Node -} - -func (n debugFormatNode) String() string { - out, err := FormatNode(n.Node) - if err != nil { - return fmt.Sprintf("failed to format %s: %s", n.Node, err) - } - return fmt.Sprintf("(%T) %s", n.Node, out) -} diff --git a/vendor/gotest.tools/v3/poll/check.go b/vendor/gotest.tools/v3/poll/check.go deleted file mode 100644 index 060b0998906b..000000000000 --- a/vendor/gotest.tools/v3/poll/check.go +++ /dev/null @@ -1,39 +0,0 @@ -package poll - -import ( - "net" - "os" -) - -// Check is a function which will be used as check for the WaitOn method. -type Check func(t LogT) Result - -// FileExists looks on filesystem and check that path exists. -func FileExists(path string) Check { - return func(t LogT) Result { - _, err := os.Stat(path) - if os.IsNotExist(err) { - t.Logf("waiting on file %s to exist", path) - return Continue("file %s does not exist", path) - } - if err != nil { - return Error(err) - } - - return Success() - } -} - -// Connection try to open a connection to the address on the -// named network. See net.Dial for a description of the network and -// address parameters. -func Connection(network, address string) Check { - return func(t LogT) Result { - _, err := net.Dial(network, address) - if err != nil { - t.Logf("waiting on socket %s://%s to be available...", network, address) - return Continue("socket %s://%s not available", network, address) - } - return Success() - } -} diff --git a/vendor/gotest.tools/v3/poll/poll.go b/vendor/gotest.tools/v3/poll/poll.go deleted file mode 100644 index 29c5b40e187f..000000000000 --- a/vendor/gotest.tools/v3/poll/poll.go +++ /dev/null @@ -1,171 +0,0 @@ -/*Package poll provides tools for testing asynchronous code. - */ -package poll // import "gotest.tools/v3/poll" - -import ( - "fmt" - "strings" - "time" - - "gotest.tools/v3/assert/cmp" - "gotest.tools/v3/internal/assert" -) - -// TestingT is the subset of testing.T used by WaitOn -type TestingT interface { - LogT - Fatalf(format string, args ...interface{}) -} - -// LogT is a logging interface that is passed to the WaitOn check function -type LogT interface { - Log(args ...interface{}) - Logf(format string, args ...interface{}) -} - -type helperT interface { - Helper() -} - -// Settings are used to configure the behaviour of WaitOn -type Settings struct { - // Timeout is the maximum time to wait for the condition. Defaults to 10s. - Timeout time.Duration - // Delay is the time to sleep between checking the condition. Defaults to - // 100ms. - Delay time.Duration -} - -func defaultConfig() *Settings { - return &Settings{Timeout: 10 * time.Second, Delay: 100 * time.Millisecond} -} - -// SettingOp is a function which accepts and modifies Settings -type SettingOp func(config *Settings) - -// WithDelay sets the delay to wait between polls -func WithDelay(delay time.Duration) SettingOp { - return func(config *Settings) { - config.Delay = delay - } -} - -// WithTimeout sets the timeout -func WithTimeout(timeout time.Duration) SettingOp { - return func(config *Settings) { - config.Timeout = timeout - } -} - -// Result of a check performed by WaitOn -type Result interface { - // Error indicates that the check failed and polling should stop, and the - // the has failed - Error() error - // Done indicates that polling should stop, and the test should proceed - Done() bool - // Message provides the most recent state when polling has not completed - Message() string -} - -type result struct { - done bool - message string - err error -} - -func (r result) Done() bool { - return r.done -} - -func (r result) Message() string { - return r.message -} - -func (r result) Error() error { - return r.err -} - -// Continue returns a Result that indicates to WaitOn that it should continue -// polling. The message text will be used as the failure message if the timeout -// is reached. -func Continue(message string, args ...interface{}) Result { - return result{message: fmt.Sprintf(message, args...)} -} - -// Success returns a Result where Done() returns true, which indicates to WaitOn -// that it should stop polling and exit without an error. -func Success() Result { - return result{done: true} -} - -// Error returns a Result that indicates to WaitOn that it should fail the test -// and stop polling. -func Error(err error) Result { - return result{err: err} -} - -// WaitOn a condition or until a timeout. Poll by calling check and exit when -// check returns a done Result. To fail a test and exit polling with an error -// return a error result. -func WaitOn(t TestingT, check Check, pollOps ...SettingOp) { - if ht, ok := t.(helperT); ok { - ht.Helper() - } - config := defaultConfig() - for _, pollOp := range pollOps { - pollOp(config) - } - - var lastMessage string - after := time.After(config.Timeout) - chResult := make(chan Result) - for { - go func() { - chResult <- check(t) - }() - select { - case <-after: - if lastMessage == "" { - lastMessage = "first check never completed" - } - t.Fatalf("timeout hit after %s: %s", config.Timeout, lastMessage) - case result := <-chResult: - switch { - case result.Error() != nil: - t.Fatalf("polling check failed: %s", result.Error()) - case result.Done(): - return - } - time.Sleep(config.Delay) - lastMessage = result.Message() - } - } -} - -// Compare values using the cmp.Comparison. If the comparison fails return a -// result which indicates to WaitOn that it should continue waiting. -// If the comparison is successful then WaitOn stops polling. -func Compare(compare cmp.Comparison) Result { - buf := new(logBuffer) - if assert.RunComparison(buf, assert.ArgsAtZeroIndex, compare) { - return Success() - } - return Continue(buf.String()) -} - -type logBuffer struct { - log [][]interface{} -} - -func (c *logBuffer) Log(args ...interface{}) { - c.log = append(c.log, args) -} - -func (c *logBuffer) String() string { - b := new(strings.Builder) - for _, item := range c.log { - b.WriteString(fmt.Sprint(item...) + " ") - } - return b.String() -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2df8f1e21e93..0a9bf399ffd9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,7 +1,3 @@ -# github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 -## explicit; go 1.16 -github.com/Azure/go-ansiterm -github.com/Azure/go-ansiterm/winterm # github.com/Microsoft/go-winio v0.5.1 ## explicit; go 1.12 github.com/Microsoft/go-winio @@ -249,17 +245,11 @@ github.com/docker/docker/pkg/fileutils github.com/docker/docker/pkg/homedir github.com/docker/docker/pkg/idtools github.com/docker/docker/pkg/ioutils -github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/pkg/longpath github.com/docker/docker/pkg/pools github.com/docker/docker/pkg/reexec -github.com/docker/docker/pkg/stringid github.com/docker/docker/pkg/system github.com/docker/docker/profiles/seccomp -github.com/docker/docker/testutil/daemon -github.com/docker/docker/testutil/environment -github.com/docker/docker/testutil/fixtures/load -github.com/docker/docker/testutil/request # github.com/docker/docker-credential-helpers v0.6.4 ## explicit; go 1.13 github.com/docker/docker-credential-helpers/client @@ -395,8 +385,6 @@ github.com/moby/sys/mountinfo github.com/moby/sys/signal # github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 ## explicit; go 1.13 -github.com/moby/term -github.com/moby/term/windows # github.com/morikuni/aec v1.0.0 ## explicit github.com/morikuni/aec @@ -711,13 +699,4 @@ google.golang.org/protobuf/types/known/wrapperspb # gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ## explicit gopkg.in/yaml.v3 -# gotest.tools/v3 v3.0.3 -## explicit; go 1.11 -gotest.tools/v3/assert -gotest.tools/v3/assert/cmp -gotest.tools/v3/internal/assert -gotest.tools/v3/internal/difflib -gotest.tools/v3/internal/format -gotest.tools/v3/internal/source -gotest.tools/v3/poll # github.com/docker/docker => github.com/docker/docker v20.10.3-0.20220224222438-c78f6963a1c0+incompatible