diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 000000000..ae9ef001a --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,6 @@ +[allowlist] + description = "Project allowlist" + + paths = [ + '''benchmark\/internal\/registry\/fake_quay.key$''', + ] diff --git a/Makefile b/Makefile index 0f4122def..cfc85f52a 100644 --- a/Makefile +++ b/Makefile @@ -144,6 +144,13 @@ feature_%: ## Run acceptance tests for a single feature file, e.g. make feature_ scenario_%: build ## Run acceptance tests for a single scenario, e.g. make scenario_inline_policy @cd acceptance && go test -test.run 'TestFeatures/$*' +benchmark_%: + @cd benchmark/$* + @go run . + +.PHONY: benchmark +benchmark: benchmark_simple ## Run benchmarks + .PHONY: ci ci: test lint-fix acceptance ## Run the usual required CI tasks diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 000000000..db98e7874 --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,12 @@ +# Benchmarks of ec CLI + +Benchmarks within this directory use the [golang +benchmarking](golang.org/x/benchmarks/) package and output in the [standard +benchmark +format](https://go.googlesource.com/proposal/+/master/design/14313-benchmark-format.md). + +Each benchmark is built as a standalone executable with no external dependency +other than any data that is contained within it. Benchmarks are run from within +the directory they're defined in, simply by running `go run .`, additional +arguments can be passed in, for example `-benchnum 10` to run the benchmark 10 +times. diff --git a/benchmark/internal/registry/fake_quay.cer b/benchmark/internal/registry/fake_quay.cer new file mode 100644 index 000000000..31b65f6cf --- /dev/null +++ b/benchmark/internal/registry/fake_quay.cer @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOjCCAiKgAwIBAgIUOc/vG5o8pNnIBCIYsrYJ01jkmfEwDQYJKoZIhvcNAQEL +BQAwFzEVMBMGA1UEAwwMYmVuY2htYXJrLmVjMB4XDTI0MTIwOTE1MzIyMVoXDTM0 +MTIwNzE1MzIyMVowFzEVMBMGA1UEAwwMYmVuY2htYXJrLmVjMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnVIvUGHA2XFScaRcN8vxNiuDShN4SNuCWcdC +cbzvCbA7yu4v2LJBqsbDIs5zWcr9kb15vg0Cg3dCHztnsJCmFIwp6lKc3l60eD4+ +Qke2YnD3cUB/P4A7jMUC2kEjjlqdnoLw6IIwt7D6JZeaZhDpPfGyf3llxoVdT5+J +dfBtn6U4WnYqqTg7vccoe0RTXkotLAUMyshd00QaGKIOZ5HdzDBXHUVszTU+Vidf +9xyxndDVlxnE70zWv/jeZLhgnkxMRzoi0q2hq25TeugQ+yrGKVD4UBB6CaGWgAIN +Sw0iTFmYd+0uBVpTYF8KLO2jc/bNqFGJn2t/+P88XqfHTCZVfwIDAQABo34wfDA5 +BgNVHREEMjAwggdxdWF5LmlvghpyZWdpc3RyeS5hY2Nlc3MucmVkaGF0LmNvbYIJ +bG9jYWxob3N0MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNV +HQ4EFgQUP3lNVxeEEpMjoKQ2wPk6hhLsXOwwDQYJKoZIhvcNAQELBQADggEBAFKp +MpYwkR5vb73JsRATYr6H/A5bRAjVg+NoMklOJ5lu5PtwomD0rlD8OIJeXuT57Bsy +PAukG7gXlHk0zJ3cExxsys+jscsGKi2+gKEWvOYj06Z5xug7GPZyoA9r6MOKclZJ +VXCxpQfkl5pGDQiIhtpvuADt8oBogx4mwDhP16WBz/5BkKIpsLn7jGZOUYaSrjG3 +OLf5AArhHzs0rRRcaCjbybuah8nQMMqG7Q6bz7jF4szCeIL7ndWro2U5kgVVMrXS +5zbEklvW5OXFO/UREiY+5YBAu6gCr0APFLAQi5qfAhKpbQkjZ28unuB/3aQlT0kR +wHo3oDNZDNaIwBoP/54= +-----END CERTIFICATE----- diff --git a/benchmark/internal/registry/fake_quay.key b/benchmark/internal/registry/fake_quay.key new file mode 100644 index 000000000..f72c8e78e --- /dev/null +++ b/benchmark/internal/registry/fake_quay.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdUi9QYcDZcVJx +pFw3y/E2K4NKE3hI24JZx0JxvO8JsDvK7i/YskGqxsMiznNZyv2RvXm+DQKDd0If +O2ewkKYUjCnqUpzeXrR4Pj5CR7ZicPdxQH8/gDuMxQLaQSOOWp2egvDogjC3sPol +l5pmEOk98bJ/eWXGhV1Pn4l18G2fpThadiqpODu9xyh7RFNeSi0sBQzKyF3TRBoY +og5nkd3MMFcdRWzNNT5WJ1/3HLGd0NWXGcTvTNa/+N5kuGCeTExHOiLSraGrblN6 +6BD7KsYpUPhQEHoJoZaAAg1LDSJMWZh37S4FWlNgXwos7aNz9s2oUYmfa3/4/zxe +p8dMJlV/AgMBAAECggEASM1Xh+M002tVs7FT255NKbxJLWaFK3IpiFJltSyxkdI0 +WVyQV79mFBmXA+x2BP+jCGaeiAyNNTljKADdox/NO4UBgKZqYZ2B9oMXXKTDChss +5wPp3wEAjcw93bJ3OdFFT61YvsBAu0DzAaJ+mO0Kgtfuun77Ujs1SzuQ6Tsx/8ZD +STr8q7DcMAd6afHFFk5NZDqyFPgzmEMUWRFy7BH/vLLEgdRi7I7UbTYhjpP7uyjF +/0HLSjBQJr58554CyL11OcVOwqktKZYKMVsCNWg6l4uhYxg0ChyJgO+PuUhPqh1i +eIybcaDUVQ0LG/gBYzDlnw8yNXPO4+HX+MdIXafBAQKBgQDZx6m2rsI3L4M0ow89 +T6L8jMrFF6bUp2PBVPOYvobk4de3x7ma4WwK212l869A2u536+8BlBaiZN0yRSmI +XXX0oL8JfqTO7d5efa9zHdkEN+t7iwVFWsYe74jjVR/oOyW7ZJ07gP/kZudbm8uk +DnGzEGsjTYo7K6dEcEiXXmZiDwKBgQC47j8iR7v6a0E7EzEcM6FIpAV8tlpj0wUt +pXKHPRdMQaOi39YyNWCGGake7bRCGz2ni1zqSVqVIcm6yvzlS/o3lLMTUYlUxtqt +0cGrTJXkyhwkyoAJg0vwU43BJkbUNsX0y5revv/T4TaVTYK4dv2RTv8Jbdp6sT7i +B6I7tFmFkQKBgQDQShe24rRchbPOrzoPINC5DYuOMA3fC+3r5e1KJMftt1dTrdGG +IZ3tUFvkMgpnVD2KMvyYHOP9E80/nEiZ5RHBE9FDKn5Eb9sjssAQsPZ0A2vU8GTt +LWGaCu14yFzJB3ESJqv/UmTsNcOHqZ1+XlY+tjBSRoI0D49edKnpJF913wKBgQCn +WSHUuamIIYr0FJf6d1ZaT+OPSc1eTFWBSxjq/QOaREP6XiiNYvQoJgx/KohW0iPm +/Bxm/15zWhIdcReNwEV8CppKvxxRlWnKpehmRXXXhnYVbRKUiTYtEs9SnHq4C6Dz +t1Q8ggcsC7/DOFM07qjj1+K++6QcJ01KabIL6VahoQKBgGNCgw4+0291OA8nwjXl +HNu9WBzJVHsAL9RDvrL6c4wcUWmhJTUcKN/TnndYN5SdvrOzZ2RjysS8KZoLnHgI +c41uBNLvGtE9RPuzFe7U3zt9t80d4gcjy92tBru6xszPIgmKsUe8Hrl2EWbJvCET +/BbfoyzzqH3f+vYm25GFSIy5 +-----END PRIVATE KEY----- diff --git a/benchmark/internal/registry/registry.go b/benchmark/internal/registry/registry.go new file mode 100644 index 000000000..c18861392 --- /dev/null +++ b/benchmark/internal/registry/registry.go @@ -0,0 +1,169 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +//type Closer func() +// SPDX-License-Identifier: Apache-2.0 + +package registry + +import ( + "context" + "crypto/tls" + "crypto/x509" + _ "embed" + "fmt" + "log" + "net" + "net/http" + "net/http/httptest" + "net/url" + "os" + "path" + "time" + + "github.com/docker/docker/api/types/container" + "github.com/smarty/cproxy/v2" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/registry" + "github.com/testcontainers/testcontainers-go/wait" + + "github.com/enterprise-contract/ec-cli/benchmark/internal/suite" +) + +//go:embed fake_quay.cer +var certificate []byte + +//go:embed fake_quay.key +var key []byte + +type registryCloser struct { + tempDir string + container *registry.RegistryContainer + proxy *httptest.Server +} + +func (r *registryCloser) Close() { + if r == nil { + return + } + + if r.tempDir != "" { + _ = os.RemoveAll(r.tempDir) + } + + if r.container != nil { + _ = r.container.Terminate(context.Background()) + } + + if r.proxy != nil { + r.proxy.Close() + } +} + +type registryProxy struct { + registry string +} + +func (f *registryProxy) IsAuthorized(_ http.ResponseWriter, req *http.Request) bool { + req.RequestURI = fmt.Sprintf("https://%s/", f.registry) + req.URL, _ = url.Parse(req.RequestURI) + req.Host = f.registry + + return true +} + +func Launch(data string) (suite.Closer, error) { + ctx := context.Background() + + env := testcontainers.WithEnv(map[string]string{ + "REGISTRY_HTTP_TLS_CERTIFICATE": "/tls/fake_quay.cer", + "REGISTRY_HTTP_TLS_KEY": "/tls/fake_quay.key", + }) + + dir, err := os.MkdirTemp("", "ec-benchmark-tls-*") + if err != nil { + return nil, err + } + closer := ®istryCloser{dir, nil, nil} + + if err := os.Setenv("https_proxy", "http://localhost:3128"); err != nil { + return nil, err + } + + if err := os.Chmod(dir, 0755); err != nil { + return closer.Close, err + } + + certPath := path.Join(dir, "fake_quay.cer") + if err := os.WriteFile(certPath, certificate, 0600); err != nil { + return closer.Close, err + } + + if err := os.Setenv("SSL_CERT_FILE", certPath); err != nil { + return closer.Close, err + } + + if err := os.WriteFile(path.Join(dir, "fake_quay.key"), key, 0600); err != nil { + return closer.Close, err + } + + rp := registryProxy{} + proxy := cproxy.New(cproxy.Options.Filter(&rp), cproxy.Options.Logger(log.Default())) + proxyServer := httptest.NewUnstartedServer(proxy) + proxyServer.Listener, err = net.Listen("tcp", "127.0.0.1:3128") + if err != nil { + return closer.Close, err + } + proxyServer.Config.ErrorLog = log.Default() + proxyServer.Start() + closer.proxy = proxyServer + + tlsMount := testcontainers.WithHostConfigModifier(func(hostConfig *container.HostConfig) { + hostConfig.Binds = append(hostConfig.Binds, fmt.Sprintf("%s:/tls:ro,Z", dir)) + }) + + roots := x509.NewCertPool() + roots.AppendCertsFromPEM(certificate) + waitStrategy := testcontainers.WithWaitStrategy(wait.ForHTTP("/"). + WithPort("5000/tcp"). + WithTLS(true, &tls.Config{ + RootCAs: roots, + MinVersion: tls.VersionTLS13, + }). + WithStartupTimeout(10 * time.Second)) + + opts := []testcontainers.ContainerCustomizer{ + registry.WithData(data), + env, + tlsMount, + waitStrategy, + } + + if false { + opts = append(opts, + testcontainers.WithConfigModifier(func(config *container.Config) { + config.AttachStdout = true + }), + testcontainers.WithLogger(log.Default())) + } + + r, err := registry.Run(ctx, "registry:2.8.3", opts...) + if err != nil { + return closer.Close, err + } + closer.container = r + + rp.registry = r.RegistryName + + return closer.Close, nil +} diff --git a/benchmark/internal/suite/closer.go b/benchmark/internal/suite/closer.go new file mode 100644 index 000000000..15101c10f --- /dev/null +++ b/benchmark/internal/suite/closer.go @@ -0,0 +1,19 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package suite + +type Closer func() diff --git a/benchmark/internal/suite/suite.go b/benchmark/internal/suite/suite.go new file mode 100644 index 000000000..789e2fb13 --- /dev/null +++ b/benchmark/internal/suite/suite.go @@ -0,0 +1,32 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package suite + +import ( + "io" + + "github.com/enterprise-contract/ec-cli/cmd" + "github.com/enterprise-contract/ec-cli/cmd/root" +) + +func Execute(args []string) error { + c := root.NewRootCmd() + cmd.AddCommandsTo(c) + c.SetArgs(args) + c.SetOutput(io.Discard) + return c.Execute() +} diff --git a/benchmark/internal/untar/untar.go b/benchmark/internal/untar/untar.go new file mode 100644 index 000000000..5f875b50a --- /dev/null +++ b/benchmark/internal/untar/untar.go @@ -0,0 +1,91 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package untar + +import ( + "compress/gzip" + "errors" + "fmt" + "io" + "io/fs" + "math" + "os" + "path" + + "github.com/google/safearchive/tar" +) + +func UnTar(a string) (string, error) { + dir, err := os.MkdirTemp("", "ec-benchmark") + if err != nil { + return "", err + } + + archive, err := os.Open(a) + if err != nil { + return "", err + } + defer archive.Close() + + gz, err := gzip.NewReader(archive) + if err != nil { + return "", err + } + defer gz.Close() + + t := tar.NewReader(gz) + for { + hdr, err := t.Next() + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return "", err + } + + dst := path.Join(dir, path.Clean(hdr.Name)) + if hdr.Mode < 0 || hdr.Mode > math.MaxUint32 { + panic(fmt.Sprintf("weird tar header mode: %d", hdr.Mode)) + } + mode := fs.FileMode(hdr.Mode) + + switch hdr.Typeflag { + case tar.TypeDir: + err = os.MkdirAll(dst, mode) + case tar.TypeLink: + err = os.Symlink(path.Join(dir, path.Clean(hdr.Linkname)), dst) + case tar.TypeReg: + var f io.WriteCloser + f, err = os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, mode) + if err != nil { + break + } + + _, err = io.Copy(f, t) + if err != nil && !errors.Is(err, io.EOF) { + break + } + err = f.Close() + } + + if err != nil { + return "", err + } + } + + return dir, nil +} diff --git a/benchmark/offliner/README.md b/benchmark/offliner/README.md new file mode 100644 index 000000000..0b24bbb2d --- /dev/null +++ b/benchmark/offliner/README.md @@ -0,0 +1,8 @@ +# Offliner + +A tool to offline, i.e. place all data for an container image in a remote +registry to a local data directory. This local data directory can be mounted to +docker.io/registry container registry so running against it eliminates remote +network access. + +Use: `offliner ` diff --git a/benchmark/offliner/base_images.go b/benchmark/offliner/base_images.go new file mode 100644 index 000000000..d64d09646 --- /dev/null +++ b/benchmark/offliner/base_images.go @@ -0,0 +1,133 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "encoding/json" + "strconv" + + "github.com/CycloneDX/cyclonedx-go" + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/spdx/tools-golang/spdx" +) + +func baseImages(ref name.Reference) ([]name.Reference, error) { + sbomRef := digestTag(ref, "sbom") + + img, err := remote.Image(sbomRef) + if err != nil { + return nil, err + } + + refs := make([]name.Reference, 0, 5) + layers, err := img.Layers() + if err != nil { + return nil, err + } + + fromCycloneDX := func(layer v1.Layer) ([]name.Reference, error) { + var refs = make([]name.Reference, 0, 5) + + data, err := layer.Uncompressed() + if err != nil { + return nil, err + } + defer data.Close() + + decoder := cyclonedx.NewBOMDecoder(data, cyclonedx.BOMFileFormatJSON) + + var bom cyclonedx.BOM + if err := decoder.Decode(&bom); err != nil { + return nil, err + } + + isNumber := func(s string) bool { + _, err := strconv.ParseUint(s, 10, 64) + return err == nil + } + + for _, formulation := range nab(bom.Formulation) { + for _, component := range nab(formulation.Components) { + if component.Type != cyclonedx.ComponentTypeContainer { + continue + } + + for _, property := range nab(component.Properties) { + isBase := property.Name == "konflux:container:is_base_image" && property.Value == "true" + isStage := property.Name == "konflux:container:is_builder_image:for_stage" && isNumber(property.Value) + if !isBase && !isStage { + continue + } + + if r, err := name.ParseReference(component.Name); err == nil { + refs = append(refs, r) + } + } + } + } + + return refs, nil + } + + fromSPDX := func(layer v1.Layer) ([]name.Reference, error) { + var refs = make([]name.Reference, 0, 5) + + data, err := layer.Uncompressed() + if err != nil { + return nil, err + } + defer data.Close() + + decoder := json.NewDecoder(data) + + var bom spdx.Document + if err := decoder.Decode(&bom); err != nil { + return nil, err + } + + // TODO missing the rest of the implementation here, lacking SPDX + // examples currently. Missing parsing and extracting base images from + // SPDX, similarly to how it is done for CycloneDX + + return refs, nil + } + + for _, layer := range layers { + mt, err := layer.MediaType() + if err != nil { + return nil, err + } + + var fetch func(v1.Layer) ([]name.Reference, error) = func(l v1.Layer) ([]name.Reference, error) { return nil, nil } + switch mt { + case "application/vnd.cyclonedx+json": + fetch = fromCycloneDX + case "text/spdx+json": + fetch = fromSPDX + } + + if more, err := fetch(layer); err != nil { + return nil, err + } else { + refs = append(refs, more...) + } + } + + return refs, nil +} diff --git a/benchmark/offliner/nab.go b/benchmark/offliner/nab.go new file mode 100644 index 000000000..947f71d37 --- /dev/null +++ b/benchmark/offliner/nab.go @@ -0,0 +1,25 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +func nab[T any](v *[]T) []T { + if v == nil { + return nil + } + + return *v +} diff --git a/benchmark/offliner/offliner.go b/benchmark/offliner/offliner.go new file mode 100644 index 000000000..6a129cc07 --- /dev/null +++ b/benchmark/offliner/offliner.go @@ -0,0 +1,139 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "fmt" + "log" + "os" + "path/filepath" + + "github.com/docker/docker/api/types/container" + "github.com/google/go-containerregistry/pkg/crane" + "github.com/google/go-containerregistry/pkg/logs" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/registry" +) + +func items(sourceImages []name.Reference, destination name.Registry) map[string]string { + items := map[string]string{} + for _, sourceImage := range sourceImages { + var dest fmt.Stringer = destination.Repo(sourceImage.Context().RepositoryStr()) + if d, ok := sourceImage.(name.Digest); ok { + dest = dest.(name.Repository).Digest(d.DigestStr()) + } + if t, ok := sourceImage.(name.Tag); ok { + dest = dest.(name.Repository).Tag(t.TagStr()) + } + + items[sourceImage.String()] = dest.String() + } + + return items +} + +func main() { + if len(os.Args) != 3 { + fmt.Fprintf(os.Stderr, "Usage: %s \n", os.Args[0]) + os.Exit(1) + } + + sourceImage := os.Args[1] + dir, err := filepath.Abs(os.Args[2]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + if _, err := os.Stat(dir); os.IsNotExist(err) { + if err := os.MkdirAll(dir, 0755); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(3) + } + } + + source, err := name.ParseReference(sourceImage) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(4) + } + + _, ok := source.(name.Digest) + if !ok { + fmt.Fprintln(os.Stderr, "use pinned image references") + os.Exit(5) + } + + ctx := context.Background() + registry, err := registry.Run(ctx, + registry.DefaultImage, + testcontainers.WithConfigModifier(func(config *container.Config) { + config.User = fmt.Sprintf("%d:%d", os.Getuid(), os.Getgid()) + }), + testcontainers.WithHostConfigModifier(func(hostConfig *container.HostConfig) { + hostConfig.UsernsMode = "host" + hostConfig.Binds = append(hostConfig.Binds, fmt.Sprintf("%s:/var/lib/registry:z", dir)) + }), + ) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(6) + } + defer func() { _ = registry.Terminate(ctx) }() + + destination, err := name.NewRegistry(registry.RegistryName, name.Insecure) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(7) + } + logs.Progress = log.New(os.Stdout, "", log.LstdFlags) + + relatedImages, err := related(source) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(8) + } + + idx, err := remote.Index(source) + if err == nil { + idxManifest, err := idx.IndexManifest() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(8) + } + + for _, m := range idxManifest.Manifests { + img := source.Context().Digest(m.Digest.String()) + rel, err := related(img) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(9) + } + relatedImages = append(relatedImages, rel...) + } + } + + for s, d := range items(relatedImages, destination) { + if err := crane.Copy(s, d); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(10) + } + } +} diff --git a/benchmark/offliner/offliner_test.go b/benchmark/offliner/offliner_test.go new file mode 100644 index 000000000..c1e777ba2 --- /dev/null +++ b/benchmark/offliner/offliner_test.go @@ -0,0 +1,49 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "maps" + "testing" + + "github.com/google/go-containerregistry/pkg/name" +) + +func TestItems(t *testing.T) { + dest, err := name.NewRegistry("newregistry.io") + if err != nil { + t.Fatal(err) + } + + imgs := []name.Reference{ + name.MustParseReference("registry.io/repository/image"), + name.MustParseReference("registry.io/repository/image:tag"), + name.MustParseReference("registry.io/repository/image@sha256:9f80b4f7506d2799298a685162723482cac160abf701e029ee5cbaa6c74967ea"), + } + + got := items(imgs, dest) + + expected := map[string]string{ + "registry.io/repository/image": "newregistry.io/repository/image:latest", + "registry.io/repository/image:tag": "newregistry.io/repository/image:tag", + "registry.io/repository/image@sha256:9f80b4f7506d2799298a685162723482cac160abf701e029ee5cbaa6c74967ea": "newregistry.io/repository/image@sha256:9f80b4f7506d2799298a685162723482cac160abf701e029ee5cbaa6c74967ea", + } + + if !maps.Equal(expected, got) { + t.Errorf("expected and got images differ: %v != %v", expected, got) + } +} diff --git a/benchmark/offliner/referrers.go b/benchmark/offliner/referrers.go new file mode 100644 index 000000000..f182670ff --- /dev/null +++ b/benchmark/offliner/referrers.go @@ -0,0 +1,63 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/remote" +) + +func referrers(ref name.Reference) ([]name.Reference, error) { + var err error + var idx v1.ImageIndex + if d, ok := ref.(name.Digest); ok { + idx, err = remote.Referrers(d) + + if err != nil { + return nil, err + } + } else { + img, err := remote.Image(ref) + if err != nil { + return nil, err + } + + digest, err := img.Digest() + if err != nil { + return nil, err + } + ref := ref.Context().Digest(digest.String()) + idx, err = remote.Referrers(ref) + if err != nil { + return nil, err + } + } + + indexManifest, err := idx.IndexManifest() + if err != nil { + return nil, err + } + + references := make([]name.Reference, 0, len(indexManifest.Manifests)) + for _, manifest := range indexManifest.Manifests { + r := ref.Context().Digest(manifest.Digest.String()) + references = append(references, r) + } + + return references, nil +} diff --git a/benchmark/offliner/refs.go b/benchmark/offliner/refs.go new file mode 100644 index 000000000..190530bf4 --- /dev/null +++ b/benchmark/offliner/refs.go @@ -0,0 +1,44 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "fmt" + "strings" + + "github.com/google/go-containerregistry/pkg/name" +) + +func digestTag(ref name.Reference, suffix string) name.Reference { + digest := ref.(name.Digest).DigestStr() + + tag := fmt.Sprintf("%s.%s", strings.Replace(digest, ":", "-", 1), suffix) + + return ref.Context().Tag(tag) +} + +func signature(ref name.Reference) name.Reference { + return digestTag(ref, "sig") +} + +func attestation(ref name.Reference) name.Reference { + return digestTag(ref, "att") +} + +func sbom(ref name.Reference) name.Reference { + return digestTag(ref, "sbom") +} diff --git a/benchmark/offliner/related.go b/benchmark/offliner/related.go new file mode 100644 index 000000000..f7260fdde --- /dev/null +++ b/benchmark/offliner/related.go @@ -0,0 +1,91 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "log" + "slices" + "strings" + + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" +) + +type relatedFn func(ref name.Reference) ([]name.Reference, error) + +func related(ref name.Reference) ([]name.Reference, error) { + references := []name.Reference{ref} + + for _, r := range []name.Reference{ + signature(ref), + attestation(ref), + sbom(ref), + } { + if _, err := remote.Image(r); err == nil { + references = append(references, r) + } else { + log.Printf("Can't dereference %q: %v", r, err) + } + } + + related := []relatedFn{ + referrers, + baseImages, + scanReports, + subjects, + } + + for _, rel := range related { + refs, err := rel(ref) + if err != nil { + log.Printf("Can't fetch related image for %q: %v", ref, err) + continue + } + references = append(references, refs...) + } + + cmp := func(a, b name.Reference) int { + return strings.Compare(a.String(), b.String()) + } + + for _, ref := range references { + if _, ok := ref.(name.Digest); !ok { + img, err := remote.Image(ref) + if err != nil { + return nil, err + } + + digest, err := img.Digest() + if err != nil { + return nil, err + } + + ref = ref.Context().Digest(digest.String()) + } + + ref := signature(ref) + if _, err := remote.Image(ref); err == nil { + references = append(references, ref) + } else { + log.Printf("Can't dereference %q: %v", ref, err) + } + } + + slices.SortFunc(references, cmp) + + return slices.Compact(references), nil +} diff --git a/benchmark/offliner/scans.go b/benchmark/offliner/scans.go new file mode 100644 index 000000000..c864d5552 --- /dev/null +++ b/benchmark/offliner/scans.go @@ -0,0 +1,117 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "encoding/base64" + "encoding/json" + + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/in-toto/in-toto-golang/in_toto" + "github.com/secure-systems-lab/go-securesystemslib/dsse" +) + +func scanReports(ref name.Reference) ([]name.Reference, error) { + att := attestation(ref) + + img, err := remote.Image(att) + if err != nil { + return nil, err + } + + layers, err := img.Layers() + if err != nil { + return nil, err + } + + refs := make([]name.Reference, 0, 5) + for _, layer := range layers { + if mt, err := layer.MediaType(); err != nil || mt != "application/vnd.dsse.envelope.v1+json" { + continue + } + + data, err := layer.Uncompressed() + if err != nil { + return nil, err + } + defer data.Close() + + var envelope dsse.Envelope + decoder := json.NewDecoder(data) + if err := decoder.Decode(&envelope); err != nil { + return nil, err + } + + if envelope.PayloadType != "application/vnd.in-toto+json" { + continue + } + + raw, err := base64.StdEncoding.DecodeString(envelope.Payload) + if err != nil { + return nil, err + } + + var statement in_toto.ProvenanceStatementSLSA02 + if err := json.Unmarshal(raw, &statement); err != nil { + return nil, err + } + + if statement.PredicateType != "https://slsa.dev/provenance/v0.2" { + continue + } + + subject, err := name.NewRepository(statement.Subject[0].Name) + if err != nil { + return nil, err + } + + buildConfig := statement.Predicate.BuildConfig + + tasks := buildConfig.(map[string]any)["tasks"].([]any) + + for _, task := range tasks { + task := task.(map[string]any) + // TODO match by reference instead of name + if task["name"] != "clair-scan" { + continue + } + + results := task["results"].([]any) + + for _, result := range results { + result := result.(map[string]any) + if result["name"] != "REPORTS" { + continue + } + + report := result["value"] + + var reports map[string]string + if err := json.Unmarshal([]byte(report.(string)), &reports); err != nil { + return nil, err + } + + for _, digest := range reports { + refs = append(refs, subject.Digest(digest)) + } + } + } + } + + return refs, nil +} diff --git a/benchmark/offliner/subjects.go b/benchmark/offliner/subjects.go new file mode 100644 index 000000000..8d9f2317e --- /dev/null +++ b/benchmark/offliner/subjects.go @@ -0,0 +1,90 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "encoding/base64" + "encoding/json" + "fmt" + + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/in-toto/in-toto-golang/in_toto" + "github.com/secure-systems-lab/go-securesystemslib/dsse" +) + +func subjects(ref name.Reference) ([]name.Reference, error) { + att := attestation(ref) + + img, err := remote.Image(att) + if err != nil { + return nil, err + } + + layers, err := img.Layers() + if err != nil { + return nil, err + } + + refs := make([]name.Reference, 0, 5) + for _, layer := range layers { + if mt, err := layer.MediaType(); err != nil || mt != "application/vnd.dsse.envelope.v1+json" { + continue + } + + data, err := layer.Uncompressed() + if err != nil { + return nil, err + } + defer data.Close() + + var envelope dsse.Envelope + decoder := json.NewDecoder(data) + if err := decoder.Decode(&envelope); err != nil { + return nil, err + } + + if envelope.PayloadType != "application/vnd.in-toto+json" { + continue + } + + raw, err := base64.StdEncoding.DecodeString(envelope.Payload) + if err != nil { + return nil, err + } + + var statement in_toto.ProvenanceStatementSLSA02 + if err := json.Unmarshal(raw, &statement); err != nil { + return nil, err + } + + if statement.PredicateType != "https://slsa.dev/provenance/v0.2" { + continue + } + + for _, subject := range statement.Subject { + ref, err := name.NewRepository(subject.Name) + if err != nil { + return nil, err + } + refs = append(refs, ref.Digest(fmt.Sprintf("sha256:%s", subject.Digest["sha256"]))) + } + + } + + return refs, nil +} diff --git a/benchmark/simple/prepare_data.sh b/benchmark/simple/prepare_data.sh new file mode 100755 index 000000000..a710d65f9 --- /dev/null +++ b/benchmark/simple/prepare_data.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright The Enterprise Contract Contributors +# +# 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. +# +# SPDX-License-Identifier: Apache-2.0 + +# Creates the files in the data directory that should contain all the data +# needed to run the benchmark, uses the ../offliner for images andplain git +# clone for the git data dependency +set -o errexit +set -o nounset +set -o pipefail + +offliner="$(git rev-parse --show-toplevel)/benchmark/offliner" + +dir="$(mktemp -d)" +trap 'rm -rf "${dir}"' EXIT + +( + cd "${dir}" + + imgs=( + quay.io/redhat-user-workloads/rhtap-contract-tenant/golden-container/golden-container@sha256:166e38c156fa81d577a7ba7a948b68c79005a06e302779d1bebc7d31e8bea315 + quay.io/konflux-ci/tekton-catalog/data-acceptable-bundles@sha256:1e70b8f672388838f20a7d45e145e31e99dab06cefa1c5514d6ce41c8bbea1b0 + quay.io/enterprise-contract/ec-release-policy@sha256:faed14fcf1a00cc19d6e71040219d232a6549e28167650e03ff4ca3204a73a24 + ) + + for img in "${imgs[@]}"; do + go run -C "${offliner}" . "${img}" "${dir}/data/registry/data" + done + + git clone --no-checkout https://github.com/release-engineering/rhtap-ec-policy.git data/git/rhtap-ec-policy.git +) + +tar czf data.tar.gz -C "${dir}" . diff --git a/benchmark/simple/simple.go b/benchmark/simple/simple.go new file mode 100644 index 000000000..789925243 --- /dev/null +++ b/benchmark/simple/simple.go @@ -0,0 +1,123 @@ +// Copyright The Enterprise Contract Contributors +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +// Simple benchmark running the @redhat collection policy at a fixed point in +// time with the state of the container image registry contained within the +// data/registry and git state within data/git. The prepare_data.sh script can +// be used to re-populate the data directory. +package main + +import ( + "fmt" + "os" + "path" + + "golang.org/x/benchmarks/driver" + + "github.com/enterprise-contract/ec-cli/benchmark/internal/registry" + "github.com/enterprise-contract/ec-cli/benchmark/internal/suite" + "github.com/enterprise-contract/ec-cli/benchmark/internal/untar" +) + +func main() { + driver.Main("Simple", benchmark) +} + +func setup() (string, suite.Closer) { + dir, err := untar.UnTar("data.tar.gz") + if err != nil { + panic(err) + } + + closer, err := registry.Launch(path.Join(dir, "data/registry/data")) + if err != nil { + panic(err) + } + + return dir, func() { + closer() + os.RemoveAll(dir) + } +} + +func benchmark() driver.Result { + dir, closer := setup() + defer closer() + + return driver.Benchmark(run(dir)) +} + +func ec(dir string) func() { + snapshot := `{ +"components": [ +{ + "name": "golden-container", + "containerImage": "quay.io/redhat-user-workloads/rhtap-contract-tenant/golden-container/golden-container@sha256:166e38c156fa81d577a7ba7a948b68c79005a06e302779d1bebc7d31e8bea315", + "source": { + "git": { + "url": "https://github.com/enterprise-contract/golden-container", + "revision": "8327c1ce7472b017b9396fe26d5d5e1ed0eb61cc" + } + } +} +] +}` + + policy := fmt.Sprintf(`{ +"publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA\nnaYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==\n-----END PUBLIC KEY-----", +"sources": [ +{ + "data": [ + "git::file://%s/data/git/rhtap-ec-policy.git//data?ref=a524ee2f2f7774f6f360eb64c4cb24004de52aae", + "oci::quay.io/konflux-ci/tekton-catalog/data-acceptable-bundles@sha256:1e70b8f672388838f20a7d45e145e31e99dab06cefa1c5514d6ce41c8bbea1b0" + ], + "policy": [ + "oci::quay.io/enterprise-contract/ec-release-policy@sha256:faed14fcf1a00cc19d6e71040219d232a6549e28167650e03ff4ca3204a73a24" + ], + "config": { + "include": [ + "@redhat" + ], + }, +} +] +}`, dir) + + return func() { + + os.Setenv("EC_CACHE", "false") + + if err := suite.Execute([]string{ + "validate", + "image", + "--json-input", + snapshot, + "--policy", + policy, + "--ignore-rekor", + "--effective-time", + "2024-12-10T00:00:00Z", + }); err != nil { + panic(err) + } + } +} + +func run(dir string) func(n uint64) { + return func(n uint64) { + driver.Parallel(n, 1, ec(dir)) + } +} diff --git a/cmd/root.go b/cmd/root.go index 1ce92a82d..ce0aca7a2 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -20,6 +20,7 @@ import ( "context" log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" "github.com/enterprise-contract/ec-cli/cmd/fetch" "github.com/enterprise-contract/ec-cli/cmd/initialize" @@ -51,15 +52,19 @@ func Execute() { } func init() { - RootCmd.AddCommand(fetch.FetchCmd) - RootCmd.AddCommand(initialize.InitCmd) - RootCmd.AddCommand(inspect.InspectCmd) - RootCmd.AddCommand(track.TrackCmd) - RootCmd.AddCommand(validate.ValidateCmd) - RootCmd.AddCommand(version.VersionCmd) - RootCmd.AddCommand(opa.OPACmd) - RootCmd.AddCommand(sigstore.SigstoreCmd) + AddCommandsTo(RootCmd) +} + +func AddCommandsTo(cmd *cobra.Command) { + cmd.AddCommand(fetch.FetchCmd) + cmd.AddCommand(initialize.InitCmd) + cmd.AddCommand(inspect.InspectCmd) + cmd.AddCommand(track.TrackCmd) + cmd.AddCommand(validate.ValidateCmd) + cmd.AddCommand(version.VersionCmd) + cmd.AddCommand(opa.OPACmd) + cmd.AddCommand(sigstore.SigstoreCmd) if utils.Experimental() { - RootCmd.AddCommand(test.TestCmd) + cmd.AddCommand(test.TestCmd) } } diff --git a/go.mod b/go.mod index 011f49c35..ddedc7fe6 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,10 @@ go 1.22.7 require ( cuelang.org/go v0.11.0 + github.com/CycloneDX/cyclonedx-go v0.9.0 github.com/MakeNowJust/heredoc v1.0.0 github.com/Maldris/go-billy-afero v0.0.0-20200815120323-e9d3de59c99a + github.com/docker/docker v27.1.1+incompatible github.com/enterprise-contract/enterprise-contract-controller/api v0.1.69 github.com/enterprise-contract/go-gather v0.0.5 github.com/evanphx/json-patch v5.9.0+incompatible @@ -14,6 +16,7 @@ require ( github.com/go-logr/logr v1.4.2 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.20.2 + github.com/google/safearchive v0.0.0-20241025131057-f7ce9d7b6f9c github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b github.com/hashicorp/go-getter v1.7.6 github.com/in-toto/in-toto-golang v0.9.0 @@ -31,6 +34,8 @@ require ( github.com/sigstore/cosign/v2 v2.4.1 github.com/sigstore/sigstore v1.8.9 github.com/sirupsen/logrus v1.9.3 + github.com/smarty/cproxy/v2 v2.1.1 + github.com/spdx/tools-golang v0.5.5 github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 @@ -38,6 +43,9 @@ require ( github.com/stretchr/testify v1.10.0 github.com/stuart-warren/yamlfmt v0.2.0 github.com/tektoncd/pipeline v0.63.0 + github.com/testcontainers/testcontainers-go v0.34.1-0.20241204123437-72be13940122 // using unreleased version that contains the fix in https://github.com/testcontainers/testcontainers-go/pull/2899 + github.com/testcontainers/testcontainers-go/modules/registry v0.34.0 + golang.org/x/benchmarks v0.0.0-20241115175113-a2b48b605b42 golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/net v0.32.0 golang.org/x/sync v0.10.0 @@ -67,6 +75,7 @@ require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.15.0 // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.29 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.24 // indirect @@ -76,7 +85,6 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/BurntSushi/toml v1.4.0 // indirect - github.com/CycloneDX/cyclonedx-go v0.9.0 // indirect github.com/KeisukeYamashita/go-vcl v0.4.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect @@ -141,6 +149,7 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/containerd/typeurl/v2 v2.2.0 // indirect github.com/coreos/go-oidc/v3 v3.11.0 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect github.com/cyphar/filepath-securejoin v0.3.4 // indirect @@ -150,9 +159,11 @@ require ( github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v27.2.0+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect @@ -173,6 +184,7 @@ require ( github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/analysis v0.23.0 // indirect github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -226,6 +238,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/letsencrypt/boulder v0.0.0-20240830194243-1fcf0ee08180 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/maruel/natural v1.1.1 // indirect @@ -237,8 +250,14 @@ require ( github.com/moby/buildkit v0.15.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/mozillazg/docker-credential-acr-helper v0.4.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect @@ -252,6 +271,7 @@ require ( github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.58.0 // indirect @@ -267,6 +287,8 @@ require ( github.com/segmentio/ksuid v1.0.4 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/shibumi/go-pathspec v1.3.0 // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shteou/go-ignore v0.3.1 // indirect github.com/sigstore/fulcio v1.6.3 // indirect github.com/sigstore/protobuf-specs v0.3.2 // indirect @@ -275,7 +297,6 @@ require ( github.com/skeema/knownhosts v1.3.0 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spdx/tools-golang v0.5.5 // indirect github.com/spf13/cast v1.7.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/stretchr/objx v0.5.2 // indirect @@ -290,6 +311,8 @@ require ( github.com/tidwall/sjson v1.2.5 // indirect github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/tmccombs/hcl2json v0.6.4 // indirect github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect github.com/transparency-dev/merkle v0.0.2 // indirect @@ -301,6 +324,7 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yashtewari/glob-intersection v0.2.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/zclconf/go-cty v1.15.0 // indirect go.mongodb.org/mongo-driver v1.16.1 // indirect go.opencensus.io v0.24.0 // indirect @@ -319,11 +343,11 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.31.0 // indirect golang.org/x/mod v0.21.0 // indirect - golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/term v0.27.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.26.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/api v0.196.0 // indirect diff --git a/go.sum b/go.sum index 66babd806..db33a97e3 100644 --- a/go.sum +++ b/go.sum @@ -222,6 +222,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0/go.mod h1:qLIye2hwb/ZouqhpSD9Zn3SJipvpEnz1Ywl3VUk9Y0s= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= @@ -493,11 +495,15 @@ github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03V github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= @@ -526,12 +532,18 @@ github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 h1:lxmTCgmHE1G github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7/go.mod h1:GvWntX9qiTlOud0WkQ6ewFm0LPy5JUR1Xo0Ngbd1w6Y= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v27.2.0+incompatible h1:yHD1QEB1/0vr5eBNpu8tncu8gWxg8EydFPOSKHzXSMM= github.com/docker/cli v27.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -631,6 +643,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= @@ -778,11 +792,13 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= -github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20241017200806-017d972448fc h1:NGyrhhFhwvRAZg02jnYVg3GBQy0qGBKmFQJwaPmpmxs= +github.com/google/pprof v0.0.0-20241017200806-017d972448fc/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/safearchive v0.0.0-20241025131057-f7ce9d7b6f9c h1:GzqKebXGmQ+9RUwNUCjt768fVW0mMkSjw+BTR7wlyLQ= +github.com/google/safearchive v0.0.0-20241025131057-f7ce9d7b6f9c/go.mod h1:OqnQPv70Lm5prPo201C0t0krFmSjwgcWIAsA9S0xdQA= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM= github.com/google/trillian v1.6.0 h1:jMBeDBIkINFvS2n6oV5maDqfRlxREAc6CW9QYWQ0qT4= @@ -951,6 +967,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -1002,10 +1020,18 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1013,6 +1039,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozillazg/docker-credential-acr-helper v0.4.0 h1:Uoh3Z9CcpEDnLiozDx+D7oDgRq7X+R296vAqAumnOcw= github.com/mozillazg/docker-credential-acr-helper v0.4.0/go.mod h1:2kiicb3OlPytmlNC9XGkLvVC+f0qTiJw3f/mhmeeQBg= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -1085,6 +1113,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1162,6 +1192,12 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shteou/go-ignore v0.3.1 h1:/DVY4w06eKliWrbkwKfBHJgUleld+QAlmlQvfRQOigA= github.com/shteou/go-ignore v0.3.1/go.mod h1:hMVyBe+qt5/Z11W/Fxxf86b5SuL8kM29xNWLYob9Vos= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -1204,6 +1240,12 @@ github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:s github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smarty/assertions v1.16.0 h1:EvHNkdRA4QHMrn75NZSoUQ/mAUXAYWfatfB01yTCzfY= +github.com/smarty/assertions v1.16.0/go.mod h1:duaaFdCS0K9dnoM50iyek/eYINOZ64gbh1Xlf6LG7AI= +github.com/smarty/cproxy/v2 v2.1.1 h1:CReH/eZaK/YEQbWHYaoYFTtXFwjZCggqWrNLC5d46vE= +github.com/smarty/cproxy/v2 v2.1.1/go.mod h1:YzpKMSNNMlkkPUCeAnCLKJtjOwlYqQET7ZF3DFHEQ3g= +github.com/smarty/gunit v1.5.0 h1:OmG6a/rgi7qCjlQis6VjXbvx/WqZ8I6xSlbfN4YB5MY= +github.com/smarty/gunit v1.5.0/go.mod h1:uAeNibUD292KZRcg5OTy7lb6WR5++UC0BQOzNuiRzpU= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1278,6 +1320,10 @@ github.com/tektoncd/pipeline v0.63.0 h1:QLkhYr970jgs6vmHopXz8pcXbz5c3i0a0FX7ggGt github.com/tektoncd/pipeline v0.63.0/go.mod h1:HA7r0XJzhhcajNBcl0GErmcT5Omow1jVfLKwbVGjojY= github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw= +github.com/testcontainers/testcontainers-go v0.34.1-0.20241204123437-72be13940122 h1:dsnk0a/bMsSQzsfrFCvXkbp9arGuAVgike7POsCRXOg= +github.com/testcontainers/testcontainers-go v0.34.1-0.20241204123437-72be13940122/go.mod h1:wJduyVyIhQzkHwN3OZlrCQDygQpC3VNQEKewxc4c058= +github.com/testcontainers/testcontainers-go/modules/registry v0.34.0 h1:ooSrochnpOleRvr1/uOirSi+5Zjk9udmG7mkoQKmdEQ= +github.com/testcontainers/testcontainers-go/modules/registry v0.34.0/go.mod h1:lVn5G9wnfLV4N1WPdCtPUV9zlGbJvqyidSlojZLOBVA= github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg= github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU= github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI= @@ -1299,6 +1345,10 @@ github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHT github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmccombs/hcl2json v0.6.4 h1:/FWnzS9JCuyZ4MNwrG4vMrFrzRgsWEOVi+1AyYUVLGw= github.com/tmccombs/hcl2json v0.6.4/go.mod h1:+ppKlIW3H5nsAsZddXPy2iMyvld3SHxyjswOZhavRDk= github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 h1:2f304B10LaZdB8kkVEaoXvAMVan2tl9AiK4G0odjQtE= @@ -1345,6 +1395,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= @@ -1383,6 +1435,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrT go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY= go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= @@ -1408,6 +1462,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/benchmarks v0.0.0-20241115175113-a2b48b605b42 h1:BzkGQzHX30kNxg8pXCGB6nzRQhf7EkzvW+PIFMPu4mI= +golang.org/x/benchmarks v0.0.0-20241115175113-a2b48b605b42/go.mod h1:ffJO46aE6lfIXB1/kHNFyBOmsVj/KyOMziH9Cxj4uEE= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1565,8 +1621,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1603,6 +1659,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1630,6 +1687,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1678,6 +1736,7 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -1714,8 +1773,8 @@ golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2048,8 +2107,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=