From 67ff1ebde4841e14912bc8865e7c7cbb7ae09d5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 22:23:21 +0000 Subject: [PATCH] build(deps): bump github.com/containers/common from 0.55.4 to 0.57.4 Bumps [github.com/containers/common](https://github.com/containers/common) from 0.55.4 to 0.57.4. - [Release notes](https://github.com/containers/common/releases) - [Commits](https://github.com/containers/common/compare/v0.55.4...v0.57.4) --- updated-dependencies: - dependency-name: github.com/containers/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 121 +- go.sum | 263 +- .../Microsoft/hcsshim/internal/hcs/process.go | 68 +- .../internal/hcs/schema2/close_handle.go | 4 +- .../internal/hcs/schema2/console_size.go | 7 +- .../hcs/schema2/process_modify_request.go | 6 +- .../internal/hcs/schema2/process_status.go | 9 +- .../Microsoft/hcsshim/internal/hcs/system.go | 31 +- .../Microsoft/hcsshim/internal/log/format.go | 7 +- .../Microsoft/hcsshim/internal/log/hook.go | 5 +- .../hcsshim/internal/log/nopformatter.go | 12 + .../internal/protocol/guestrequest/types.go | 22 +- .../hcsshim/internal/wclayer/layerutils.go | 24 + vendor/github.com/Microsoft/hcsshim/layer.go | 1 + .../go-crypto/openpgp/armor/armor.go | 11 +- .../go-crypto/openpgp/packet/public_key.go | 4 + .../go-crypto/openpgp/packet/signature.go | 2 +- .../openpgp/packet/symmetric_key_encrypted.go | 31 +- .../containerd/log/context_deprecated.go | 149 + .../containerd/platforms/defaults_windows.go | 26 +- .../containerd/platforms/platforms.go | 12 + .../containerd/platforms/platforms_other.go | 4 + .../containerd/platforms/platforms_windows.go | 8 + .../containerd/containerd/plugin/context.go | 16 +- .../containerd/containerd/plugin/plugin.go | 7 +- .../containerd/plugin/plugin_go18.go | 17 +- .../containerd/plugin/plugin_other.go | 4 +- .../containerd/containerd/version/version.go | 2 +- .../github.com/containerd/log/.golangci.yml | 30 + vendor/github.com/containerd/log/LICENSE | 191 + vendor/github.com/containerd/log/README.md | 17 + .../{containerd => }/log/context.go | 11 +- .../containerd/nri/pkg/adaptation/api.go | 1 + .../containerd/nri/pkg/adaptation/plugin.go | 2 +- .../containerd/nri/pkg/adaptation/result.go | 36 + .../containerd/nri/pkg/api/adjustment.go | 15 + .../containerd/nri/pkg/api/api.pb.go | 1123 +- .../containerd/nri/pkg/api/api.proto | 9 + .../containerd/nri/pkg/api/api_ttrpc.pb.go | 157 +- .../containerd/nri/pkg/api/event.go | 4 +- .../pkg/runtime-tools/generate/generate.go | 17 + .../containerd/nri/pkg/stub/stub.go | 90 +- .../stargz-snapshotter/estargz/build.go | 3 +- .../common/internal/attributedstring/slice.go | 102 + .../containers/common/libimage/copier.go | 88 +- .../common/libimage/define/manifests.go | 27 + .../common/libimage/define/platform.go | 11 + .../containers/common/libimage/disk_usage.go | 3 + .../containers/common/libimage/events.go | 3 + .../common/libimage/filter/filter.go | 55 + .../containers/common/libimage/filters.go | 27 +- .../containers/common/libimage/history.go | 54 +- .../containers/common/libimage/image.go | 109 +- .../common/libimage/image_config.go | 5 +- .../containers/common/libimage/image_tree.go | 3 + .../containers/common/libimage/import.go | 5 +- .../containers/common/libimage/inspect.go | 3 + .../containers/common/libimage/layer_tree.go | 25 + .../containers/common/libimage/load.go | 3 + .../common/libimage/manifest_list.go | 36 +- .../common/libimage/manifests/manifests.go | 64 +- .../containers/common/libimage/normalize.go | 3 + .../containers/common/libimage/oci.go | 3 + .../containers/common/libimage/platform.go | 99 +- .../common/libimage/platform/platform.go | 57 + .../containers/common/libimage/pull.go | 23 +- .../containers/common/libimage/push.go | 3 + .../containers/common/libimage/runtime.go | 47 +- .../containers/common/libimage/save.go | 3 + .../containers/common/libimage/search.go | 61 +- .../common/libnetwork/cni/network.go | 16 +- .../common/libnetwork/cni/run_freebsd.go | 8 +- .../common/libnetwork/etchosts/hosts.go | 17 +- .../common/libnetwork/internal/util/util.go | 4 +- .../common/libnetwork/netavark/config.go | 5 +- .../common/libnetwork/netavark/exec.go | 2 +- .../common/libnetwork/netavark/ipam.go | 2 +- .../common/libnetwork/netavark/network.go | 18 +- .../common/libnetwork/network/interface.go | 6 +- .../common/libnetwork/pasta/pasta.go | 2 +- .../libnetwork/slirp4netns/slirp4netns.go | 4 +- .../common/libnetwork/types/const.go | 1 + .../common/libnetwork/util/filters.go | 4 +- .../common/pkg/apparmor/apparmor_linux.go | 5 + .../pkg/apparmor/apparmor_linux_template.go | 2 +- .../containers/common/pkg/cgroups/blkio.go | 151 - .../common/pkg/cgroups/blkio_linux.go | 1 - .../containers/common/pkg/cgroups/cgroups.go | 614 - .../common/pkg/cgroups/cgroups_linux.go | 187 +- .../common/pkg/cgroups/cgroups_supported.go | 9 + .../common/pkg/cgroups/cgroups_unsupported.go | 8 + .../containers/common/pkg/cgroups/cpu.go | 91 - .../containers/common/pkg/cgroups/cpuset.go | 49 - .../containers/common/pkg/cgroups/memory.go | 69 - .../common/pkg/cgroups/memory_linux.go | 21 +- .../containers/common/pkg/cgroups/pids.go | 71 - .../common/pkg/cgroups/systemd_linux.go | 3 +- .../containers/common/pkg/cgroups/utils.go | 179 - .../common/pkg/cgroups/utils_linux.go | 7 +- .../containers/common/pkg/config/config.go | 472 +- .../common/pkg/config/config_darwin.go | 4 +- .../common/pkg/config/config_local.go | 34 +- .../common/pkg/config/containers.conf | 72 +- .../common/pkg/config/containers.conf-freebsd | 42 +- .../common/pkg/config/db_backend.go | 17 +- .../containers/common/pkg/config/default.go | 209 +- .../common/pkg/config/default_darwin.go | 11 + .../common/pkg/config/default_freebsd.go | 4 + .../common/pkg/config/default_linux.go | 17 +- .../common/pkg/config/default_unsupported.go | 11 - .../common/pkg/config/default_windows.go | 16 +- .../containers/common/pkg/config/modules.go | 95 + .../containers/common/pkg/config/new.go | 240 + .../containers/common/pkg/filters/filters.go | 55 +- .../containers/common/pkg/flag/flag.go | 2 +- .../containers/common/pkg/retry/retry.go | 1 - .../pkg/secrets/filedriver/filedriver.go | 2 +- .../containers/common/pkg/secrets/secrets.go | 25 +- .../pkg/secrets/shelldriver/shelldriver.go | 1 - .../common/pkg/ssh/connection_golang.go | 17 +- .../common/pkg/ssh/connection_native.go | 2 +- .../containers/common/pkg/ssh/types.go | 1 + .../containers/common/pkg/ssh/utils.go | 36 +- .../common/pkg/subscriptions/subscriptions.go | 30 +- .../containers/common/pkg/util/copy.go | 57 - .../containers/common/pkg/util/util.go | 105 - .../containers/common/pkg/version/version.go | 105 + .../containers/common/version/version.go | 2 +- .../containers/image/v5/copy/compression.go | 20 +- .../containers/image/v5/copy/copy.go | 30 +- .../containers/image/v5/copy/encryption.go | 2 +- .../containers/image/v5/copy/multiple.go | 17 +- .../containers/image/v5/copy/progress_bars.go | 5 + .../containers/image/v5/copy/single.go | 46 +- .../image/v5/docker/daemon/client.go | 7 +- .../image/v5/docker/daemon/daemon_dest.go | 33 +- .../image/v5/docker/distribution_error.go | 3 +- .../image/v5/docker/docker_client.go | 91 +- .../image/v5/docker/docker_image.go | 3 + .../image/v5/docker/docker_image_dest.go | 70 +- .../image/v5/docker/docker_image_src.go | 15 +- .../image/v5/docker/docker_transport.go | 63 +- .../containers/image/v5/docker/errors.go | 9 +- .../v5/docker/internal/tarfile/reader.go | 2 +- .../v5/docker/policyconfiguration/naming.go | 2 +- .../containers/image/v5/image/unparsed.go | 22 + .../internal/blobinfocache/blobinfocache.go | 6 + .../image/v5/internal/blobinfocache/types.go | 16 +- .../containers/image/v5/internal/image/oci.go | 79 +- .../internal/imagedestination/impl/helpers.go | 5 + .../internal/manifest/docker_schema2_list.go | 70 +- .../image/v5/internal/manifest/errors.go | 22 +- .../image/v5/internal/manifest/oci_index.go | 80 +- .../internal/pkg/platform/platform_matcher.go | 4 + .../v5/internal/streamdigest/stream_digest.go | 2 +- .../image/v5/internal/tmpdir/tmpdir.go | 12 +- .../image/v5/manifest/docker_schema1.go | 3 + .../image/v5/manifest/docker_schema2.go | 3 + .../containers/image/v5/manifest/oci.go | 4 +- .../image/v5/oci/archive/oci_src.go | 12 + .../image/v5/oci/archive/oci_transport.go | 21 +- .../image/v5/oci/layout/oci_delete.go | 240 + .../image/v5/oci/layout/oci_dest.go | 15 +- .../containers/image/v5/oci/layout/oci_src.go | 2 +- .../image/v5/oci/layout/oci_transport.go | 50 +- .../image/v5/openshift/openshift.go | 4 + .../image/v5/openshift/openshift_dest.go | 4 +- .../image/v5/openshift/openshift_src.go | 9 +- .../v5/pkg/blobinfocache/boltdb/boltdb.go | 393 - .../image/v5/pkg/blobinfocache/default.go | 20 +- .../internal/prioritize/prioritize.go | 57 +- .../v5/pkg/blobinfocache/memory/memory.go | 68 +- .../v5/pkg/blobinfocache/sqlite/sqlite.go | 575 + .../image/v5/pkg/docker/config/config.go | 286 +- .../image/v5/pkg/shortnames/shortnames.go | 3 +- .../v5/pkg/tlsclientconfig/tlsclientconfig.go | 2 +- .../github.com/containers/image/v5/sif/src.go | 2 +- .../image/v5/signature/sigstore/copied.go | 2 +- .../image/v5/storage/storage_dest.go | 178 +- .../image/v5/storage/storage_reference.go | 31 + .../image/v5/storage/storage_src.go | 18 +- .../image/v5/storage/storage_transport.go | 33 + .../transports/alltransports/alltransports.go | 11 +- .../containers/image/v5/types/types.go | 8 +- .../containers/image/v5/version/version.go | 4 +- .../github.com/containers/ocicrypt/Makefile | 1 + .../keywrap/pkcs11/keywrapper_pkcs11.go | 6 +- .../containers/ocicrypt/spec/spec.go | 10 +- .../github.com/containers/storage/.cirrus.yml | 6 +- vendor/github.com/containers/storage/VERSION | 2 +- .../containers/storage/drivers/driver.go | 3 + .../storage/drivers/overlay/check.go | 33 + .../drivers/overlay/composefs_notsupported.go | 6 +- .../drivers/overlay/composefs_supported.go | 54 +- .../storage/drivers/overlay/mount.go | 21 +- .../storage/drivers/overlay/overlay.go | 95 +- .../github.com/containers/storage/layers.go | 20 +- .../containers/storage/pkg/archive/archive.go | 19 +- .../storage/pkg/chunked/cache_linux.go | 5 + .../storage/pkg/chunked/dump/dump.go | 230 + .../storage/pkg/chunked/storage_linux.go | 22 +- .../storage/pkg/loopback/attach_loopback.go | 18 +- .../containers/storage/pkg/system/rm.go | 6 +- .../storage/pkg/unshare/unshare_darwin.go | 5 + .../storage/pkg/unshare/unshare_linux.go | 10 + .../pkg/unshare/unshare_unsupported.go | 5 + .../containers/storage/storage.conf | 5 +- vendor/github.com/containers/storage/store.go | 25 +- .../containers/storage/types/options.go | 5 +- .../cpuguy83/go-md2man/v2/md2man/md2man.go | 6 +- .../cpuguy83/go-md2man/v2/md2man/roff.go | 30 +- .../distribution/reference/.gitignore | 2 + .../distribution/reference/.golangci.yml | 18 + .../distribution/reference/CODE-OF-CONDUCT.md | 5 + .../distribution/reference/CONTRIBUTING.md | 114 + .../distribution/reference/GOVERNANCE.md | 144 + .../github.com/distribution/reference/LICENSE | 202 + .../distribution/reference/MAINTAINERS | 26 + .../distribution/reference/Makefile | 25 + .../distribution/reference/README.md | 30 + .../distribution/reference/SECURITY.md | 7 + .../reference/distribution-logo.svg | 1 + .../distribution/reference/helpers.go | 2 +- .../distribution/reference/normalize.go | 131 +- .../distribution/reference/reference.go | 27 +- .../distribution/reference/regexp.go | 163 + .../github.com/distribution/reference/sort.go | 75 + .../reference/helpers_deprecated.go | 34 + .../reference/normalize_deprecated.go | 92 + .../reference/reference_deprecated.go | 172 + .../docker/distribution/reference/regexp.go | 143 - .../reference/regexp_deprecated.go | 50 + .../distribution/reference/sort_deprecated.go | 10 + .../registry/api/v2/descriptors.go | 2 +- .../distribution/registry/api/v2/urls.go | 2 +- .../client/client.go | 8 +- .../client/command.go | 13 +- .../credentials/credentials.go | 69 +- .../credentials/error.go | 31 +- .../github.com/docker/docker/api/swagger.yaml | 50 +- .../docker/docker/api/types/configs.go | 4 +- .../docker/docker/api/types/filters/parse.go | 10 +- .../docker/docker/api/types/image/opts.go | 4 +- .../docker/api/types/registry/registry.go | 6 +- .../docker/api/types/versions/compare.go | 8 +- .../github.com/docker/docker/client/client.go | 30 + .../docker/docker/client/container_create.go | 6 +- .../github.com/docker/docker/client/hijack.go | 13 +- .../docker/docker/client/interface.go | 4 +- .../docker/docker/client/request.go | 10 +- .../docker/docker/pkg/archive/diff.go | 19 + .../docker/docker/pkg/idtools/idtools_unix.go | 5 +- .../github.com/fsnotify/fsnotify/.cirrus.yml | 13 + .../github.com/fsnotify/fsnotify/.gitignore | 1 + .../github.com/fsnotify/fsnotify/CHANGELOG.md | 83 +- vendor/github.com/fsnotify/fsnotify/README.md | 81 +- .../fsnotify/fsnotify/backend_fen.go | 552 +- .../fsnotify/fsnotify/backend_inotify.go | 377 +- .../fsnotify/fsnotify/backend_kqueue.go | 295 +- .../fsnotify/fsnotify/backend_other.go | 205 +- .../fsnotify/fsnotify/backend_windows.go | 247 +- .../github.com/fsnotify/fsnotify/fsnotify.go | 91 +- vendor/github.com/fsnotify/fsnotify/mkdoc.zsh | 125 +- .../go-jose/go-jose/v3/CHANGELOG.md | 8 + .../go-jose/go-jose/v3/symmetric.go | 5 + vendor/github.com/go-logr/logr/README.md | 113 +- vendor/github.com/go-logr/logr/SECURITY.md | 18 + vendor/github.com/go-logr/logr/funcr/funcr.go | 48 +- vendor/github.com/go-logr/logr/logr.go | 35 +- .../github.com/google/go-cmp/cmp/compare.go | 38 +- .../cmp/{export_unsafe.go => export.go} | 5 - .../google/go-cmp/cmp/export_panic.go | 16 - .../value/{pointer_unsafe.go => pointer.go} | 3 - .../cmp/internal/value/pointer_purego.go | 34 - .../github.com/google/go-cmp/cmp/options.go | 84 +- vendor/github.com/google/go-cmp/cmp/path.go | 46 +- .../google/go-cmp/cmp/report_reflect.go | 2 +- .../go-containerregistry/pkg/v1/config.go | 151 + .../google/go-containerregistry/pkg/v1/doc.go | 18 + .../go-containerregistry/pkg/v1/hash.go | 123 + .../go-containerregistry/pkg/v1/image.go | 59 + .../go-containerregistry/pkg/v1/index.go | 43 + .../go-containerregistry/pkg/v1/layer.go | 42 + .../go-containerregistry/pkg/v1/manifest.go | 71 + .../go-containerregistry/pkg/v1/platform.go | 149 + .../go-containerregistry/pkg/v1/progress.go | 25 + .../pkg/v1/types/types.go | 98 + .../pkg/v1/zz_deepcopy_generated.go | 339 + .../grpc-gateway/v2/{LICENSE.txt => LICENSE} | 0 .../grpc-gateway/v2/runtime/BUILD.bazel | 8 +- .../grpc-gateway/v2/runtime/fieldmask.go | 2 +- .../grpc-gateway/v2/runtime/handler.go | 3 +- .../v2/runtime/marshal_httpbodyproto.go | 2 +- vendor/github.com/jinzhu/copier/.gitignore | 2 + vendor/github.com/jinzhu/copier/README.md | 10 +- vendor/github.com/jinzhu/copier/copier.go | 405 +- vendor/github.com/jinzhu/copier/errors.go | 9 +- .../klauspost/compress/.goreleaser.yml | 20 +- .../github.com/klauspost/compress/README.md | 27 + .../klauspost/compress/flate/deflate.go | 29 + .../klauspost/compress/flate/fast_encoder.go | 23 - .../klauspost/compress/flate/inflate.go | 66 +- .../klauspost/compress/flate/inflate_gen.go | 34 +- .../klauspost/compress/flate/level5.go | 398 + .../compress/flate/matchlen_amd64.go | 16 + .../klauspost/compress/flate/matchlen_amd64.s | 68 + .../compress/flate/matchlen_generic.go | 33 + .../klauspost/compress/fse/bitwriter.go | 3 +- .../klauspost/compress/fse/compress.go | 5 +- .../klauspost/compress/huff0/bitwriter.go | 3 +- .../klauspost/compress/huff0/compress.go | 20 +- .../klauspost/compress/zstd/bitreader.go | 34 +- .../klauspost/compress/zstd/bitwriter.go | 3 +- .../klauspost/compress/zstd/blockenc.go | 29 +- .../klauspost/compress/zstd/dict.go | 379 +- .../klauspost/compress/zstd/enc_best.go | 55 +- .../klauspost/compress/zstd/enc_better.go | 17 +- .../klauspost/compress/zstd/encoder.go | 13 +- .../klauspost/compress/zstd/frameenc.go | 4 +- .../klauspost/compress/zstd/seqdec.go | 17 +- .../klauspost/compress/zstd/seqdec_amd64.s | 128 +- .../klauspost/compress/zstd/seqdec_generic.go | 2 +- .../klauspost/compress/zstd/snappy.go | 5 +- .../mattn/go-sqlite3/sqlite3-binding.c | 12588 +++++++++++----- .../mattn/go-sqlite3/sqlite3-binding.h | 291 +- .../github.com/mattn/go-sqlite3/sqlite3ext.h | 10 + .../moby/sys/mountinfo/mountinfo_linux.go | 50 +- vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md | 12 + .../ginkgo/v2/ginkgo/internal/test_suite.go | 3 +- .../onsi/ginkgo/v2/types/version.go | 2 +- vendor/github.com/onsi/gomega/CHANGELOG.md | 23 + vendor/github.com/onsi/gomega/gomega_dsl.go | 10 +- vendor/github.com/onsi/gomega/matchers.go | 56 +- .../onsi/gomega/matchers/be_false_matcher.go | 13 +- .../onsi/gomega/matchers/be_true_matcher.go | 13 +- .../gomega/matchers/match_error_matcher.go | 25 +- .../go-digest}/digestset/set.go | 15 + .../image-spec/specs-go/v1/descriptor.go | 2 +- .../image-spec/specs-go/v1/layout.go | 6 +- .../image-spec/specs-go/version.go | 2 +- .../runc/libcontainer/cgroups/file.go | 3 +- .../runc/libcontainer/cgroups/fs/hugetlb.go | 36 +- .../runc/libcontainer/cgroups/fs/memory.go | 6 + .../runc/libcontainer/cgroups/fs2/hugetlb.go | 30 +- .../runtime-tools/generate/generate.go | 2 +- .../generate/seccomp/parse_action.go | 6 +- .../generate/seccomp/seccomp_default.go | 2 - vendor/github.com/pkg/sftp/attrs.go | 33 +- vendor/github.com/pkg/sftp/attrs_stubs.go | 1 + vendor/github.com/pkg/sftp/attrs_unix.go | 1 + vendor/github.com/pkg/sftp/client.go | 65 +- vendor/github.com/pkg/sftp/conn.go | 12 +- vendor/github.com/pkg/sftp/debug.go | 1 + vendor/github.com/pkg/sftp/fuzz.go | 1 + .../internal/encoding/ssh/filexfer/attrs.go | 117 +- .../internal/encoding/ssh/filexfer/buffer.go | 153 +- .../encoding/ssh/filexfer/extended_packets.go | 7 +- .../encoding/ssh/filexfer/extensions.go | 13 +- .../encoding/ssh/filexfer/filexfer.go | 4 +- .../sftp/internal/encoding/ssh/filexfer/fx.go | 18 +- .../internal/encoding/ssh/filexfer/fxp.go | 57 +- .../encoding/ssh/filexfer/handle_packets.go | 67 +- .../encoding/ssh/filexfer/init_packets.go | 12 +- .../encoding/ssh/filexfer/open_packets.go | 17 +- .../internal/encoding/ssh/filexfer/packets.go | 80 +- .../encoding/ssh/filexfer/path_packets.go | 72 +- .../encoding/ssh/filexfer/permissions.go | 2 +- .../encoding/ssh/filexfer/response_packets.go | 57 +- vendor/github.com/pkg/sftp/ls_formatting.go | 7 + vendor/github.com/pkg/sftp/ls_plan9.go | 1 + vendor/github.com/pkg/sftp/ls_stub.go | 1 + vendor/github.com/pkg/sftp/ls_unix.go | 1 + vendor/github.com/pkg/sftp/packet-manager.go | 4 +- vendor/github.com/pkg/sftp/packet-typing.go | 2 +- vendor/github.com/pkg/sftp/packet.go | 25 +- vendor/github.com/pkg/sftp/release.go | 1 + vendor/github.com/pkg/sftp/request-example.go | 41 +- .../github.com/pkg/sftp/request-interfaces.go | 48 +- vendor/github.com/pkg/sftp/request-plan9.go | 20 +- vendor/github.com/pkg/sftp/request-readme.md | 2 +- vendor/github.com/pkg/sftp/request-server.go | 17 +- vendor/github.com/pkg/sftp/request-unix.go | 5 +- vendor/github.com/pkg/sftp/request.go | 25 +- vendor/github.com/pkg/sftp/request_windows.go | 31 - vendor/github.com/pkg/sftp/server.go | 62 +- vendor/github.com/pkg/sftp/server_plan9.go | 27 + .../pkg/sftp/server_statvfs_impl.go | 1 + .../pkg/sftp/server_statvfs_linux.go | 1 + .../pkg/sftp/server_statvfs_stubs.go | 1 + vendor/github.com/pkg/sftp/server_unix.go | 16 + vendor/github.com/pkg/sftp/server_windows.go | 39 + vendor/github.com/pkg/sftp/sftp.go | 2 +- vendor/github.com/pkg/sftp/syscall_fixed.go | 1 + vendor/github.com/pkg/sftp/syscall_good.go | 4 +- .../client_golang/prometheus/counter.go | 26 +- .../client_golang/prometheus/desc.go | 28 +- .../prometheus/expvar_collector.go | 2 +- .../client_golang/prometheus/gauge.go | 8 +- .../client_golang/prometheus/histogram.go | 118 +- .../prometheus/internal/difflib.go | 2 +- .../client_golang/prometheus/labels.go | 58 +- .../client_golang/prometheus/metric.go | 3 + .../prometheus/promhttp/instrument_server.go | 9 +- .../client_golang/prometheus/registry.go | 6 +- .../client_golang/prometheus/summary.go | 41 +- .../client_golang/prometheus/value.go | 55 +- .../client_golang/prometheus/vec.go | 106 +- .../prometheus/client_model/go/metrics.pb.go | 350 +- .../prometheus/procfs/.golangci.yml | 3 + .../prometheus/procfs/Makefile.common | 8 +- vendor/github.com/prometheus/procfs/README.md | 4 +- vendor/github.com/prometheus/procfs/arp.go | 6 +- .../github.com/prometheus/procfs/buddyinfo.go | 6 +- .../github.com/prometheus/procfs/cpuinfo.go | 17 +- vendor/github.com/prometheus/procfs/crypto.go | 7 +- vendor/github.com/prometheus/procfs/fs.go | 8 +- .../prometheus/procfs/fs_statfs_notype.go | 4 +- .../prometheus/procfs/fs_statfs_type.go | 4 +- .../github.com/prometheus/procfs/fscache.go | 6 +- vendor/github.com/prometheus/procfs/ipvs.go | 7 +- .../github.com/prometheus/procfs/loadavg.go | 4 +- vendor/github.com/prometheus/procfs/mdstat.go | 36 +- .../github.com/prometheus/procfs/meminfo.go | 4 +- .../github.com/prometheus/procfs/mountinfo.go | 10 +- .../prometheus/procfs/mountstats.go | 32 +- .../prometheus/procfs/net_conntrackstat.go | 7 +- .../prometheus/procfs/net_ip_socket.go | 32 +- .../prometheus/procfs/net_protocols.go | 4 +- .../github.com/prometheus/procfs/net_route.go | 143 + .../prometheus/procfs/net_sockstat.go | 9 +- .../prometheus/procfs/net_softnet.go | 4 +- .../github.com/prometheus/procfs/net_unix.go | 16 +- .../prometheus/procfs/net_wireless.go | 28 +- .../github.com/prometheus/procfs/net_xfrm.go | 2 +- vendor/github.com/prometheus/procfs/proc.go | 17 +- .../prometheus/procfs/proc_cgroup.go | 4 +- .../prometheus/procfs/proc_cgroups.go | 8 +- .../prometheus/procfs/proc_fdinfo.go | 2 +- .../prometheus/procfs/proc_interrupts.go | 2 +- .../prometheus/procfs/proc_limits.go | 4 +- .../github.com/prometheus/procfs/proc_maps.go | 8 +- .../prometheus/procfs/proc_netstat.go | 4 +- .../github.com/prometheus/procfs/proc_ns.go | 6 +- .../github.com/prometheus/procfs/proc_psi.go | 6 +- .../prometheus/procfs/proc_smaps.go | 4 +- .../github.com/prometheus/procfs/proc_snmp.go | 4 +- .../github.com/prometheus/procfs/proc_stat.go | 2 +- .../github.com/prometheus/procfs/proc_sys.go | 2 +- vendor/github.com/prometheus/procfs/slab.go | 2 +- .../github.com/prometheus/procfs/softirqs.go | 24 +- vendor/github.com/prometheus/procfs/stat.go | 28 +- vendor/github.com/prometheus/procfs/swaps.go | 8 +- vendor/github.com/prometheus/procfs/thread.go | 8 +- vendor/github.com/prometheus/procfs/vm.go | 2 +- .../github.com/prometheus/procfs/zoneinfo.go | 4 +- .../go-securesystemslib/LICENSE | 21 + .../encrypted/encrypted.go | 102 +- .../fulcio/pkg/certificate/extensions.go | 44 +- .../sigstore/pkg/cryptoutils/privatekey.go | 2 +- .../sigstore/pkg/signature/payload/payload.go | 2 +- vendor/github.com/spf13/cobra/.golangci.yml | 8 +- vendor/github.com/spf13/cobra/README.md | 8 +- vendor/github.com/spf13/cobra/active_help.go | 10 +- vendor/github.com/spf13/cobra/active_help.md | 157 - .../spf13/cobra/bash_completions.go | 2 +- .../spf13/cobra/bash_completions.md | 93 - .../spf13/cobra/bash_completionsV2.go | 2 +- vendor/github.com/spf13/cobra/cobra.go | 13 +- vendor/github.com/spf13/cobra/command.go | 69 +- vendor/github.com/spf13/cobra/completions.go | 29 +- .../spf13/cobra/fish_completions.go | 2 +- .../spf13/cobra/fish_completions.md | 4 - vendor/github.com/spf13/cobra/flag_groups.go | 68 +- .../spf13/cobra/powershell_completions.go | 6 +- .../spf13/cobra/powershell_completions.md | 3 - .../spf13/cobra/projects_using_cobra.md | 64 - .../spf13/cobra/shell_completions.md | 576 - vendor/github.com/spf13/cobra/user_guide.md | 726 - .../github.com/spf13/cobra/zsh_completions.md | 48 - .../sylabs/sif/v2/pkg/sif/create.go | 126 +- .../sylabs/sif/v2/pkg/sif/descriptor.go | 54 + .../sylabs/sif/v2/pkg/sif/descriptor_input.go | 10 +- .../sylabs/sif/v2/pkg/sif/select.go | 14 +- .../github.com/sylabs/sif/v2/pkg/sif/sif.go | 6 + .../theupdateframework/go-tuf/LICENSE | 27 - .../github.com/vbauerster/mpb/v8/CONTRIBUTING | 15 + vendor/github.com/vbauerster/mpb/v8/bar.go | 103 +- .../vbauerster/mpb/v8/bar_filler.go | 8 - .../vbauerster/mpb/v8/bar_filler_bar.go | 314 +- .../vbauerster/mpb/v8/bar_filler_nop.go | 10 +- .../vbauerster/mpb/v8/bar_filler_spinner.go | 65 +- .../vbauerster/mpb/v8/bar_option.go | 11 +- .../vbauerster/mpb/v8/container_option.go | 6 +- .../github.com/vbauerster/mpb/v8/decor/any.go | 13 +- .../vbauerster/mpb/v8/decor/decorator.go | 50 +- .../github.com/vbauerster/mpb/v8/decor/eta.go | 8 +- .../vbauerster/mpb/v8/decor/merge.go | 111 - .../vbauerster/mpb/v8/decor/meta.go | 34 + .../vbauerster/mpb/v8/decor/on_abort.go | 62 +- .../mpb/v8/decor/on_compete_or_on_abort.go | 21 + .../vbauerster/mpb/v8/decor/on_complete.go | 60 +- .../vbauerster/mpb/v8/decor/speed.go | 8 +- .../vbauerster/mpb/v8/decor/spinner.go | 4 +- .../vbauerster/mpb/v8/heap_manager.go | 27 +- .../vbauerster/mpb/v8/priority_queue.go | 15 +- .../github.com/vbauerster/mpb/v8/progress.go | 87 +- vendor/go.etcd.io/bbolt/bolt_openbsd.go | 15 +- vendor/go.etcd.io/bbolt/db.go | 46 +- .../google.golang.org/grpc/otelgrpc/config.go | 5 +- .../google.golang.org/grpc/otelgrpc/doc.go | 45 + .../grpc/otelgrpc/interceptor.go | 11 +- .../grpc/otelgrpc/stats_handler.go | 187 + .../grpc/otelgrpc/version.go | 2 +- .../otel/exporters/otlp/otlptrace/version.go | 2 +- .../x/crypto/argon2/blamka_amd64.go | 1 - .../golang.org/x/crypto/argon2/blamka_amd64.s | 1 - .../golang.org/x/crypto/argon2/blamka_ref.go | 1 - .../x/crypto/blake2b/blake2bAVX2_amd64.go | 1 - .../x/crypto/blake2b/blake2bAVX2_amd64.s | 1 - .../x/crypto/blake2b/blake2b_amd64.go | 1 - .../x/crypto/blake2b/blake2b_amd64.s | 1 - .../x/crypto/blake2b/blake2b_ref.go | 1 - .../golang.org/x/crypto/blake2b/register.go | 1 - .../x/crypto/chacha20/chacha_arm64.go | 1 - .../x/crypto/chacha20/chacha_arm64.s | 1 - .../x/crypto/chacha20/chacha_noasm.go | 1 - .../x/crypto/chacha20/chacha_ppc64le.go | 1 - .../x/crypto/chacha20/chacha_ppc64le.s | 1 - .../x/crypto/chacha20/chacha_s390x.go | 1 - .../x/crypto/chacha20/chacha_s390x.s | 1 - .../curve25519/internal/field/fe_amd64.go | 1 - .../curve25519/internal/field/fe_amd64.s | 1 - .../internal/field/fe_amd64_noasm.go | 1 - .../curve25519/internal/field/fe_arm64.go | 1 - .../curve25519/internal/field/fe_arm64.s | 1 - .../internal/field/fe_arm64_noasm.go | 1 - vendor/golang.org/x/crypto/hkdf/hkdf.go | 4 +- .../x/crypto/internal/alias/alias.go | 1 - .../x/crypto/internal/alias/alias_purego.go | 1 - .../x/crypto/internal/poly1305/bits_compat.go | 1 - .../x/crypto/internal/poly1305/bits_go1.13.go | 1 - .../x/crypto/internal/poly1305/mac_noasm.go | 1 - .../x/crypto/internal/poly1305/sum_amd64.go | 1 - .../x/crypto/internal/poly1305/sum_amd64.s | 1 - .../x/crypto/internal/poly1305/sum_ppc64le.go | 1 - .../x/crypto/internal/poly1305/sum_ppc64le.s | 1 - .../x/crypto/internal/poly1305/sum_s390x.go | 1 - .../x/crypto/internal/poly1305/sum_s390x.s | 1 - .../x/crypto/salsa20/salsa/salsa20_amd64.go | 1 - .../x/crypto/salsa20/salsa/salsa20_amd64.s | 1 - .../x/crypto/salsa20/salsa/salsa20_noasm.go | 1 - .../x/crypto/sha3/hashes_generic.go | 1 - vendor/golang.org/x/crypto/sha3/keccakf.go | 1 - .../golang.org/x/crypto/sha3/keccakf_amd64.go | 1 - .../golang.org/x/crypto/sha3/keccakf_amd64.s | 1 - vendor/golang.org/x/crypto/sha3/register.go | 1 - vendor/golang.org/x/crypto/sha3/sha3_s390x.go | 1 - vendor/golang.org/x/crypto/sha3/sha3_s390x.s | 1 - .../golang.org/x/crypto/sha3/shake_generic.go | 1 - vendor/golang.org/x/crypto/sha3/xor.go | 1 - .../golang.org/x/crypto/sha3/xor_unaligned.go | 2 - .../golang.org/x/crypto/ssh/agent/client.go | 13 +- .../golang.org/x/crypto/ssh/agent/server.go | 2 +- vendor/golang.org/x/crypto/ssh/common.go | 3 - vendor/golang.org/x/crypto/ssh/handshake.go | 7 + vendor/golang.org/x/crypto/ssh/keys.go | 19 +- vendor/golang.org/x/crypto/ssh/server.go | 20 +- vendor/golang.org/x/exp/slices/cmp.go | 44 + vendor/golang.org/x/exp/slices/slices.go | 353 +- vendor/golang.org/x/exp/slices/sort.go | 115 +- .../slices/{zsortfunc.go => zsortanyfunc.go} | 154 +- .../golang.org/x/exp/slices/zsortordered.go | 34 +- vendor/golang.org/x/net/context/go17.go | 1 - vendor/golang.org/x/net/context/go19.go | 1 - vendor/golang.org/x/net/context/pre_go17.go | 1 - vendor/golang.org/x/net/context/pre_go19.go | 1 - vendor/golang.org/x/net/http2/databuffer.go | 59 +- vendor/golang.org/x/net/http2/go111.go | 30 - vendor/golang.org/x/net/http2/go115.go | 27 - vendor/golang.org/x/net/http2/go118.go | 17 - vendor/golang.org/x/net/http2/not_go111.go | 21 - vendor/golang.org/x/net/http2/not_go115.go | 31 - vendor/golang.org/x/net/http2/not_go118.go | 17 - vendor/golang.org/x/net/http2/server.go | 24 +- vendor/golang.org/x/net/http2/transport.go | 33 +- vendor/golang.org/x/net/idna/go118.go | 1 - vendor/golang.org/x/net/idna/idna10.0.0.go | 1 - vendor/golang.org/x/net/idna/idna9.0.0.go | 1 - vendor/golang.org/x/net/idna/pre_go118.go | 1 - vendor/golang.org/x/net/idna/tables10.0.0.go | 1 - vendor/golang.org/x/net/idna/tables11.0.0.go | 1 - vendor/golang.org/x/net/idna/tables12.0.0.go | 1 - vendor/golang.org/x/net/idna/tables13.0.0.go | 1 - vendor/golang.org/x/net/idna/tables15.0.0.go | 1 - vendor/golang.org/x/net/idna/tables9.0.0.go | 1 - vendor/golang.org/x/net/idna/trie12.0.0.go | 1 - vendor/golang.org/x/net/idna/trie13.0.0.go | 1 - vendor/golang.org/x/oauth2/deviceauth.go | 198 + .../x/oauth2/internal/client_appengine.go | 1 - vendor/golang.org/x/oauth2/internal/token.go | 70 +- vendor/golang.org/x/oauth2/oauth2.go | 33 +- vendor/golang.org/x/oauth2/pkce.go | 68 + vendor/golang.org/x/oauth2/token.go | 2 +- vendor/golang.org/x/sync/errgroup/go120.go | 1 - .../golang.org/x/sync/errgroup/pre_go120.go | 1 - vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s | 1 - vendor/golang.org/x/sys/cpu/cpu_aix.go | 1 - vendor/golang.org/x/sys/cpu/cpu_arm64.s | 1 - vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go | 1 - vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go | 1 - vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 2 - .../golang.org/x/sys/cpu/cpu_gccgo_arm64.go | 1 - .../golang.org/x/sys/cpu/cpu_gccgo_s390x.go | 1 - vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c | 2 - vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go | 2 - vendor/golang.org/x/sys/cpu/cpu_linux.go | 1 - .../golang.org/x/sys/cpu/cpu_linux_mips64x.go | 2 - .../golang.org/x/sys/cpu/cpu_linux_noinit.go | 1 - .../golang.org/x/sys/cpu/cpu_linux_ppc64x.go | 2 - vendor/golang.org/x/sys/cpu/cpu_loong64.go | 1 - vendor/golang.org/x/sys/cpu/cpu_mips64x.go | 1 - vendor/golang.org/x/sys/cpu/cpu_mipsx.go | 1 - vendor/golang.org/x/sys/cpu/cpu_other_arm.go | 1 - .../golang.org/x/sys/cpu/cpu_other_arm64.go | 1 - .../golang.org/x/sys/cpu/cpu_other_mips64x.go | 2 - .../golang.org/x/sys/cpu/cpu_other_ppc64x.go | 3 - .../golang.org/x/sys/cpu/cpu_other_riscv64.go | 1 - vendor/golang.org/x/sys/cpu/cpu_ppc64x.go | 1 - vendor/golang.org/x/sys/cpu/cpu_riscv64.go | 1 - vendor/golang.org/x/sys/cpu/cpu_s390x.s | 1 - vendor/golang.org/x/sys/cpu/cpu_wasm.go | 1 - vendor/golang.org/x/sys/cpu/cpu_x86.go | 1 - vendor/golang.org/x/sys/cpu/cpu_x86.s | 2 - vendor/golang.org/x/sys/cpu/endian_big.go | 1 - vendor/golang.org/x/sys/cpu/endian_little.go | 1 - .../x/sys/cpu/proc_cpuinfo_linux.go | 1 - .../x/sys/cpu/runtime_auxv_go121.go | 1 - .../golang.org/x/sys/cpu/syscall_aix_gccgo.go | 1 - .../x/sys/cpu/syscall_aix_ppc64_gc.go | 1 - .../golang.org/x/sys/execabs/execabs_go118.go | 1 - .../golang.org/x/sys/execabs/execabs_go119.go | 1 - .../golang.org/x/sys/plan9/pwd_go15_plan9.go | 1 - vendor/golang.org/x/sys/plan9/pwd_plan9.go | 1 - vendor/golang.org/x/sys/plan9/race.go | 1 - vendor/golang.org/x/sys/plan9/race0.go | 1 - vendor/golang.org/x/sys/plan9/str.go | 1 - vendor/golang.org/x/sys/plan9/syscall.go | 1 - .../x/sys/plan9/zsyscall_plan9_386.go | 1 - .../x/sys/plan9/zsyscall_plan9_amd64.go | 1 - .../x/sys/plan9/zsyscall_plan9_arm.go | 1 - vendor/golang.org/x/sys/unix/aliases.go | 2 - vendor/golang.org/x/sys/unix/asm_aix_ppc64.s | 1 - vendor/golang.org/x/sys/unix/asm_bsd_386.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_amd64.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_arm.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_arm64.s | 2 - vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s | 2 - .../golang.org/x/sys/unix/asm_bsd_riscv64.s | 2 - vendor/golang.org/x/sys/unix/asm_linux_386.s | 1 - .../golang.org/x/sys/unix/asm_linux_amd64.s | 1 - vendor/golang.org/x/sys/unix/asm_linux_arm.s | 1 - .../golang.org/x/sys/unix/asm_linux_arm64.s | 3 - .../golang.org/x/sys/unix/asm_linux_loong64.s | 3 - .../golang.org/x/sys/unix/asm_linux_mips64x.s | 3 - .../golang.org/x/sys/unix/asm_linux_mipsx.s | 3 - .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 3 - .../golang.org/x/sys/unix/asm_linux_riscv64.s | 2 - .../golang.org/x/sys/unix/asm_linux_s390x.s | 3 - .../x/sys/unix/asm_openbsd_mips64.s | 1 - .../golang.org/x/sys/unix/asm_solaris_amd64.s | 1 - vendor/golang.org/x/sys/unix/asm_zos_s390x.s | 3 - vendor/golang.org/x/sys/unix/cap_freebsd.go | 1 - vendor/golang.org/x/sys/unix/constants.go | 1 - vendor/golang.org/x/sys/unix/dev_aix_ppc.go | 1 - vendor/golang.org/x/sys/unix/dev_aix_ppc64.go | 1 - vendor/golang.org/x/sys/unix/dev_zos.go | 1 - vendor/golang.org/x/sys/unix/dirent.go | 1 - vendor/golang.org/x/sys/unix/endian_big.go | 1 - vendor/golang.org/x/sys/unix/endian_little.go | 1 - vendor/golang.org/x/sys/unix/env_unix.go | 1 - vendor/golang.org/x/sys/unix/epoll_zos.go | 1 - vendor/golang.org/x/sys/unix/fcntl.go | 1 - .../x/sys/unix/fcntl_linux_32bit.go | 1 - vendor/golang.org/x/sys/unix/fdset.go | 1 - vendor/golang.org/x/sys/unix/fstatfs_zos.go | 1 - vendor/golang.org/x/sys/unix/gccgo.go | 1 - vendor/golang.org/x/sys/unix/gccgo_c.c | 1 - .../x/sys/unix/gccgo_linux_amd64.go | 1 - vendor/golang.org/x/sys/unix/ifreq_linux.go | 1 - vendor/golang.org/x/sys/unix/ioctl_signed.go | 1 - .../golang.org/x/sys/unix/ioctl_unsigned.go | 1 - vendor/golang.org/x/sys/unix/ioctl_zos.go | 1 - vendor/golang.org/x/sys/unix/mkerrors.sh | 1 - vendor/golang.org/x/sys/unix/mmap_nomremap.go | 1 - vendor/golang.org/x/sys/unix/mremap.go | 1 - vendor/golang.org/x/sys/unix/pagesize_unix.go | 1 - .../golang.org/x/sys/unix/pledge_openbsd.go | 92 +- vendor/golang.org/x/sys/unix/ptrace_darwin.go | 1 - vendor/golang.org/x/sys/unix/ptrace_ios.go | 1 - vendor/golang.org/x/sys/unix/race.go | 1 - vendor/golang.org/x/sys/unix/race0.go | 1 - .../x/sys/unix/readdirent_getdents.go | 1 - .../x/sys/unix/readdirent_getdirentries.go | 1 - vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 1 - .../x/sys/unix/sockcmsg_unix_other.go | 1 - vendor/golang.org/x/sys/unix/syscall.go | 1 - vendor/golang.org/x/sys/unix/syscall_aix.go | 4 +- .../golang.org/x/sys/unix/syscall_aix_ppc.go | 1 - .../x/sys/unix/syscall_aix_ppc64.go | 1 - vendor/golang.org/x/sys/unix/syscall_bsd.go | 1 - .../x/sys/unix/syscall_darwin_amd64.go | 1 - .../x/sys/unix/syscall_darwin_arm64.go | 1 - .../x/sys/unix/syscall_darwin_libSystem.go | 1 - .../x/sys/unix/syscall_dragonfly_amd64.go | 1 - .../x/sys/unix/syscall_freebsd_386.go | 1 - .../x/sys/unix/syscall_freebsd_amd64.go | 1 - .../x/sys/unix/syscall_freebsd_arm.go | 1 - .../x/sys/unix/syscall_freebsd_arm64.go | 1 - .../x/sys/unix/syscall_freebsd_riscv64.go | 1 - vendor/golang.org/x/sys/unix/syscall_hurd.go | 1 - .../golang.org/x/sys/unix/syscall_hurd_386.go | 1 - .../golang.org/x/sys/unix/syscall_illumos.go | 1 - vendor/golang.org/x/sys/unix/syscall_linux.go | 5 +- .../x/sys/unix/syscall_linux_386.go | 1 - .../x/sys/unix/syscall_linux_alarm.go | 2 - .../x/sys/unix/syscall_linux_amd64.go | 1 - .../x/sys/unix/syscall_linux_amd64_gc.go | 1 - .../x/sys/unix/syscall_linux_arm.go | 1 - .../x/sys/unix/syscall_linux_arm64.go | 1 - .../golang.org/x/sys/unix/syscall_linux_gc.go | 1 - .../x/sys/unix/syscall_linux_gc_386.go | 1 - .../x/sys/unix/syscall_linux_gc_arm.go | 1 - .../x/sys/unix/syscall_linux_gccgo_386.go | 1 - .../x/sys/unix/syscall_linux_gccgo_arm.go | 1 - .../x/sys/unix/syscall_linux_loong64.go | 1 - .../x/sys/unix/syscall_linux_mips64x.go | 2 - .../x/sys/unix/syscall_linux_mipsx.go | 2 - .../x/sys/unix/syscall_linux_ppc.go | 1 - .../x/sys/unix/syscall_linux_ppc64x.go | 2 - .../x/sys/unix/syscall_linux_riscv64.go | 1 - .../x/sys/unix/syscall_linux_s390x.go | 1 - .../x/sys/unix/syscall_linux_sparc64.go | 1 - .../x/sys/unix/syscall_netbsd_386.go | 1 - .../x/sys/unix/syscall_netbsd_amd64.go | 1 - .../x/sys/unix/syscall_netbsd_arm.go | 1 - .../x/sys/unix/syscall_netbsd_arm64.go | 1 - .../golang.org/x/sys/unix/syscall_openbsd.go | 14 +- .../x/sys/unix/syscall_openbsd_386.go | 1 - .../x/sys/unix/syscall_openbsd_amd64.go | 1 - .../x/sys/unix/syscall_openbsd_arm.go | 1 - .../x/sys/unix/syscall_openbsd_arm64.go | 1 - .../x/sys/unix/syscall_openbsd_libc.go | 1 - .../x/sys/unix/syscall_openbsd_ppc64.go | 1 - .../x/sys/unix/syscall_openbsd_riscv64.go | 1 - .../golang.org/x/sys/unix/syscall_solaris.go | 3 +- .../x/sys/unix/syscall_solaris_amd64.go | 1 - vendor/golang.org/x/sys/unix/syscall_unix.go | 1 - .../golang.org/x/sys/unix/syscall_unix_gc.go | 2 - .../x/sys/unix/syscall_unix_gc_ppc64x.go | 3 - .../x/sys/unix/syscall_zos_s390x.go | 1 - vendor/golang.org/x/sys/unix/sysvshm_linux.go | 1 - vendor/golang.org/x/sys/unix/sysvshm_unix.go | 1 - .../x/sys/unix/sysvshm_unix_other.go | 1 - vendor/golang.org/x/sys/unix/timestruct.go | 1 - .../golang.org/x/sys/unix/unveil_openbsd.go | 41 +- vendor/golang.org/x/sys/unix/xattr_bsd.go | 1 - .../golang.org/x/sys/unix/zerrors_aix_ppc.go | 1 - .../x/sys/unix/zerrors_aix_ppc64.go | 1 - .../x/sys/unix/zerrors_darwin_amd64.go | 1 - .../x/sys/unix/zerrors_darwin_arm64.go | 1 - .../x/sys/unix/zerrors_dragonfly_amd64.go | 1 - .../x/sys/unix/zerrors_freebsd_386.go | 1 - .../x/sys/unix/zerrors_freebsd_amd64.go | 1 - .../x/sys/unix/zerrors_freebsd_arm.go | 1 - .../x/sys/unix/zerrors_freebsd_arm64.go | 1 - .../x/sys/unix/zerrors_freebsd_riscv64.go | 1 - vendor/golang.org/x/sys/unix/zerrors_linux.go | 14 +- .../x/sys/unix/zerrors_linux_386.go | 1 - .../x/sys/unix/zerrors_linux_amd64.go | 1 - .../x/sys/unix/zerrors_linux_arm.go | 1 - .../x/sys/unix/zerrors_linux_arm64.go | 1 - .../x/sys/unix/zerrors_linux_loong64.go | 2 +- .../x/sys/unix/zerrors_linux_mips.go | 1 - .../x/sys/unix/zerrors_linux_mips64.go | 1 - .../x/sys/unix/zerrors_linux_mips64le.go | 1 - .../x/sys/unix/zerrors_linux_mipsle.go | 1 - .../x/sys/unix/zerrors_linux_ppc.go | 1 - .../x/sys/unix/zerrors_linux_ppc64.go | 1 - .../x/sys/unix/zerrors_linux_ppc64le.go | 1 - .../x/sys/unix/zerrors_linux_riscv64.go | 4 +- .../x/sys/unix/zerrors_linux_s390x.go | 1 - .../x/sys/unix/zerrors_linux_sparc64.go | 1 - .../x/sys/unix/zerrors_netbsd_386.go | 1 - .../x/sys/unix/zerrors_netbsd_amd64.go | 1 - .../x/sys/unix/zerrors_netbsd_arm.go | 1 - .../x/sys/unix/zerrors_netbsd_arm64.go | 1 - .../x/sys/unix/zerrors_openbsd_386.go | 1 - .../x/sys/unix/zerrors_openbsd_amd64.go | 1 - .../x/sys/unix/zerrors_openbsd_arm.go | 1 - .../x/sys/unix/zerrors_openbsd_arm64.go | 1 - .../x/sys/unix/zerrors_openbsd_mips64.go | 1 - .../x/sys/unix/zerrors_openbsd_ppc64.go | 1 - .../x/sys/unix/zerrors_openbsd_riscv64.go | 1 - .../x/sys/unix/zerrors_solaris_amd64.go | 1 - .../x/sys/unix/zerrors_zos_s390x.go | 1 - .../x/sys/unix/zptrace_armnn_linux.go | 2 - .../x/sys/unix/zptrace_mipsnn_linux.go | 2 - .../x/sys/unix/zptrace_mipsnnle_linux.go | 2 - .../x/sys/unix/zptrace_x86_linux.go | 2 - .../golang.org/x/sys/unix/zsyscall_aix_ppc.go | 1 - .../x/sys/unix/zsyscall_aix_ppc64.go | 1 - .../x/sys/unix/zsyscall_aix_ppc64_gc.go | 1 - .../x/sys/unix/zsyscall_aix_ppc64_gccgo.go | 1 - .../x/sys/unix/zsyscall_darwin_amd64.go | 1 - .../x/sys/unix/zsyscall_darwin_arm64.go | 1 - .../x/sys/unix/zsyscall_dragonfly_amd64.go | 1 - .../x/sys/unix/zsyscall_freebsd_386.go | 1 - .../x/sys/unix/zsyscall_freebsd_amd64.go | 1 - .../x/sys/unix/zsyscall_freebsd_arm.go | 1 - .../x/sys/unix/zsyscall_freebsd_arm64.go | 1 - .../x/sys/unix/zsyscall_freebsd_riscv64.go | 1 - .../x/sys/unix/zsyscall_illumos_amd64.go | 1 - .../golang.org/x/sys/unix/zsyscall_linux.go | 11 +- .../x/sys/unix/zsyscall_linux_386.go | 1 - .../x/sys/unix/zsyscall_linux_amd64.go | 1 - .../x/sys/unix/zsyscall_linux_arm.go | 1 - .../x/sys/unix/zsyscall_linux_arm64.go | 1 - .../x/sys/unix/zsyscall_linux_loong64.go | 1 - .../x/sys/unix/zsyscall_linux_mips.go | 1 - .../x/sys/unix/zsyscall_linux_mips64.go | 1 - .../x/sys/unix/zsyscall_linux_mips64le.go | 1 - .../x/sys/unix/zsyscall_linux_mipsle.go | 1 - .../x/sys/unix/zsyscall_linux_ppc.go | 1 - .../x/sys/unix/zsyscall_linux_ppc64.go | 1 - .../x/sys/unix/zsyscall_linux_ppc64le.go | 1 - .../x/sys/unix/zsyscall_linux_riscv64.go | 1 - .../x/sys/unix/zsyscall_linux_s390x.go | 1 - .../x/sys/unix/zsyscall_linux_sparc64.go | 1 - .../x/sys/unix/zsyscall_netbsd_386.go | 1 - .../x/sys/unix/zsyscall_netbsd_amd64.go | 1 - .../x/sys/unix/zsyscall_netbsd_arm.go | 1 - .../x/sys/unix/zsyscall_netbsd_arm64.go | 1 - .../x/sys/unix/zsyscall_openbsd_386.go | 46 +- .../x/sys/unix/zsyscall_openbsd_386.s | 15 + .../x/sys/unix/zsyscall_openbsd_amd64.go | 46 +- .../x/sys/unix/zsyscall_openbsd_amd64.s | 15 + .../x/sys/unix/zsyscall_openbsd_arm.go | 46 +- .../x/sys/unix/zsyscall_openbsd_arm.s | 15 + .../x/sys/unix/zsyscall_openbsd_arm64.go | 46 +- .../x/sys/unix/zsyscall_openbsd_arm64.s | 15 + .../x/sys/unix/zsyscall_openbsd_mips64.go | 46 +- .../x/sys/unix/zsyscall_openbsd_mips64.s | 15 + .../x/sys/unix/zsyscall_openbsd_ppc64.go | 46 +- .../x/sys/unix/zsyscall_openbsd_ppc64.s | 18 + .../x/sys/unix/zsyscall_openbsd_riscv64.go | 46 +- .../x/sys/unix/zsyscall_openbsd_riscv64.s | 15 + .../x/sys/unix/zsyscall_solaris_amd64.go | 1 - .../x/sys/unix/zsyscall_zos_s390x.go | 1 - .../x/sys/unix/zsysctl_openbsd_386.go | 1 - .../x/sys/unix/zsysctl_openbsd_amd64.go | 1 - .../x/sys/unix/zsysctl_openbsd_arm.go | 1 - .../x/sys/unix/zsysctl_openbsd_arm64.go | 1 - .../x/sys/unix/zsysctl_openbsd_mips64.go | 1 - .../x/sys/unix/zsysctl_openbsd_ppc64.go | 1 - .../x/sys/unix/zsysctl_openbsd_riscv64.go | 1 - .../x/sys/unix/zsysnum_darwin_amd64.go | 1 - .../x/sys/unix/zsysnum_darwin_arm64.go | 1 - .../x/sys/unix/zsysnum_dragonfly_amd64.go | 1 - .../x/sys/unix/zsysnum_freebsd_386.go | 1 - .../x/sys/unix/zsysnum_freebsd_amd64.go | 1 - .../x/sys/unix/zsysnum_freebsd_arm.go | 1 - .../x/sys/unix/zsysnum_freebsd_arm64.go | 1 - .../x/sys/unix/zsysnum_freebsd_riscv64.go | 1 - .../x/sys/unix/zsysnum_linux_386.go | 2 +- .../x/sys/unix/zsysnum_linux_amd64.go | 3 +- .../x/sys/unix/zsysnum_linux_arm.go | 2 +- .../x/sys/unix/zsysnum_linux_arm64.go | 2 +- .../x/sys/unix/zsysnum_linux_loong64.go | 2 +- .../x/sys/unix/zsysnum_linux_mips.go | 2 +- .../x/sys/unix/zsysnum_linux_mips64.go | 2 +- .../x/sys/unix/zsysnum_linux_mips64le.go | 2 +- .../x/sys/unix/zsysnum_linux_mipsle.go | 2 +- .../x/sys/unix/zsysnum_linux_ppc.go | 2 +- .../x/sys/unix/zsysnum_linux_ppc64.go | 2 +- .../x/sys/unix/zsysnum_linux_ppc64le.go | 2 +- .../x/sys/unix/zsysnum_linux_riscv64.go | 2 +- .../x/sys/unix/zsysnum_linux_s390x.go | 2 +- .../x/sys/unix/zsysnum_linux_sparc64.go | 2 +- .../x/sys/unix/zsysnum_netbsd_386.go | 1 - .../x/sys/unix/zsysnum_netbsd_amd64.go | 1 - .../x/sys/unix/zsysnum_netbsd_arm.go | 1 - .../x/sys/unix/zsysnum_netbsd_arm64.go | 1 - .../x/sys/unix/zsysnum_openbsd_386.go | 1 - .../x/sys/unix/zsysnum_openbsd_amd64.go | 1 - .../x/sys/unix/zsysnum_openbsd_arm.go | 1 - .../x/sys/unix/zsysnum_openbsd_arm64.go | 1 - .../x/sys/unix/zsysnum_openbsd_mips64.go | 1 - .../x/sys/unix/zsysnum_openbsd_ppc64.go | 1 - .../x/sys/unix/zsysnum_openbsd_riscv64.go | 1 - .../x/sys/unix/zsysnum_zos_s390x.go | 1 - .../golang.org/x/sys/unix/ztypes_aix_ppc.go | 1 - .../golang.org/x/sys/unix/ztypes_aix_ppc64.go | 1 - .../x/sys/unix/ztypes_darwin_amd64.go | 1 - .../x/sys/unix/ztypes_darwin_arm64.go | 1 - .../x/sys/unix/ztypes_dragonfly_amd64.go | 1 - .../x/sys/unix/ztypes_freebsd_386.go | 1 - .../x/sys/unix/ztypes_freebsd_amd64.go | 1 - .../x/sys/unix/ztypes_freebsd_arm.go | 1 - .../x/sys/unix/ztypes_freebsd_arm64.go | 1 - .../x/sys/unix/ztypes_freebsd_riscv64.go | 1 - vendor/golang.org/x/sys/unix/ztypes_linux.go | 13 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 1 - .../x/sys/unix/ztypes_linux_amd64.go | 1 - .../golang.org/x/sys/unix/ztypes_linux_arm.go | 1 - .../x/sys/unix/ztypes_linux_arm64.go | 1 - .../x/sys/unix/ztypes_linux_loong64.go | 1 - .../x/sys/unix/ztypes_linux_mips.go | 1 - .../x/sys/unix/ztypes_linux_mips64.go | 1 - .../x/sys/unix/ztypes_linux_mips64le.go | 1 - .../x/sys/unix/ztypes_linux_mipsle.go | 1 - .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 1 - .../x/sys/unix/ztypes_linux_ppc64.go | 1 - .../x/sys/unix/ztypes_linux_ppc64le.go | 1 - .../x/sys/unix/ztypes_linux_riscv64.go | 1 - .../x/sys/unix/ztypes_linux_s390x.go | 1 - .../x/sys/unix/ztypes_linux_sparc64.go | 1 - .../x/sys/unix/ztypes_netbsd_386.go | 1 - .../x/sys/unix/ztypes_netbsd_amd64.go | 1 - .../x/sys/unix/ztypes_netbsd_arm.go | 1 - .../x/sys/unix/ztypes_netbsd_arm64.go | 1 - .../x/sys/unix/ztypes_openbsd_386.go | 1 - .../x/sys/unix/ztypes_openbsd_amd64.go | 1 - .../x/sys/unix/ztypes_openbsd_arm.go | 1 - .../x/sys/unix/ztypes_openbsd_arm64.go | 1 - .../x/sys/unix/ztypes_openbsd_mips64.go | 1 - .../x/sys/unix/ztypes_openbsd_ppc64.go | 1 - .../x/sys/unix/ztypes_openbsd_riscv64.go | 1 - .../x/sys/unix/ztypes_solaris_amd64.go | 1 - .../golang.org/x/sys/unix/ztypes_zos_s390x.go | 1 - vendor/golang.org/x/sys/windows/aliases.go | 1 - vendor/golang.org/x/sys/windows/empty.s | 1 - vendor/golang.org/x/sys/windows/eventlog.go | 1 - vendor/golang.org/x/sys/windows/mksyscall.go | 1 - vendor/golang.org/x/sys/windows/race.go | 1 - vendor/golang.org/x/sys/windows/race0.go | 1 - .../golang.org/x/sys/windows/registry/key.go | 1 - .../x/sys/windows/registry/mksyscall.go | 1 - .../x/sys/windows/registry/syscall.go | 1 - .../x/sys/windows/registry/value.go | 1 - vendor/golang.org/x/sys/windows/service.go | 1 - vendor/golang.org/x/sys/windows/str.go | 1 - vendor/golang.org/x/sys/windows/syscall.go | 1 - .../x/sys/windows/syscall_windows.go | 4 +- .../golang.org/x/sys/windows/types_windows.go | 28 +- .../x/sys/windows/zsyscall_windows.go | 9 + vendor/golang.org/x/term/term_unix.go | 1 - vendor/golang.org/x/term/term_unix_bsd.go | 1 - vendor/golang.org/x/term/term_unix_other.go | 1 - vendor/golang.org/x/term/term_unsupported.go | 1 - .../x/text/secure/bidirule/bidirule10.0.0.go | 1 - .../x/text/secure/bidirule/bidirule9.0.0.go | 1 - .../x/text/unicode/bidi/tables10.0.0.go | 1 - .../x/text/unicode/bidi/tables11.0.0.go | 1 - .../x/text/unicode/bidi/tables12.0.0.go | 1 - .../x/text/unicode/bidi/tables13.0.0.go | 1 - .../x/text/unicode/bidi/tables15.0.0.go | 1 - .../x/text/unicode/bidi/tables9.0.0.go | 1 - .../x/text/unicode/norm/tables10.0.0.go | 1 - .../x/text/unicode/norm/tables11.0.0.go | 1 - .../x/text/unicode/norm/tables12.0.0.go | 1 - .../x/text/unicode/norm/tables13.0.0.go | 1 - .../x/text/unicode/norm/tables15.0.0.go | 1 - .../x/text/unicode/norm/tables9.0.0.go | 1 - .../x/tools/cmd/stringer/stringer.go | 5 +- .../tools/go/internal/packagesdriver/sizes.go | 11 +- vendor/golang.org/x/tools/go/packages/doc.go | 2 +- .../golang.org/x/tools/go/packages/golist.go | 16 +- .../x/tools/go/packages/packages.go | 11 +- .../x/tools/go/types/objectpath/objectpath.go | 21 +- .../x/tools/internal/gcimporter/gcimporter.go | 3 +- .../x/tools/internal/typeparams/coretype.go | 8 +- .../x/tools/internal/typeparams/termlist.go | 2 +- .../x/tools/internal/typeparams/typeterm.go | 9 +- .../internal/typesinternal/objectpath.go | 24 + .../x/tools/internal/typesinternal/types.go | 16 - .../appengine/internal/api.go | 347 +- .../appengine/internal/api_classic.go | 29 +- .../appengine/internal/api_common.go | 50 +- .../appengine/internal/identity.go | 7 +- .../appengine/internal/identity_classic.go | 23 +- .../appengine/internal/identity_flex.go | 1 + .../appengine/internal/identity_vm.go | 20 +- .../appengine/internal/main.go | 1 + .../appengine/internal/main_vm.go | 3 +- .../appengine/internal/transaction.go | 10 +- .../appengine/urlfetch/urlfetch.go | 9 +- vendor/modules.txt | 181 +- vendor/sigs.k8s.io/yaml/LICENSE | 256 + vendor/sigs.k8s.io/yaml/OWNERS | 8 +- vendor/sigs.k8s.io/yaml/fields.go | 55 +- vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE | 201 + .../yaml/goyaml.v2/LICENSE.libyaml | 31 + vendor/sigs.k8s.io/yaml/goyaml.v2/NOTICE | 13 + vendor/sigs.k8s.io/yaml/goyaml.v2/OWNERS | 24 + vendor/sigs.k8s.io/yaml/goyaml.v2/README.md | 143 + vendor/sigs.k8s.io/yaml/goyaml.v2/apic.go | 744 + vendor/sigs.k8s.io/yaml/goyaml.v2/decode.go | 815 + vendor/sigs.k8s.io/yaml/goyaml.v2/emitterc.go | 1685 +++ vendor/sigs.k8s.io/yaml/goyaml.v2/encode.go | 390 + vendor/sigs.k8s.io/yaml/goyaml.v2/parserc.go | 1095 ++ vendor/sigs.k8s.io/yaml/goyaml.v2/readerc.go | 412 + vendor/sigs.k8s.io/yaml/goyaml.v2/resolve.go | 258 + vendor/sigs.k8s.io/yaml/goyaml.v2/scannerc.go | 2711 ++++ vendor/sigs.k8s.io/yaml/goyaml.v2/sorter.go | 113 + vendor/sigs.k8s.io/yaml/goyaml.v2/writerc.go | 26 + vendor/sigs.k8s.io/yaml/goyaml.v2/yaml.go | 478 + vendor/sigs.k8s.io/yaml/goyaml.v2/yamlh.go | 739 + .../yaml/goyaml.v2/yamlprivateh.go | 173 + vendor/sigs.k8s.io/yaml/yaml.go | 145 +- vendor/sigs.k8s.io/yaml/yaml_go110.go | 17 + .../container-device-interface/LICENSE | 201 + .../pkg/parser/parser.go | 212 + 1022 files changed, 36915 insertions(+), 14235 deletions(-) create mode 100644 vendor/github.com/Microsoft/hcsshim/internal/log/nopformatter.go create mode 100644 vendor/github.com/containerd/containerd/log/context_deprecated.go create mode 100644 vendor/github.com/containerd/log/.golangci.yml create mode 100644 vendor/github.com/containerd/log/LICENSE create mode 100644 vendor/github.com/containerd/log/README.md rename vendor/github.com/containerd/{containerd => }/log/context.go (98%) create mode 100644 vendor/github.com/containers/common/internal/attributedstring/slice.go create mode 100644 vendor/github.com/containers/common/libimage/define/manifests.go create mode 100644 vendor/github.com/containers/common/libimage/define/platform.go create mode 100644 vendor/github.com/containers/common/libimage/filter/filter.go create mode 100644 vendor/github.com/containers/common/libimage/platform/platform.go delete mode 100644 vendor/github.com/containers/common/pkg/cgroups/blkio.go delete mode 100644 vendor/github.com/containers/common/pkg/cgroups/cgroups.go delete mode 100644 vendor/github.com/containers/common/pkg/cgroups/cpu.go delete mode 100644 vendor/github.com/containers/common/pkg/cgroups/cpuset.go delete mode 100644 vendor/github.com/containers/common/pkg/cgroups/memory.go delete mode 100644 vendor/github.com/containers/common/pkg/cgroups/pids.go delete mode 100644 vendor/github.com/containers/common/pkg/cgroups/utils.go create mode 100644 vendor/github.com/containers/common/pkg/config/modules.go create mode 100644 vendor/github.com/containers/common/pkg/config/new.go delete mode 100644 vendor/github.com/containers/common/pkg/util/copy.go create mode 100644 vendor/github.com/containers/common/pkg/version/version.go create mode 100644 vendor/github.com/containers/image/v5/oci/layout/oci_delete.go delete mode 100644 vendor/github.com/containers/image/v5/pkg/blobinfocache/boltdb/boltdb.go create mode 100644 vendor/github.com/containers/image/v5/pkg/blobinfocache/sqlite/sqlite.go create mode 100644 vendor/github.com/containers/storage/pkg/chunked/dump/dump.go create mode 100644 vendor/github.com/distribution/reference/.gitignore create mode 100644 vendor/github.com/distribution/reference/.golangci.yml create mode 100644 vendor/github.com/distribution/reference/CODE-OF-CONDUCT.md create mode 100644 vendor/github.com/distribution/reference/CONTRIBUTING.md create mode 100644 vendor/github.com/distribution/reference/GOVERNANCE.md create mode 100644 vendor/github.com/distribution/reference/LICENSE create mode 100644 vendor/github.com/distribution/reference/MAINTAINERS create mode 100644 vendor/github.com/distribution/reference/Makefile create mode 100644 vendor/github.com/distribution/reference/README.md create mode 100644 vendor/github.com/distribution/reference/SECURITY.md create mode 100644 vendor/github.com/distribution/reference/distribution-logo.svg rename vendor/github.com/{docker => }/distribution/reference/helpers.go (94%) rename vendor/github.com/{docker => }/distribution/reference/normalize.go (52%) rename vendor/github.com/{docker => }/distribution/reference/reference.go (93%) create mode 100644 vendor/github.com/distribution/reference/regexp.go create mode 100644 vendor/github.com/distribution/reference/sort.go create mode 100644 vendor/github.com/docker/distribution/reference/helpers_deprecated.go create mode 100644 vendor/github.com/docker/distribution/reference/normalize_deprecated.go create mode 100644 vendor/github.com/docker/distribution/reference/reference_deprecated.go delete mode 100644 vendor/github.com/docker/distribution/reference/regexp.go create mode 100644 vendor/github.com/docker/distribution/reference/regexp_deprecated.go create mode 100644 vendor/github.com/docker/distribution/reference/sort_deprecated.go create mode 100644 vendor/github.com/fsnotify/fsnotify/.cirrus.yml create mode 100644 vendor/github.com/go-jose/go-jose/v3/CHANGELOG.md create mode 100644 vendor/github.com/go-logr/logr/SECURITY.md rename vendor/github.com/google/go-cmp/cmp/{export_unsafe.go => export.go} (94%) delete mode 100644 vendor/github.com/google/go-cmp/cmp/export_panic.go rename vendor/github.com/google/go-cmp/cmp/internal/value/{pointer_unsafe.go => pointer.go} (95%) delete mode 100644 vendor/github.com/google/go-cmp/cmp/internal/value/pointer_purego.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/config.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/doc.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/hash.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/image.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/index.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/layer.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/manifest.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/platform.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/progress.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/types/types.go create mode 100644 vendor/github.com/google/go-containerregistry/pkg/v1/zz_deepcopy_generated.go rename vendor/github.com/grpc-ecosystem/grpc-gateway/v2/{LICENSE.txt => LICENSE} (100%) create mode 100644 vendor/github.com/jinzhu/copier/.gitignore create mode 100644 vendor/github.com/klauspost/compress/flate/matchlen_amd64.go create mode 100644 vendor/github.com/klauspost/compress/flate/matchlen_amd64.s create mode 100644 vendor/github.com/klauspost/compress/flate/matchlen_generic.go rename vendor/github.com/{docker/distribution => opencontainers/go-digest}/digestset/set.go (91%) create mode 100644 vendor/github.com/pkg/sftp/server_plan9.go create mode 100644 vendor/github.com/pkg/sftp/server_unix.go create mode 100644 vendor/github.com/pkg/sftp/server_windows.go create mode 100644 vendor/github.com/prometheus/procfs/net_route.go create mode 100644 vendor/github.com/secure-systems-lab/go-securesystemslib/LICENSE rename vendor/github.com/{theupdateframework/go-tuf => secure-systems-lab/go-securesystemslib}/encrypted/encrypted.go (64%) delete mode 100644 vendor/github.com/spf13/cobra/active_help.md delete mode 100644 vendor/github.com/spf13/cobra/bash_completions.md delete mode 100644 vendor/github.com/spf13/cobra/fish_completions.md delete mode 100644 vendor/github.com/spf13/cobra/powershell_completions.md delete mode 100644 vendor/github.com/spf13/cobra/projects_using_cobra.md delete mode 100644 vendor/github.com/spf13/cobra/shell_completions.md delete mode 100644 vendor/github.com/spf13/cobra/user_guide.md delete mode 100644 vendor/github.com/spf13/cobra/zsh_completions.md delete mode 100644 vendor/github.com/theupdateframework/go-tuf/LICENSE create mode 100644 vendor/github.com/vbauerster/mpb/v8/CONTRIBUTING delete mode 100644 vendor/github.com/vbauerster/mpb/v8/decor/merge.go create mode 100644 vendor/github.com/vbauerster/mpb/v8/decor/meta.go create mode 100644 vendor/github.com/vbauerster/mpb/v8/decor/on_compete_or_on_abort.go create mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/doc.go create mode 100644 vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go create mode 100644 vendor/golang.org/x/exp/slices/cmp.go rename vendor/golang.org/x/exp/slices/{zsortfunc.go => zsortanyfunc.go} (64%) delete mode 100644 vendor/golang.org/x/net/http2/go111.go delete mode 100644 vendor/golang.org/x/net/http2/go115.go delete mode 100644 vendor/golang.org/x/net/http2/go118.go delete mode 100644 vendor/golang.org/x/net/http2/not_go111.go delete mode 100644 vendor/golang.org/x/net/http2/not_go115.go delete mode 100644 vendor/golang.org/x/net/http2/not_go118.go create mode 100644 vendor/golang.org/x/oauth2/deviceauth.go create mode 100644 vendor/golang.org/x/oauth2/pkce.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/objectpath.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE.libyaml create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/NOTICE create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/OWNERS create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/README.md create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/apic.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/decode.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/emitterc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/encode.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/parserc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/readerc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/resolve.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/scannerc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/sorter.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/writerc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/yaml.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/yamlh.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/yamlprivateh.go create mode 100644 vendor/tags.cncf.io/container-device-interface/LICENSE create mode 100644 vendor/tags.cncf.io/container-device-interface/pkg/parser/parser.go diff --git a/go.mod b/go.mod index e753ffa56f8..b5367a5292d 100644 --- a/go.mod +++ b/go.mod @@ -11,32 +11,32 @@ require ( github.com/checkpoint-restore/go-criu/v6 v6.3.0 github.com/container-orchestrated-devices/container-device-interface v0.6.0 github.com/containerd/cgroups v1.1.0 - github.com/containerd/containerd v1.7.5 + github.com/containerd/containerd v1.7.9 github.com/containerd/cri-containerd v1.19.0 github.com/containerd/fifo v1.1.0 - github.com/containerd/nri v0.3.1-0.20230504231226-94185418e253 + github.com/containerd/nri v0.4.0 github.com/containerd/ttrpc v1.2.2 github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 github.com/containernetworking/cni v1.1.2 github.com/containernetworking/plugins v1.3.0 - github.com/containers/common v0.55.4 + github.com/containers/common v0.57.4 github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon-rs v0.6.1 - github.com/containers/image/v5 v5.27.0 + github.com/containers/image/v5 v5.29.2 github.com/containers/kubensmnt v1.2.0 - github.com/containers/ocicrypt v1.1.8 + github.com/containers/ocicrypt v1.1.9 github.com/containers/podman/v4 v4.6.2 - github.com/containers/storage v1.50.2 + github.com/containers/storage v1.51.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cpuguy83/go-md2man v1.0.10 github.com/creack/pty v1.1.18 github.com/cri-o/ocicni v0.4.1-0.20230504062519-ad62f4ea0c11 github.com/cyphar/filepath-securejoin v0.2.4 - github.com/docker/distribution v2.8.2+incompatible + github.com/docker/distribution v2.8.3+incompatible github.com/docker/go-units v0.5.0 - github.com/fsnotify/fsnotify v1.6.0 + github.com/fsnotify/fsnotify v1.7.0 github.com/go-chi/chi/v5 v5.0.10 - github.com/go-logr/logr v1.2.4 + github.com/go-logr/logr v1.3.0 github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 github.com/gogo/protobuf v1.3.2 github.com/golang/mock v1.6.0 @@ -46,15 +46,15 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/intel/goresctrl v0.5.0 github.com/json-iterator/go v1.1.12 - github.com/onsi/ginkgo/v2 v2.13.0 - github.com/onsi/gomega v1.28.0 + github.com/onsi/ginkgo/v2 v2.13.1 + github.com/onsi/gomega v1.30.0 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc4 - github.com/opencontainers/runc v1.1.9 + github.com/opencontainers/image-spec v1.1.0-rc5 + github.com/opencontainers/runc v1.1.10 github.com/opencontainers/runtime-spec v1.1.1-0.20230823135140-4fec88fd00a4 - github.com/opencontainers/runtime-tools v0.9.1-0.20230317050512-e931285f4b69 + github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc github.com/opencontainers/selinux v1.11.0 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 github.com/seccomp/libseccomp-golang v0.10.0 github.com/sirupsen/logrus v1.9.3 github.com/soheilhy/cmux v0.1.5 @@ -63,14 +63,14 @@ require ( github.com/uptrace/opentelemetry-go-extra/otellogrus v0.2.2 github.com/urfave/cli/v2 v2.25.7 github.com/vishvananda/netlink v1.2.1-beta.2 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 go.opentelemetry.io/otel v1.19.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 go.opentelemetry.io/otel/sdk v1.19.0 go.opentelemetry.io/otel/trace v1.19.0 - golang.org/x/net v0.17.0 - golang.org/x/sync v0.3.0 - golang.org/x/sys v0.13.0 + golang.org/x/net v0.18.0 + golang.org/x/sync v0.5.0 + golang.org/x/sys v0.14.0 google.golang.org/grpc v1.58.3 google.golang.org/protobuf v1.31.0 k8s.io/api v0.29.0-alpha.2 @@ -82,15 +82,15 @@ require ( k8s.io/utils v0.0.0-20230726121419-3b25d923346b sigs.k8s.io/release-sdk v0.10.3 sigs.k8s.io/release-utils v0.7.5 - sigs.k8s.io/yaml v1.3.0 + sigs.k8s.io/yaml v1.4.0 ) require ( capnproto.org/go/capnp/v3 v3.0.0-alpha.25 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/Microsoft/hcsshim v0.12.0-rc.0 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230528122434-6f98819771a1 // indirect + github.com/Microsoft/hcsshim v0.12.0-rc.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/acomagu/bufpipe v1.0.4 // indirect @@ -104,18 +104,20 @@ require ( github.com/containerd/cgroups/v3 v3.0.2 // indirect github.com/containerd/console v1.0.3 // indirect github.com/containerd/go-runc v1.0.0 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/containerd/typeurl/v2 v2.1.1 // indirect github.com/containers/buildah v1.31.2 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/psgo v1.8.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/disiqueira/gotree/v3 v3.0.2 // indirect - github.com/docker/docker v24.0.2+incompatible // indirect - github.com/docker/docker-credential-helpers v0.7.0 // indirect + github.com/distribution/reference v0.5.0 // indirect + github.com/docker/docker v24.0.7+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.0 // indirect github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-metrics v0.0.1 // indirect @@ -126,7 +128,7 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.4.1 // indirect github.com/go-git/go-git/v5 v5.7.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.21.4 // indirect github.com/go-openapi/errors v0.20.4 // indirect @@ -142,8 +144,8 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/go-containerregistry v0.15.2 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-containerregistry v0.16.1 // indirect github.com/google/go-github/v53 v53.2.0 // indirect github.com/google/go-intervals v0.0.2 // indirect github.com/google/go-querystring v1.1.0 // indirect @@ -152,31 +154,31 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jinzhu/copier v0.3.5 // indirect + github.com/jinzhu/copier v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/klauspost/compress v1.17.3 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/kr/fs v0.1.0 // indirect github.com/letsencrypt/boulder v0.0.0-20230213213521-fdfea0d469b6 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect - github.com/mattn/go-sqlite3 v1.14.17 // indirect + github.com/mattn/go-sqlite3 v1.14.18 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/sys/mountinfo v0.6.2 // indirect + github.com/moby/sys/mountinfo v0.7.1 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -189,53 +191,53 @@ require ( github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pkg/sftp v1.13.5 // indirect + github.com/pkg/sftp v1.13.6 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/proglottis/gpgme v0.1.3 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect github.com/sergi/go-diff v1.3.1 // indirect - github.com/sigstore/fulcio v1.3.1 // indirect + github.com/sigstore/fulcio v1.4.3 // indirect github.com/sigstore/rekor v1.2.2 // indirect - github.com/sigstore/sigstore v1.7.1 // indirect + github.com/sigstore/sigstore v1.7.5 // indirect github.com/skeema/knownhosts v1.1.1 // indirect - github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect - github.com/sylabs/sif/v2 v2.11.5 // indirect + github.com/sylabs/sif/v2 v2.15.0 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect - github.com/theupdateframework/go-tuf v0.5.2 // indirect github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/ulikunitz/xz v0.5.11 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.2.2 // indirect github.com/vbatts/tar-split v0.11.5 // indirect - github.com/vbauerster/mpb/v8 v8.4.0 // indirect + github.com/vbauerster/mpb/v8 v8.6.2 // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - go.etcd.io/bbolt v1.3.7 // indirect + go.etcd.io/bbolt v1.3.8 // indirect go.mongodb.org/mongo-driver v1.11.3 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/oauth2 v0.14.0 // indirect + golang.org/x/term v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + golang.org/x/tools v0.14.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect @@ -246,5 +248,6 @@ require ( k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect + tags.cncf.io/container-device-interface v0.6.2 // indirect zenhack.net/go/util v0.0.0-20230218002511-744d2d6d1739 // indirect ) diff --git a/go.sum b/go.sum index d4527b584ba..f371fe52812 100644 --- a/go.sum +++ b/go.sum @@ -13,12 +13,12 @@ cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk= +cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk= -cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -75,14 +75,14 @@ github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.12.0-rc.0 h1:wX/F5huJxH9APBkhKSEAqaiZsuBvbbDnyBROZAqsSaY= -github.com/Microsoft/hcsshim v0.12.0-rc.0/go.mod h1:rvOnw3YlfoNnEp45wReUngvsXbwRW+AFQ10GVjG1kMU= +github.com/Microsoft/hcsshim v0.12.0-rc.1 h1:Hy+xzYujv7urO5wrgcG58SPMOXNLrj4WCJbySs2XX/A= +github.com/Microsoft/hcsshim v0.12.0-rc.1/go.mod h1:Y1a1S0QlYp1mBpyvGiuEdOfZqnao+0uX5AWHXQ5NhZU= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v0.0.0-20230528122434-6f98819771a1 h1:JMDGhoQvXNTqH6Y3MC0IUw6tcZvaUdujNqzK2HYWZc8= -github.com/ProtonMail/go-crypto v0.0.0-20230528122434-6f98819771a1/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs= +github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= @@ -213,8 +213,8 @@ github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09Zvgq github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= -github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/containerd/containerd v1.7.9 h1:KOhK01szQbM80YfW1H6RZKh85PHGqY/9OcEZ35Je8sc= +github.com/containerd/containerd v1.7.9/go.mod h1:0/W44LWEYfSHoxBtsHIiNU/duEkgpMokemafHVCpq9Y= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -244,15 +244,17 @@ github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.3.1-0.20230504231226-94185418e253 h1:cUfRSE/vMuzRREn61rJcDavM4e7V0sZwxLSQywvJop8= -github.com/containerd/nri v0.3.1-0.20230504231226-94185418e253/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI= +github.com/containerd/nri v0.4.0 h1:PjgIBm0RtUiFyEO6JqPBQZRQicbsIz41Fz/5VSC0zgw= +github.com/containerd/nri v0.4.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI= github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= github.com/containerd/stargz-snapshotter/estargz v0.12.0/go.mod h1:AIQ59TewBFJ4GOPEQXujcrJ/EKxh5xXZegW1rkR1P/M= -github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU= +github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= @@ -285,14 +287,14 @@ github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0= github.com/containers/buildah v1.31.2 h1:Pfbuzq5dtbLYtj95zDu1rLbVo9bnboknv18ZmlfXVA4= github.com/containers/buildah v1.31.2/go.mod h1:EnrujxgRtUi0+2DrxXAzyQ/GybLliqT0+06PMLSTlvw= -github.com/containers/common v0.55.4 h1:7IxB/G5qtDU+rp1YiVWkDpd+ZC4ZlCQ7k2jZJYkB/R8= -github.com/containers/common v0.55.4/go.mod h1:5mVCpfMBWyO+zaD7Fw+DBHFa42YFKROwle1qpEKcX3U= +github.com/containers/common v0.57.4 h1:kmfBad92kUjP5X44BPpOwMe+eZQqaKETfS+ASeL0g+g= +github.com/containers/common v0.57.4/go.mod h1:o3L3CyOI9yr+JC8l4dZgvqTxcjs3qdKmkek00uchgvw= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon-rs v0.6.1 h1:mjs2hs1/oT7jYL1RgZSYN2MxxyjWOaRouv2BNqQkaKU= github.com/containers/conmon-rs v0.6.1/go.mod h1:6Kk0tGkTVFN6nmd5ynDK2ECK1vAorbMquSilcKCb0MQ= -github.com/containers/image/v5 v5.27.0 h1:4jKVWAa4YurTWUyAWMoC71zJkSylBR7pWd0jqGkukYc= -github.com/containers/image/v5 v5.27.0/go.mod h1:IwlOGzTkGnmfirXxt0hZeJlzv1zVukE03WZQ203Z9GA= +github.com/containers/image/v5 v5.29.2 h1:b8U0XYWhaQbKucK73IbmSm8WQyKAhKDbAHQc45XlsOw= +github.com/containers/image/v5 v5.29.2/go.mod h1:kQ7qcDsps424ZAz24thD+x7+dJw1vgur3A9tTDsj97E= github.com/containers/kubensmnt v1.2.0 h1:BDtkaOFQ5fN7FnB9kC6peMW50KkwI1KI8E9ROBFeQIg= github.com/containers/kubensmnt v1.2.0/go.mod h1:1/HG09N/a1+WSD3zkurzeWtqlKRSfUUnlIF/08zloqk= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= @@ -300,15 +302,15 @@ github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.8 h1:saSBF0/8DyPUjzcxMVzL2OBUWCkvRvqIm75pu0ADSZk= -github.com/containers/ocicrypt v1.1.8/go.mod h1:jM362hyBtbwLMWzXQZTlkjKGAQf/BN/LFMtH0FIRt34= +github.com/containers/ocicrypt v1.1.9 h1:2Csfba4jse85Raxk5HIyEk8OwZNjRvfkhEGijOjIdEM= +github.com/containers/ocicrypt v1.1.9/go.mod h1:dTKx1918d8TDkxXvarscpNVY+lyPakPNFN4jwA9GBys= github.com/containers/podman/v4 v4.6.2 h1:tUHH6RfavqH0QZJHA9JoiMtMatjUSe4LjkvQYD8AhMs= github.com/containers/podman/v4 v4.6.2/go.mod h1:RszjaonNv/hLayX58T06xci2ixrcCoR5hfdfN6PQWmc= github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY= github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc= github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s= -github.com/containers/storage v1.50.2 h1:Fys4BjFUVNRBEXlO70hFI48VW4EXsgnGisTpk9tTMsE= -github.com/containers/storage v1.50.2/go.mod h1:dpspZsUrcKD8SpTofvKWhwPDHD0MkO4Q7VE+oYdWkiA= +github.com/containers/storage v1.51.0 h1:AowbcpiWXzAjHosKz7MKvPEqpyX+ryZA/ZurytRrFNA= +github.com/containers/storage v1.51.0/go.mod h1:ybl8a3j1PPtpyaEi/5A6TOFs+5TrEyObeKJzVtkUlfc= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= @@ -332,16 +334,17 @@ github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cri-o/ocicni v0.4.1-0.20230504062519-ad62f4ea0c11 h1:tNECj3vbJTpiieCM4wK7VcgzUrhZGXZhEf7iLHlBe14= github.com/cri-o/ocicni v0.4.1-0.20230504062519-ad62f4ea0c11/go.mod h1:/i3DeaXVuw12dwFUXeXzrp68osVAzNi4s5jCRKTGZKE= -github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1 h1:8Pq5UNTC+/UfvcOPKQGZoKCkeF+ZaKa4wJ9OS2gsQQM= -github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= +github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 h1:2Dx4IHfC1yHWI12AxQDJM1QbRCDfk6M+blLzlZCXdrc= +github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= 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= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= @@ -359,19 +362,23 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWhkNRq8= github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= +github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +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 v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg= -github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= -github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= +github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 h1:IPrmumsT9t5BS7XcPhgsCTlkWbYg80SEXUzDpReaU6Y= github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11/go.mod h1:a6bNUGTbQBsY6VRHTr4h/rkOXjl244DyRD0tx3fgq4Q= @@ -422,8 +429,8 @@ github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzP github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsouza/go-dockerclient v1.9.7 h1:FlIrT71E62zwKgRvCvWGdxRD+a/pIy+miY/n3MXgfuw= github.com/fsouza/go-dockerclient v1.9.7/go.mod h1:vx9C32kE2D15yDSOMCDaAEIARZpDQDFBHeqL3MgQy/U= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= @@ -446,8 +453,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -458,8 +465,8 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/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-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= @@ -608,11 +615,12 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= -github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE= -github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q= +github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ= +github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ= github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUexMpIfk= github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q= github.com/google/go-github/v53 v53.2.0 h1:wvz3FyF53v4BK+AsnvCmeNhf8AkTaeh2SoYu/XUvTtI= @@ -669,8 +677,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -704,8 +712,8 @@ github.com/intel/goresctrl v0.5.0/go.mod h1:mIe63ggylWYr0cU/l8n11FAkesqfvuP3oktI github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4= @@ -737,8 +745,8 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= +github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -779,14 +787,14 @@ github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlW github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= -github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI= +github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -814,8 +822,9 @@ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0Gq github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +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/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= @@ -857,8 +866,8 @@ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= +github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -868,8 +877,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= -github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -878,8 +887,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -887,8 +896,8 @@ github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rm github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM= -github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= +github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40= +github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -898,8 +907,8 @@ github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.m github.com/opencontainers/runtime-spec v1.1.1-0.20230823135140-4fec88fd00a4 h1:EctkgBjZ1y4q+sibyuuIgiKpa0QSd2elFtSSdNvBVow= github.com/opencontainers/runtime-spec v1.1.1-0.20230823135140-4fec88fd00a4/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/runtime-tools v0.9.1-0.20230317050512-e931285f4b69 h1:NL4xDvl68WWqQ+8WPMM3l5PsZTxaT7Z4K3VSKDRuAGs= -github.com/opencontainers/runtime-tools v0.9.1-0.20230317050512-e931285f4b69/go.mod h1:bNpfuSHA3DZRtD0TPWO8LzgtLpFPTVA/3jDkzD/OPyk= +github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc h1:d2hUh5O6MRBvStV55MQ8we08t42zSTqBbscoQccWmMc= +github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc/go.mod h1:8tx1helyqhUC65McMm3x7HmOex8lO2/v9zPuxmKHurs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= @@ -912,6 +921,8 @@ github.com/openshift/imagebuilder v1.2.5/go.mod h1:bF4w79W8nM+jH1QkAiHSUVaqHkMBJ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqwnHagNDPGOlts35QkhAZ8by3DR7nMih7M= github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= @@ -925,8 +936,8 @@ github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go= -github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg= +github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= +github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= @@ -938,15 +949,15 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -966,8 +977,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= @@ -977,8 +988,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= @@ -994,15 +1005,17 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAjPbcMsODrTQUpJ02eNLUoxBg= +github.com/secure-systems-lab/go-securesystemslib v0.7.0/go.mod h1:/2gYnlnHVQ6xeGtfIqFy7Do03K4cdCY0A/GlJLDKLHI= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sigstore/fulcio v1.3.1 h1:0ntW9VbQbt2JytoSs8BOGB84A65eeyvGSavWteYp29Y= -github.com/sigstore/fulcio v1.3.1/go.mod h1:/XfqazOec45ulJZpyL9sq+OsVQ8g2UOVoNVi7abFgqU= +github.com/sigstore/fulcio v1.4.3 h1:9JcUCZjjVhRF9fmhVuz6i1RyhCc/EGCD7MOl+iqCJLQ= +github.com/sigstore/fulcio v1.4.3/go.mod h1:BQPWo7cfxmJwgaHlphUHUpFkp5+YxeJes82oo39m5og= github.com/sigstore/rekor v1.2.2 h1:5JK/zKZvcQpL/jBmHvmFj3YbpDMBQnJQ6ygp8xdF3bY= github.com/sigstore/rekor v1.2.2/go.mod h1:FGnWBGWzeNceJnp0x9eDFd41mI8aQqCjj+Zp0IEs0Qg= -github.com/sigstore/sigstore v1.7.1 h1:fCATemikcBK0cG4+NcM940MfoIgmioY1vC6E66hXxks= -github.com/sigstore/sigstore v1.7.1/go.mod h1:0PmMzfJP2Y9+lugD0wer4e7TihR5tM7NcIs3bQNk5xg= +github.com/sigstore/sigstore v1.7.5 h1:ij55dBhLwjICmLTBJZm7SqoQLdsu/oowDanACcJNs48= +github.com/sigstore/sigstore v1.7.5/go.mod h1:9OCmYWhzuq/G4e1cy9m297tuMRJ1LExyrXY3ZC3Zt/s= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1030,8 +1043,8 @@ github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKv github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1060,8 +1073,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/sylabs/sif/v2 v2.11.5 h1:7ssPH3epSonsTrzbS1YxeJ9KuqAN7ISlSM61a7j/mQM= -github.com/sylabs/sif/v2 v2.11.5/go.mod h1:GBoZs9LU3e4yJH1dcZ3Akf/jsqYgy5SeguJQC+zd75Y= +github.com/sylabs/sif/v2 v2.15.0 h1:Nv0tzksFnoQiQ2eUwpAis9nVqEu4c3RcNSxX8P3Cecw= +github.com/sylabs/sif/v2 v2.15.0/go.mod h1:X1H7eaPz6BAxA84POMESXoXfTqgAnLQkujyF/CQFWTc= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= @@ -1070,8 +1083,6 @@ github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= -github.com/theupdateframework/go-tuf v0.5.2 h1:habfDzTmpbzBLIFGWa2ZpVhYvFBoK0C1onC3a4zuPRA= -github.com/theupdateframework/go-tuf v0.5.2/go.mod h1:SyMV5kg5n4uEclsyxXJZI2UxPFJNDc4Y+r7wv+MlvTA= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1099,8 +1110,8 @@ github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6S github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/vbauerster/mpb/v8 v8.4.0 h1:Jq2iNA7T6SydpMVOwaT+2OBWlXS9Th8KEvBqeu5eeTo= -github.com/vbauerster/mpb/v8 v8.4.0/go.mod h1:vjp3hSTuCtR+x98/+2vW3eZ8XzxvGoP8CPseHMhiPyc= +github.com/vbauerster/mpb/v8 v8.6.2 h1:9EhnJGQRtvgDVCychJgR96EDCOqgg2NsMuk5JUcX4DA= +github.com/vbauerster/mpb/v8 v8.6.2/go.mod h1:oVJ7T+dib99kZ/VBjoBaC8aPXiSAihnzuKmotuihyFo= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -1148,8 +1159,8 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= +go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= @@ -1165,14 +1176,14 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0 h1:7XZai4VhA473clBrOqqHdjHBImGfyEtv0qW4nnn/kAo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.43.0/go.mod h1:1WpsUwjQrUJSNugfMlPn0rPRJ9Do7wwBgTBPK7MLiS4= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0 h1:RsQi0qJ2imFfCvZabqzM9cNXBG8k6gXMv1A0cXRmH6A= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.45.0/go.mod h1:vsh3ySueQCiKPxFLvjWC4Z135gIa34TQ/NSqkDTZYUM= go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0 h1:U5GYackKpVKlPrd/5gKMlrTlP2dCESAAFU682VCpieY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.17.0/go.mod h1:aFsJfCEnLzEu9vRRAcUiB/cpRTbVsNdF3OHSPpdjxZQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0 h1:iGeIsSYwpYSvh5UGzWrJfTDJvPjrXtxl3GUppj6IXQU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.17.0/go.mod h1:1j3H3G1SBYpZFti6OI4P0uRQCW20MXkG5v4UWXppLLE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= @@ -1209,12 +1220,12 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1225,8 +1236,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1250,8 +1261,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1297,18 +1308,19 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= 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= @@ -1323,8 +1335,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1409,21 +1421,21 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1433,11 +1445,12 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= @@ -1498,8 +1511,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1522,8 +1535,8 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1551,12 +1564,12 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1641,8 +1654,8 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= -gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/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= @@ -1715,7 +1728,9 @@ sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6Lv sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +tags.cncf.io/container-device-interface v0.6.2 h1:dThE6dtp/93ZDGhqaED2Pu374SOeUkBfuvkLuiTdwzg= +tags.cncf.io/container-device-interface v0.6.2/go.mod h1:Shusyhjs1A5Na/kqPVLL0KqnHQHuunol9LFeUNkuGVE= zenhack.net/go/util v0.0.0-20230218002511-744d2d6d1739 h1:/QnbZBURrZUFvnxB4wDyRrPsWzh2KWbJ6AjUjohCHJ8= zenhack.net/go/util v0.0.0-20230218002511-744d2d6d1739/go.mod h1:0lafdGg7tDb7RcXASgmJmRbLFLkAxu328+KGIs7icDE= diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go index e437e297c0d..37afbf6917a 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go @@ -12,14 +12,16 @@ import ( "syscall" "time" + "go.opencensus.io/trace" + "github.com/Microsoft/hcsshim/internal/cow" + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" "github.com/Microsoft/hcsshim/internal/log" "github.com/Microsoft/hcsshim/internal/oc" + "github.com/Microsoft/hcsshim/internal/protocol/guestrequest" "github.com/Microsoft/hcsshim/internal/vmcompute" - "go.opencensus.io/trace" ) -// ContainerError is an error encountered in HCS type Process struct { handleLock sync.RWMutex handle vmcompute.HcsProcess @@ -50,35 +52,6 @@ func newProcess(process vmcompute.HcsProcess, processID int, computeSystem *Syst } } -type processModifyRequest struct { - Operation string - ConsoleSize *consoleSize `json:",omitempty"` - CloseHandle *closeHandle `json:",omitempty"` -} - -type consoleSize struct { - Height uint16 - Width uint16 -} - -type closeHandle struct { - Handle string -} - -type processStatus struct { - ProcessID uint32 - Exited bool - ExitCode uint32 - LastWaitResult int32 -} - -const stdIn string = "StdIn" - -const ( - modifyConsoleSize string = "ConsoleSize" - modifyCloseHandle string = "CloseHandle" -) - // Pid returns the process ID of the process within the container. func (process *Process) Pid() int { return process.processID @@ -260,14 +233,14 @@ func (process *Process) waitBackground() { process.handleLock.RLock() defer process.handleLock.RUnlock() - // Make sure we didnt race with Close() here + // Make sure we didn't race with Close() here if process.handle != 0 { propertiesJSON, resultJSON, err = vmcompute.HcsGetProcessProperties(ctx, process.handle) events := processHcsResult(ctx, resultJSON) if err != nil { err = makeProcessError(process, operation, err, events) } else { - properties := &processStatus{} + properties := &hcsschema.ProcessStatus{} err = json.Unmarshal([]byte(propertiesJSON), properties) if err != nil { err = makeProcessError(process, operation, err, nil) @@ -318,10 +291,9 @@ func (process *Process) ResizeConsole(ctx context.Context, width, height uint16) if process.handle == 0 { return makeProcessError(process, operation, ErrAlreadyClosed, nil) } - - modifyRequest := processModifyRequest{ - Operation: modifyConsoleSize, - ConsoleSize: &consoleSize{ + modifyRequest := hcsschema.ProcessModifyRequest{ + Operation: guestrequest.ModifyProcessConsoleSize, + ConsoleSize: &hcsschema.ConsoleSize{ Height: height, Width: width, }, @@ -421,18 +393,12 @@ func (process *Process) CloseStdin(ctx context.Context) (err error) { return makeProcessError(process, operation, ErrAlreadyClosed, nil) } - process.stdioLock.Lock() - defer process.stdioLock.Unlock() - if process.stdin == nil { - return nil - } - //HcsModifyProcess request to close stdin will fail if the process has already exited if !process.stopped() { - modifyRequest := processModifyRequest{ - Operation: modifyCloseHandle, - CloseHandle: &closeHandle{ - Handle: stdIn, + modifyRequest := hcsschema.ProcessModifyRequest{ + Operation: guestrequest.CloseProcessHandle, + CloseHandle: &hcsschema.CloseHandle{ + Handle: guestrequest.STDInHandle, }, } @@ -448,8 +414,12 @@ func (process *Process) CloseStdin(ctx context.Context) (err error) { } } - process.stdin.Close() - process.stdin = nil + process.stdioLock.Lock() + defer process.stdioLock.Unlock() + if process.stdin != nil { + process.stdin.Close() + process.stdin = nil + } return nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/close_handle.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/close_handle.go index b4f9c315b05..bb36777b821 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/close_handle.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/close_handle.go @@ -9,6 +9,8 @@ package hcsschema +import "github.com/Microsoft/hcsshim/internal/protocol/guestrequest" + type CloseHandle struct { - Handle string `json:"Handle,omitempty"` + Handle guestrequest.STDIOHandle `json:"Handle,omitempty"` // NOTE: Swagger generated as string. Locally updated. } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/console_size.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/console_size.go index 68aa04a573e..347da50e86c 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/console_size.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/console_size.go @@ -9,8 +9,11 @@ package hcsschema +// NOTE: Swagger generated fields as int32. Locally updated to uint16 to match documentation. +// https://learn.microsoft.com/en-us/virtualization/api/hcs/schemareference#ConsoleSize + type ConsoleSize struct { - Height int32 `json:"Height,omitempty"` + Height uint16 `json:"Height,omitempty"` - Width int32 `json:"Width,omitempty"` + Width uint16 `json:"Width,omitempty"` } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_modify_request.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_modify_request.go index e4ed095c7be..862b7911e2d 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_modify_request.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_modify_request.go @@ -9,9 +9,11 @@ package hcsschema -// Passed to HcsRpc_ModifyProcess +import "github.com/Microsoft/hcsshim/internal/protocol/guestrequest" + +// Passed to HcsRpc_ModifyProcess type ProcessModifyRequest struct { - Operation string `json:"Operation,omitempty"` + Operation guestrequest.ProcessModifyOperation `json:"Operation,omitempty"` // NOTE: Swagger generated as string. Locally updated. ConsoleSize *ConsoleSize `json:"ConsoleSize,omitempty"` diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_status.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_status.go index ad9a4fa9ad6..3c371d4650a 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_status.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/schema2/process_status.go @@ -9,13 +9,16 @@ package hcsschema -// Status of a process running in a container +// NOTE: Swagger generated fields as int32. Locally updated to uint16 to match documentation. +// https://learn.microsoft.com/en-us/virtualization/api/hcs/schemareference#ConsoleSize + +// Status of a process running in a container type ProcessStatus struct { - ProcessId int32 `json:"ProcessId,omitempty"` + ProcessId uint32 `json:"ProcessId,omitempty"` // NOTE: Swagger generated as int32. Locally updated to match documentation. Exited bool `json:"Exited,omitempty"` - ExitCode int32 `json:"ExitCode,omitempty"` + ExitCode uint32 `json:"ExitCode,omitempty"` // NOTE: Swagger generated as int32. Locally updated to match documentation. LastWaitResult int32 `json:"LastWaitResult,omitempty"` } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go index cf20adefc93..cf1db7da9a9 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go @@ -304,11 +304,22 @@ func (computeSystem *System) WaitError() error { return computeSystem.waitError } -// Wait synchronously waits for the compute system to shutdown or terminate. If -// the compute system has already exited returns the previous error (if any). +// Wait synchronously waits for the compute system to shutdown or terminate. +// If the compute system has already exited returns the previous error (if any). func (computeSystem *System) Wait() error { - <-computeSystem.WaitChannel() - return computeSystem.WaitError() + return computeSystem.WaitCtx(context.Background()) +} + +// WaitCtx synchronously waits for the compute system to shutdown or terminate, or the context to be cancelled. +// +// See [System.Wait] for more information. +func (computeSystem *System) WaitCtx(ctx context.Context) error { + select { + case <-computeSystem.WaitChannel(): + return computeSystem.WaitError() + case <-ctx.Done(): + return ctx.Err() + } } // stopped returns true if the compute system stopped. @@ -735,9 +746,17 @@ func (computeSystem *System) OpenProcess(ctx context.Context, pid int) (*Process } // Close cleans up any state associated with the compute system but does not terminate or wait for it. -func (computeSystem *System) Close() (err error) { +func (computeSystem *System) Close() error { + return computeSystem.CloseCtx(context.Background()) +} + +// CloseCtx is similar to [System.Close], but accepts a context. +// +// The context is used for all operations, including waits, so timeouts/cancellations may prevent +// proper system cleanup. +func (computeSystem *System) CloseCtx(ctx context.Context) (err error) { operation := "hcs::System::Close" - ctx, span := oc.StartSpan(context.Background(), operation) + ctx, span := oc.StartSpan(ctx, operation) defer span.End() defer func() { oc.SetSpanStatus(span, err) }() span.AddAttributes(trace.StringAttribute("cid", computeSystem.id)) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/log/format.go b/vendor/github.com/Microsoft/hcsshim/internal/log/format.go index d35efa01612..6d69c15b97d 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/log/format.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/log/format.go @@ -9,13 +9,16 @@ import ( "reflect" "time" - "github.com/containerd/containerd/log" "github.com/sirupsen/logrus" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) -const TimeFormat = log.RFC3339NanoFixed +// TimeFormat is [time.RFC3339Nano] with nanoseconds padded using +// zeros to ensure the formatted time is always the same number of +// characters. +// Based on RFC3339NanoFixed from github.com/containerd/log +const TimeFormat = "2006-01-02T15:04:05.000000000Z07:00" func FormatTime(t time.Time) string { return t.Format(TimeFormat) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/log/hook.go b/vendor/github.com/Microsoft/hcsshim/internal/log/hook.go index 94c6d0918f9..bb547a329f6 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/log/hook.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/log/hook.go @@ -6,7 +6,6 @@ import ( "time" "github.com/Microsoft/hcsshim/internal/logfields" - "github.com/containerd/containerd/log" "github.com/sirupsen/logrus" "go.opencensus.io/trace" ) @@ -30,7 +29,7 @@ type Hook struct { // An empty string disables formatting. // When disabled, the fall back will the JSON encoding, if enabled. // - // Default is [github.com/containerd/containerd/log.RFC3339NanoFixed]. + // Default is [TimeFormat]. TimeFormat string // Duration format converts a [time.Duration] fields to an appropriate encoding. @@ -49,7 +48,7 @@ var _ logrus.Hook = &Hook{} func NewHook() *Hook { return &Hook{ - TimeFormat: log.RFC3339NanoFixed, + TimeFormat: TimeFormat, DurationFormat: DurationFormatString, AddSpanContext: true, } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/log/nopformatter.go b/vendor/github.com/Microsoft/hcsshim/internal/log/nopformatter.go new file mode 100644 index 00000000000..909ba68b28f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/log/nopformatter.go @@ -0,0 +1,12 @@ +package log + +import ( + "github.com/sirupsen/logrus" +) + +type NopFormatter struct{} + +var _ logrus.Formatter = NopFormatter{} + +// Format does nothing and returns a nil slice. +func (NopFormatter) Format(*logrus.Entry) ([]byte, error) { return nil, nil } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/protocol/guestrequest/types.go b/vendor/github.com/Microsoft/hcsshim/internal/protocol/guestrequest/types.go index d8d0c20b103..4f441803b7a 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/protocol/guestrequest/types.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/protocol/guestrequest/types.go @@ -5,7 +5,7 @@ package guestrequest type RequestType string type ResourceType string -// RequestType const +// RequestType const. const ( RequestTypeAdd RequestType = "Add" RequestTypeRemove RequestType = "Remove" @@ -54,3 +54,23 @@ var ( "305891a9-b251-5dfe-91a2-c25d9212275b", } ) + +// constants for v2 schema ProcessModifyRequest + +// Operation type for [hcsschema.ProcessModifyRequest]. +type ProcessModifyOperation string + +const ( + ModifyProcessConsoleSize ProcessModifyOperation = "ConsoleSize" + CloseProcessHandle ProcessModifyOperation = "CloseHandle" +) + +// Standard IO handle(s) to close for [hcsschema.CloseHandle] in [hcsschema.ProcessModifyRequest]. +type STDIOHandle string + +const ( + STDInHandle STDIOHandle = "StdIn" + STDOutHandle STDIOHandle = "StdOut" + STDErrHandle STDIOHandle = "StdErr" + AllHandles STDIOHandle = "All" +) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go index d5d2cb137a8..ee17dd3d1a5 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/layerutils.go @@ -7,6 +7,10 @@ package wclayer import ( "context" + "fmt" + "os" + "path/filepath" + "strconv" "syscall" "github.com/Microsoft/go-winio/pkg/guid" @@ -101,3 +105,23 @@ func layerPathsToDescriptors(ctx context.Context, parentLayerPaths []string) ([] return layers, nil } + +// GetLayerUvmBuild looks for a file named `uvmbuildversion` at `layerPath\uvmbuildversion` and returns the +// build number of the UVM from that file. +func GetLayerUvmBuild(layerPath string) (uint16, error) { + data, err := os.ReadFile(filepath.Join(layerPath, UvmBuildFileName)) + if err != nil { + return 0, err + } + ver, err := strconv.ParseUint(string(data), 10, 16) + if err != nil { + return 0, err + } + return uint16(ver), nil +} + +// WriteLayerUvmBuildFile writes a file at path `layerPath\uvmbuildversion` that contains the given `build` +// version for future reference. +func WriteLayerUvmBuildFile(layerPath string, build uint16) error { + return os.WriteFile(filepath.Join(layerPath, UvmBuildFileName), []byte(fmt.Sprintf("%d", build)), 0777) +} diff --git a/vendor/github.com/Microsoft/hcsshim/layer.go b/vendor/github.com/Microsoft/hcsshim/layer.go index afd1ddd0aee..7e9c9fbbe80 100644 --- a/vendor/github.com/Microsoft/hcsshim/layer.go +++ b/vendor/github.com/Microsoft/hcsshim/layer.go @@ -32,6 +32,7 @@ func CreateScratchLayer(info DriverInfo, layerId, parentId string, parentLayerPa func DeactivateLayer(info DriverInfo, id string) error { return wclayer.DeactivateLayer(context.Background(), layerPath(&info, id)) } + func DestroyLayer(info DriverInfo, id string) error { return wclayer.DestroyLayer(context.Background(), layerPath(&info, id)) } diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go index 0d6c5f3f962..d7af9141e36 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go @@ -10,8 +10,9 @@ import ( "bufio" "bytes" "encoding/base64" - "github.com/ProtonMail/go-crypto/openpgp/errors" "io" + + "github.com/ProtonMail/go-crypto/openpgp/errors" ) // A Block represents an OpenPGP armored structure. @@ -208,12 +209,16 @@ TryNextBlock: break } - i := bytes.Index(line, []byte(": ")) + i := bytes.Index(line, []byte(":")) if i == -1 { goto TryNextBlock } lastKey = string(line[:i]) - p.Header[lastKey] = string(line[i+2:]) + var value string + if len(line) > i+2 { + value = string(line[i+2:]) + } + p.Header[lastKey] = value } p.lReader.in = r diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go index ec903ee95a2..3402b8c140c 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go @@ -415,6 +415,10 @@ func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) { return } + if len(pk.p.Bytes()) == 0 { + return errors.StructuralError("empty EdDSA public key") + } + pub := eddsa.NewPublicKey(c) switch flag := pk.p.Bytes()[0]; flag { diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go index 6c58c86fa87..80d0bb98e0f 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go @@ -904,7 +904,7 @@ func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubp if sig.IssuerKeyId != nil && sig.Version == 4 { keyId := make([]byte, 8) binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) - subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, true, keyId}) + subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) } if sig.IssuerFingerprint != nil { contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...) diff --git a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go index a8abf2ff7c9..bac2b132ea2 100644 --- a/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go +++ b/vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go @@ -7,13 +7,11 @@ package packet import ( "bytes" "crypto/cipher" - "crypto/sha256" "io" "strconv" "github.com/ProtonMail/go-crypto/openpgp/errors" "github.com/ProtonMail/go-crypto/openpgp/s2k" - "golang.org/x/crypto/hkdf" ) // This is the largest session key that we'll support. Since at most 256-bit cipher @@ -45,13 +43,6 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { return errors.UnsupportedError("unknown SymmetricKeyEncrypted version") } - if ske.Version == 5 { - // Scalar octet count - if _, err := readFull(r, buf[:]); err != nil { - return err - } - } - // Cipher function if _, err := readFull(r, buf[:]); err != nil { return err @@ -67,11 +58,6 @@ func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { return errors.StructuralError("cannot read AEAD octet from packet") } ske.Mode = AEADMode(buf[0]) - - // Scalar octet count - if _, err := readFull(r, buf[:]); err != nil { - return err - } } var err error @@ -220,7 +206,7 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass case 5: ivLen := config.AEAD().Mode().IvLength() tagLen := config.AEAD().Mode().TagLength() - packetLength = 5 + len(s2kBytes) + ivLen + keySize + tagLen + packetLength = 3 + len(s2kBytes) + ivLen + keySize + tagLen } err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) if err != nil { @@ -230,20 +216,12 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass // Symmetric Key Encrypted Version buf := []byte{byte(version)} - if version == 5 { - // Scalar octet count - buf = append(buf, byte(3+len(s2kBytes)+config.AEAD().Mode().IvLength())) - } - // Cipher function buf = append(buf, byte(cipherFunc)) if version == 5 { // AEAD mode buf = append(buf, byte(config.AEAD().Mode())) - - // Scalar octet count - buf = append(buf, byte(len(s2kBytes))) } _, err = w.Write(buf) if err != nil { @@ -293,11 +271,6 @@ func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, pass } func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte) (aead cipher.AEAD) { - hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData) - - encryptionKey := make([]byte, c.KeySize()) - _, _ = readFull(hkdfReader, encryptionKey) - - blockCipher := c.new(encryptionKey) + blockCipher := c.new(inputKey) return mode.new(blockCipher) } diff --git a/vendor/github.com/containerd/containerd/log/context_deprecated.go b/vendor/github.com/containerd/containerd/log/context_deprecated.go new file mode 100644 index 00000000000..9e9e8b49135 --- /dev/null +++ b/vendor/github.com/containerd/containerd/log/context_deprecated.go @@ -0,0 +1,149 @@ +/* + Copyright The containerd 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. +*/ + +package log + +import ( + "context" + + "github.com/containerd/log" +) + +// G is a shorthand for [GetLogger]. +// +// Deprecated: use [log.G]. +var G = log.G + +// L is an alias for the standard logger. +// +// Deprecated: use [log.L]. +var L = log.L + +// Fields type to pass to "WithFields". +// +// Deprecated: use [log.Fields]. +type Fields = log.Fields + +// Entry is a logging entry. +// +// Deprecated: use [log.Entry]. +type Entry = log.Entry + +// RFC3339NanoFixed is [time.RFC3339Nano] with nanoseconds padded using +// zeros to ensure the formatted time is always the same number of +// characters. +// +// Deprecated: use [log.RFC3339NanoFixed]. +const RFC3339NanoFixed = log.RFC3339NanoFixed + +// Level is a logging level. +// +// Deprecated: use [log.Level]. +type Level = log.Level + +// Supported log levels. +const ( + // TraceLevel level. + // + // Deprecated: use [log.TraceLevel]. + TraceLevel Level = log.TraceLevel + + // DebugLevel level. + // + // Deprecated: use [log.DebugLevel]. + DebugLevel Level = log.DebugLevel + + // InfoLevel level. + // + // Deprecated: use [log.InfoLevel]. + InfoLevel Level = log.InfoLevel + + // WarnLevel level. + // + // Deprecated: use [log.WarnLevel]. + WarnLevel Level = log.WarnLevel + + // ErrorLevel level + // + // Deprecated: use [log.ErrorLevel]. + ErrorLevel Level = log.ErrorLevel + + // FatalLevel level. + // + // Deprecated: use [log.FatalLevel]. + FatalLevel Level = log.FatalLevel + + // PanicLevel level. + // + // Deprecated: use [log.PanicLevel]. + PanicLevel Level = log.PanicLevel +) + +// SetLevel sets log level globally. It returns an error if the given +// level is not supported. +// +// Deprecated: use [log.SetLevel]. +func SetLevel(level string) error { + return log.SetLevel(level) +} + +// GetLevel returns the current log level. +// +// Deprecated: use [log.GetLevel]. +func GetLevel() log.Level { + return log.GetLevel() +} + +// OutputFormat specifies a log output format. +// +// Deprecated: use [log.OutputFormat]. +type OutputFormat = log.OutputFormat + +// Supported log output formats. +const ( + // TextFormat represents the text logging format. + // + // Deprecated: use [log.TextFormat]. + TextFormat log.OutputFormat = "text" + + // JSONFormat represents the JSON logging format. + // + // Deprecated: use [log.JSONFormat]. + JSONFormat log.OutputFormat = "json" +) + +// SetFormat sets the log output format. +// +// Deprecated: use [log.SetFormat]. +func SetFormat(format OutputFormat) error { + return log.SetFormat(format) +} + +// WithLogger returns a new context with the provided logger. Use in +// combination with logger.WithField(s) for great effect. +// +// Deprecated: use [log.WithLogger]. +func WithLogger(ctx context.Context, logger *log.Entry) context.Context { + return log.WithLogger(ctx, logger) +} + +// GetLogger retrieves the current logger from the context. If no logger is +// available, the default logger is returned. +// +// Deprecated: use [log.GetLogger]. +func GetLogger(ctx context.Context) *log.Entry { + return log.GetLogger(ctx) +} diff --git a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go index fd5756516cf..d10fa9012bd 100644 --- a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go @@ -22,6 +22,7 @@ import ( "strconv" "strings" + "github.com/Microsoft/hcsshim/osversion" specs "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sys/windows" ) @@ -50,15 +51,36 @@ func (m windowsmatcher) Match(p specs.Platform) bool { match := m.defaultMatcher.Match(p) if match && m.OS == "windows" { - if strings.HasPrefix(p.OSVersion, m.osVersionPrefix) { + // HPC containers do not have OS version filled + if p.OSVersion == "" { return true } - return p.OSVersion == "" + + hostOsVersion := GetOsVersion(m.osVersionPrefix) + ctrOsVersion := GetOsVersion(p.OSVersion) + return osversion.CheckHostAndContainerCompat(hostOsVersion, ctrOsVersion) } return match } +func GetOsVersion(osVersionPrefix string) osversion.OSVersion { + parts := strings.Split(osVersionPrefix, ".") + if len(parts) < 3 { + return osversion.OSVersion{} + } + + majorVersion, _ := strconv.Atoi(parts[0]) + minorVersion, _ := strconv.Atoi(parts[1]) + buildNumber, _ := strconv.Atoi(parts[2]) + + return osversion.OSVersion{ + MajorVersion: uint8(majorVersion), + MinorVersion: uint8(minorVersion), + Build: uint16(buildNumber), + } +} + // Less sorts matched platforms in front of other platforms. // For matched platforms, it puts platforms with larger revision // number in front. diff --git a/vendor/github.com/containerd/containerd/platforms/platforms.go b/vendor/github.com/containerd/containerd/platforms/platforms.go index 8dcde7db7c8..56613b07656 100644 --- a/vendor/github.com/containerd/containerd/platforms/platforms.go +++ b/vendor/github.com/containerd/containerd/platforms/platforms.go @@ -196,6 +196,10 @@ func Parse(specifier string) (specs.Platform, error) { p.Variant = cpuVariant() } + if p.OS == "windows" { + p.OSVersion = GetWindowsOsVersion() + } + return p, nil } @@ -218,6 +222,10 @@ func Parse(specifier string) (specs.Platform, error) { p.Variant = "" } + if p.OS == "windows" { + p.OSVersion = GetWindowsOsVersion() + } + return p, nil case 3: // we have a fully specified variant, this is rare @@ -227,6 +235,10 @@ func Parse(specifier string) (specs.Platform, error) { p.Variant = "v8" } + if p.OS == "windows" { + p.OSVersion = GetWindowsOsVersion() + } + return p, nil } diff --git a/vendor/github.com/containerd/containerd/platforms/platforms_other.go b/vendor/github.com/containerd/containerd/platforms/platforms_other.go index 03f4dcd9981..59beeb3d1d9 100644 --- a/vendor/github.com/containerd/containerd/platforms/platforms_other.go +++ b/vendor/github.com/containerd/containerd/platforms/platforms_other.go @@ -28,3 +28,7 @@ func newDefaultMatcher(platform specs.Platform) Matcher { Platform: Normalize(platform), } } + +func GetWindowsOsVersion() string { + return "" +} diff --git a/vendor/github.com/containerd/containerd/platforms/platforms_windows.go b/vendor/github.com/containerd/containerd/platforms/platforms_windows.go index 950e2a2ddbb..733d18ddead 100644 --- a/vendor/github.com/containerd/containerd/platforms/platforms_windows.go +++ b/vendor/github.com/containerd/containerd/platforms/platforms_windows.go @@ -17,7 +17,10 @@ package platforms import ( + "fmt" + specs "github.com/opencontainers/image-spec/specs-go/v1" + "golang.org/x/sys/windows" ) // NewMatcher returns a Windows matcher that will match on osVersionPrefix if @@ -32,3 +35,8 @@ func newDefaultMatcher(platform specs.Platform) Matcher { }, } } + +func GetWindowsOsVersion() string { + major, minor, build := windows.RtlGetNtVersionNumbers() + return fmt.Sprintf("%d.%d.%d", major, minor, build) +} diff --git a/vendor/github.com/containerd/containerd/plugin/context.go b/vendor/github.com/containerd/containerd/plugin/context.go index cf916789881..370508d28d1 100644 --- a/vendor/github.com/containerd/containerd/plugin/context.go +++ b/vendor/github.com/containerd/containerd/plugin/context.go @@ -21,9 +21,10 @@ import ( "fmt" "path/filepath" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events/exchange" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // InitContext is used for plugin initialization @@ -133,6 +134,19 @@ func (ps *Set) Get(t Type) (interface{}, error) { return nil, fmt.Errorf("no plugins registered for %s: %w", t, errdefs.ErrNotFound) } +// GetByID returns the plugin of the given type and ID +func (ps *Set) GetByID(t Type, id string) (*Plugin, error) { + typSet, ok := ps.byTypeAndID[t] + if !ok || len(typSet) == 0 { + return nil, fmt.Errorf("no plugins registered for %s: %w", t, errdefs.ErrNotFound) + } + p, ok := typSet[id] + if !ok { + return nil, fmt.Errorf("no plugins registered for %s %q: %w", t, id, errdefs.ErrNotFound) + } + return p, nil +} + // GetAll returns all initialized plugins func (ps *Set) GetAll() []*Plugin { return ps.ordered diff --git a/vendor/github.com/containerd/containerd/plugin/plugin.go b/vendor/github.com/containerd/containerd/plugin/plugin.go index 082f3178b0d..f1be877fcb2 100644 --- a/vendor/github.com/containerd/containerd/plugin/plugin.go +++ b/vendor/github.com/containerd/containerd/plugin/plugin.go @@ -90,6 +90,8 @@ const ( SandboxStorePlugin Type = "io.containerd.sandbox.store.v1" // SandboxControllerPlugin implements a sandbox controller SandboxControllerPlugin Type = "io.containerd.sandbox.controller.v1" + // WarningPlugin implements a warning service + WarningPlugin Type = "io.containerd.warning.v1" ) const ( @@ -98,7 +100,8 @@ const ( // RuntimeRuncV1 is the runc runtime that supports a single container RuntimeRuncV1 = "io.containerd.runc.v1" // RuntimeRuncV2 is the runc runtime that supports multiple containers per shim - RuntimeRuncV2 = "io.containerd.runc.v2" + RuntimeRuncV2 = "io.containerd.runc.v2" + DeprecationsPlugin = "deprecations" ) // Registration contains information for registering a plugin @@ -143,7 +146,7 @@ var register = struct { }{} // Load loads all plugins at the provided path into containerd -func Load(path string) (err error) { +func Load(path string) (count int, err error) { defer func() { if v := recover(); v != nil { rerr, ok := v.(error) diff --git a/vendor/github.com/containerd/containerd/plugin/plugin_go18.go b/vendor/github.com/containerd/containerd/plugin/plugin_go18.go index 0ee442d9553..0671630a202 100644 --- a/vendor/github.com/containerd/containerd/plugin/plugin_go18.go +++ b/vendor/github.com/containerd/containerd/plugin/plugin_go18.go @@ -25,12 +25,13 @@ import ( "runtime" ) -// loadPlugins loads all plugins for the OS and Arch -// that containerd is built for inside the provided path -func loadPlugins(path string) error { +// loadPlugins loads all plugins for the OS and Arch that containerd is built +// for inside the provided path and returns the count of successfully-loaded +// plugins +func loadPlugins(path string) (int, error) { abs, err := filepath.Abs(path) if err != nil { - return err + return 0, err } pattern := filepath.Join(abs, fmt.Sprintf( "*-%s-%s.%s", @@ -40,14 +41,16 @@ func loadPlugins(path string) error { )) libs, err := filepath.Glob(pattern) if err != nil { - return err + return 0, err } + loaded := 0 for _, lib := range libs { if _, err := plugin.Open(lib); err != nil { - return err + return loaded, err } + loaded++ } - return nil + return loaded, nil } // getLibExt returns a platform specific lib extension for diff --git a/vendor/github.com/containerd/containerd/plugin/plugin_other.go b/vendor/github.com/containerd/containerd/plugin/plugin_other.go index c0b53a6b4d1..b0896d6908d 100644 --- a/vendor/github.com/containerd/containerd/plugin/plugin_other.go +++ b/vendor/github.com/containerd/containerd/plugin/plugin_other.go @@ -18,7 +18,7 @@ package plugin -func loadPlugins(path string) error { +func loadPlugins(path string) (int, error) { // plugins not supported until 1.8 - return nil + return 0, nil } diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/version/version.go index 9ef6f6b0234..088c7f81b4d 100644 --- a/vendor/github.com/containerd/containerd/version/version.go +++ b/vendor/github.com/containerd/containerd/version/version.go @@ -23,7 +23,7 @@ var ( Package = "github.com/containerd/containerd" // Version holds the complete version number. Filled in at linking time. - Version = "1.7.5+unknown" + Version = "1.7.9+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. diff --git a/vendor/github.com/containerd/log/.golangci.yml b/vendor/github.com/containerd/log/.golangci.yml new file mode 100644 index 00000000000..a695775df49 --- /dev/null +++ b/vendor/github.com/containerd/log/.golangci.yml @@ -0,0 +1,30 @@ +linters: + enable: + - exportloopref # Checks for pointers to enclosing loop variables + - gofmt + - goimports + - gosec + - ineffassign + - misspell + - nolintlint + - revive + - staticcheck + - tenv # Detects using os.Setenv instead of t.Setenv since Go 1.17 + - unconvert + - unused + - vet + - dupword # Checks for duplicate words in the source code + disable: + - errcheck + +run: + timeout: 5m + skip-dirs: + - api + - cluster + - design + - docs + - docs/man + - releases + - reports + - test # e2e scripts diff --git a/vendor/github.com/containerd/log/LICENSE b/vendor/github.com/containerd/log/LICENSE new file mode 100644 index 00000000000..584149b6ee2 --- /dev/null +++ b/vendor/github.com/containerd/log/LICENSE @@ -0,0 +1,191 @@ + + 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 The containerd 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 + + 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/containerd/log/README.md b/vendor/github.com/containerd/log/README.md new file mode 100644 index 00000000000..00e08498801 --- /dev/null +++ b/vendor/github.com/containerd/log/README.md @@ -0,0 +1,17 @@ +# log + +A Go package providing a common logging interface across containerd repositories and a way for clients to use and configure logging in containerd packages. + +This package is not intended to be used as a standalone logging package outside of the containerd ecosystem and is intended as an interface wrapper around a logging implementation. +In the future this package may be replaced with a common go logging interface. + +## Project details + +**log** is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). +As a containerd sub-project, you will find the: + * [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md), + * [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS), + * and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md) + +information in our [`containerd/project`](https://github.com/containerd/project) repository. + diff --git a/vendor/github.com/containerd/containerd/log/context.go b/vendor/github.com/containerd/log/context.go similarity index 98% rename from vendor/github.com/containerd/containerd/log/context.go rename to vendor/github.com/containerd/log/context.go index 14ff2a59c57..20153066f3a 100644 --- a/vendor/github.com/containerd/containerd/log/context.go +++ b/vendor/github.com/containerd/log/context.go @@ -44,6 +44,12 @@ import ( "github.com/sirupsen/logrus" ) +// G is a shorthand for [GetLogger]. +// +// We may want to define this locally to a package to get package tagged log +// messages. +var G = GetLogger + // L is an alias for the standard logger. var L = &Entry{ Logger: logrus.StandardLogger(), @@ -169,11 +175,6 @@ func WithLogger(ctx context.Context, logger *Entry) context.Context { // GetLogger retrieves the current logger from the context. If no logger is // available, the default logger is returned. func GetLogger(ctx context.Context) *Entry { - return G(ctx) -} - -// G is a shorthand for [GetLogger]. -func G(ctx context.Context) *Entry { if logger := ctx.Value(loggerKey{}); logger != nil { return logger.(*Entry) } diff --git a/vendor/github.com/containerd/nri/pkg/adaptation/api.go b/vendor/github.com/containerd/nri/pkg/adaptation/api.go index bc8ada0655b..49240598fa9 100644 --- a/vendor/github.com/containerd/nri/pkg/adaptation/api.go +++ b/vendor/github.com/containerd/nri/pkg/adaptation/api.go @@ -81,6 +81,7 @@ type ( HugepageLimit = api.HugepageLimit Hooks = api.Hooks Hook = api.Hook + POSIXRlimit = api.POSIXRlimit EventMask = api.EventMask ) diff --git a/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go b/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go index c4be402ea21..9b2a487eab7 100644 --- a/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go +++ b/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go @@ -119,7 +119,7 @@ func (r *Adaptation) newLaunchedPlugin(dir, idx, base, cfg string) (p *plugin, r cmd := exec.Command(filepath.Join(dir, name)) cmd.ExtraFiles = []*os.File{peerFile} cmd.Env = []string{ - api.PluginNameEnvVar + "=" + name, + api.PluginNameEnvVar + "=" + base, api.PluginIdxEnvVar + "=" + idx, api.PluginSocketEnvVar + "=3", } diff --git a/vendor/github.com/containerd/nri/pkg/adaptation/result.go b/vendor/github.com/containerd/nri/pkg/adaptation/result.go index a6188ef55a4..80f150848c3 100644 --- a/vendor/github.com/containerd/nri/pkg/adaptation/result.go +++ b/vendor/github.com/containerd/nri/pkg/adaptation/result.go @@ -56,6 +56,9 @@ func collectCreateContainerResult(request *CreateContainerRequest) *result { if request.Container.Hooks == nil { request.Container.Hooks = &Hooks{} } + if request.Container.Rlimits == nil { + request.Container.Rlimits = []*POSIXRlimit{} + } if request.Container.Linux == nil { request.Container.Linux = &LinuxContainer{} } @@ -85,6 +88,7 @@ func collectCreateContainerResult(request *CreateContainerRequest) *result { Mounts: []*Mount{}, Env: []*KeyValue{}, Hooks: &Hooks{}, + Rlimits: []*POSIXRlimit{}, Linux: &LinuxContainerAdjustment{ Devices: []*LinuxDevice{}, Resources: &LinuxResources{ @@ -210,6 +214,9 @@ func (r *result) adjust(rpl *ContainerAdjustment, plugin string) error { return err } } + if err := r.adjustRlimits(rpl.Rlimits, plugin); err != nil { + return err + } return nil } @@ -659,6 +666,19 @@ func (r *result) adjustCgroupsPath(path, plugin string) error { return nil } +func (r *result) adjustRlimits(rlimits []*POSIXRlimit, plugin string) error { + create, id, adjust := r.request.create, r.request.create.Container.Id, r.reply.adjust + for _, l := range rlimits { + if err := r.owners.claimRlimits(id, l.Type, plugin); err != nil { + return err + } + + create.Container.Rlimits = append(create.Container.Rlimits, l) + adjust.Rlimits = append(adjust.Rlimits, l) + } + return nil +} + func (r *result) updateResources(reply, u *ContainerUpdate, plugin string) error { if u.Linux == nil || u.Linux.Resources == nil { return nil @@ -873,6 +893,7 @@ type owners struct { rdtClass string unified map[string]string cgroupsPath string + rlimits map[string]string } func (ro resultOwners) ownersFor(id string) *owners { @@ -980,6 +1001,10 @@ func (ro resultOwners) claimCgroupsPath(id, plugin string) error { return ro.ownersFor(id).claimCgroupsPath(plugin) } +func (ro resultOwners) claimRlimits(id, typ, plugin string) error { + return ro.ownersFor(id).claimRlimit(typ, plugin) +} + func (o *owners) claimAnnotation(key, plugin string) error { if o.annotations == nil { o.annotations = make(map[string]string) @@ -1183,6 +1208,17 @@ func (o *owners) claimUnified(key, plugin string) error { return nil } +func (o *owners) claimRlimit(typ, plugin string) error { + if o.rlimits == nil { + o.rlimits = make(map[string]string) + } + if other, taken := o.rlimits[typ]; taken { + return conflict(plugin, other, "rlimit", typ) + } + o.rlimits[typ] = plugin + return nil +} + func (o *owners) claimCgroupsPath(plugin string) error { if other := o.cgroupsPath; other != "" { return conflict(plugin, other, "cgroups path") diff --git a/vendor/github.com/containerd/nri/pkg/api/adjustment.go b/vendor/github.com/containerd/nri/pkg/api/adjustment.go index c44b4aa5f5a..0f1fcd36e15 100644 --- a/vendor/github.com/containerd/nri/pkg/api/adjustment.go +++ b/vendor/github.com/containerd/nri/pkg/api/adjustment.go @@ -103,6 +103,15 @@ func (a *ContainerAdjustment) AddHooks(h *Hooks) { } } +func (a *ContainerAdjustment) AddRlimit(typ string, hard, soft uint64) { + a.initRlimits() + a.Rlimits = append(a.Rlimits, &POSIXRlimit{ + Type: typ, + Hard: hard, + Soft: soft, + }) +} + // AddDevice records the addition of the given device to a container. func (a *ContainerAdjustment) AddDevice(d *LinuxDevice) { a.initLinux() @@ -260,6 +269,12 @@ func (a *ContainerAdjustment) initHooks() { } } +func (a *ContainerAdjustment) initRlimits() { + if a.Rlimits == nil { + a.Rlimits = []*POSIXRlimit{} + } +} + func (a *ContainerAdjustment) initLinux() { if a.Linux == nil { a.Linux = &LinuxContainerAdjustment{} diff --git a/vendor/github.com/containerd/nri/pkg/api/api.pb.go b/vendor/github.com/containerd/nri/pkg/api/api.pb.go index 16b94120444..d06c02edd9c 100644 --- a/vendor/github.com/containerd/nri/pkg/api/api.pb.go +++ b/vendor/github.com/containerd/nri/pkg/api/api.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 +// protoc-gen-go v1.28.1 // protoc v3.20.1 // source: pkg/api/api.proto @@ -1229,6 +1229,7 @@ type Container struct { Hooks *Hooks `protobuf:"bytes,10,opt,name=hooks,proto3" json:"hooks,omitempty"` Linux *LinuxContainer `protobuf:"bytes,11,opt,name=linux,proto3" json:"linux,omitempty"` Pid uint32 `protobuf:"varint,12,opt,name=pid,proto3" json:"pid,omitempty"` // for NRI v1 emulation + Rlimits []*POSIXRlimit `protobuf:"bytes,13,rep,name=rlimits,proto3" json:"rlimits,omitempty"` } func (x *Container) Reset() { @@ -1347,6 +1348,13 @@ func (x *Container) GetPid() uint32 { return 0 } +func (x *Container) GetRlimits() []*POSIXRlimit { + if x != nil { + return x.Rlimits + } + return nil +} + // A container mount. type Mount struct { state protoimpl.MessageState @@ -2243,6 +2251,70 @@ func (x *HugepageLimit) GetLimit() uint64 { return 0 } +// Container rlimits +type POSIXRlimit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Hard uint64 `protobuf:"varint,2,opt,name=hard,proto3" json:"hard,omitempty"` + Soft uint64 `protobuf:"varint,3,opt,name=soft,proto3" json:"soft,omitempty"` +} + +func (x *POSIXRlimit) Reset() { + *x = POSIXRlimit{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_api_api_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *POSIXRlimit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*POSIXRlimit) ProtoMessage() {} + +func (x *POSIXRlimit) ProtoReflect() protoreflect.Message { + mi := &file_pkg_api_api_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use POSIXRlimit.ProtoReflect.Descriptor instead. +func (*POSIXRlimit) Descriptor() ([]byte, []int) { + return file_pkg_api_api_proto_rawDescGZIP(), []int{29} +} + +func (x *POSIXRlimit) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *POSIXRlimit) GetHard() uint64 { + if x != nil { + return x.Hard + } + return 0 +} + +func (x *POSIXRlimit) GetSoft() uint64 { + if x != nil { + return x.Soft + } + return 0 +} + // Requested adjustments to a container being created. type ContainerAdjustment struct { state protoimpl.MessageState @@ -2254,12 +2326,13 @@ type ContainerAdjustment struct { Env []*KeyValue `protobuf:"bytes,4,rep,name=env,proto3" json:"env,omitempty"` Hooks *Hooks `protobuf:"bytes,5,opt,name=hooks,proto3" json:"hooks,omitempty"` Linux *LinuxContainerAdjustment `protobuf:"bytes,6,opt,name=linux,proto3" json:"linux,omitempty"` + Rlimits []*POSIXRlimit `protobuf:"bytes,7,rep,name=rlimits,proto3" json:"rlimits,omitempty"` } func (x *ContainerAdjustment) Reset() { *x = ContainerAdjustment{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[29] + mi := &file_pkg_api_api_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2272,7 +2345,7 @@ func (x *ContainerAdjustment) String() string { func (*ContainerAdjustment) ProtoMessage() {} func (x *ContainerAdjustment) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[29] + mi := &file_pkg_api_api_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2285,7 +2358,7 @@ func (x *ContainerAdjustment) ProtoReflect() protoreflect.Message { // Deprecated: Use ContainerAdjustment.ProtoReflect.Descriptor instead. func (*ContainerAdjustment) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{29} + return file_pkg_api_api_proto_rawDescGZIP(), []int{30} } func (x *ContainerAdjustment) GetAnnotations() map[string]string { @@ -2323,6 +2396,13 @@ func (x *ContainerAdjustment) GetLinux() *LinuxContainerAdjustment { return nil } +func (x *ContainerAdjustment) GetRlimits() []*POSIXRlimit { + if x != nil { + return x.Rlimits + } + return nil +} + // Adjustments to (linux) resources. type LinuxContainerAdjustment struct { state protoimpl.MessageState @@ -2337,7 +2417,7 @@ type LinuxContainerAdjustment struct { func (x *LinuxContainerAdjustment) Reset() { *x = LinuxContainerAdjustment{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[30] + mi := &file_pkg_api_api_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2350,7 +2430,7 @@ func (x *LinuxContainerAdjustment) String() string { func (*LinuxContainerAdjustment) ProtoMessage() {} func (x *LinuxContainerAdjustment) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[30] + mi := &file_pkg_api_api_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2363,7 +2443,7 @@ func (x *LinuxContainerAdjustment) ProtoReflect() protoreflect.Message { // Deprecated: Use LinuxContainerAdjustment.ProtoReflect.Descriptor instead. func (*LinuxContainerAdjustment) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{30} + return file_pkg_api_api_proto_rawDescGZIP(), []int{31} } func (x *LinuxContainerAdjustment) GetDevices() []*LinuxDevice { @@ -2401,7 +2481,7 @@ type ContainerUpdate struct { func (x *ContainerUpdate) Reset() { *x = ContainerUpdate{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[31] + mi := &file_pkg_api_api_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2414,7 +2494,7 @@ func (x *ContainerUpdate) String() string { func (*ContainerUpdate) ProtoMessage() {} func (x *ContainerUpdate) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[31] + mi := &file_pkg_api_api_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2427,7 +2507,7 @@ func (x *ContainerUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use ContainerUpdate.ProtoReflect.Descriptor instead. func (*ContainerUpdate) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{31} + return file_pkg_api_api_proto_rawDescGZIP(), []int{32} } func (x *ContainerUpdate) GetContainerId() string { @@ -2463,7 +2543,7 @@ type LinuxContainerUpdate struct { func (x *LinuxContainerUpdate) Reset() { *x = LinuxContainerUpdate{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[32] + mi := &file_pkg_api_api_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2476,7 +2556,7 @@ func (x *LinuxContainerUpdate) String() string { func (*LinuxContainerUpdate) ProtoMessage() {} func (x *LinuxContainerUpdate) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[32] + mi := &file_pkg_api_api_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2489,7 +2569,7 @@ func (x *LinuxContainerUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use LinuxContainerUpdate.ProtoReflect.Descriptor instead. func (*LinuxContainerUpdate) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{32} + return file_pkg_api_api_proto_rawDescGZIP(), []int{33} } func (x *LinuxContainerUpdate) GetResources() *LinuxResources { @@ -2514,7 +2594,7 @@ type ContainerEviction struct { func (x *ContainerEviction) Reset() { *x = ContainerEviction{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[33] + mi := &file_pkg_api_api_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2527,7 +2607,7 @@ func (x *ContainerEviction) String() string { func (*ContainerEviction) ProtoMessage() {} func (x *ContainerEviction) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[33] + mi := &file_pkg_api_api_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2540,7 +2620,7 @@ func (x *ContainerEviction) ProtoReflect() protoreflect.Message { // Deprecated: Use ContainerEviction.ProtoReflect.Descriptor instead. func (*ContainerEviction) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{33} + return file_pkg_api_api_proto_rawDescGZIP(), []int{34} } func (x *ContainerEviction) GetContainerId() string { @@ -2570,7 +2650,7 @@ type KeyValue struct { func (x *KeyValue) Reset() { *x = KeyValue{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[34] + mi := &file_pkg_api_api_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2583,7 +2663,7 @@ func (x *KeyValue) String() string { func (*KeyValue) ProtoMessage() {} func (x *KeyValue) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[34] + mi := &file_pkg_api_api_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2596,7 +2676,7 @@ func (x *KeyValue) ProtoReflect() protoreflect.Message { // Deprecated: Use KeyValue.ProtoReflect.Descriptor instead. func (*KeyValue) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{34} + return file_pkg_api_api_proto_rawDescGZIP(), []int{35} } func (x *KeyValue) GetKey() string { @@ -2625,7 +2705,7 @@ type OptionalString struct { func (x *OptionalString) Reset() { *x = OptionalString{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[35] + mi := &file_pkg_api_api_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2638,7 +2718,7 @@ func (x *OptionalString) String() string { func (*OptionalString) ProtoMessage() {} func (x *OptionalString) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[35] + mi := &file_pkg_api_api_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2651,7 +2731,7 @@ func (x *OptionalString) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalString.ProtoReflect.Descriptor instead. func (*OptionalString) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{35} + return file_pkg_api_api_proto_rawDescGZIP(), []int{36} } func (x *OptionalString) GetValue() string { @@ -2673,7 +2753,7 @@ type OptionalInt struct { func (x *OptionalInt) Reset() { *x = OptionalInt{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[36] + mi := &file_pkg_api_api_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2686,7 +2766,7 @@ func (x *OptionalInt) String() string { func (*OptionalInt) ProtoMessage() {} func (x *OptionalInt) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[36] + mi := &file_pkg_api_api_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2699,7 +2779,7 @@ func (x *OptionalInt) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalInt.ProtoReflect.Descriptor instead. func (*OptionalInt) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{36} + return file_pkg_api_api_proto_rawDescGZIP(), []int{37} } func (x *OptionalInt) GetValue() int64 { @@ -2721,7 +2801,7 @@ type OptionalInt32 struct { func (x *OptionalInt32) Reset() { *x = OptionalInt32{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[37] + mi := &file_pkg_api_api_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2734,7 +2814,7 @@ func (x *OptionalInt32) String() string { func (*OptionalInt32) ProtoMessage() {} func (x *OptionalInt32) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[37] + mi := &file_pkg_api_api_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2747,7 +2827,7 @@ func (x *OptionalInt32) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalInt32.ProtoReflect.Descriptor instead. func (*OptionalInt32) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{37} + return file_pkg_api_api_proto_rawDescGZIP(), []int{38} } func (x *OptionalInt32) GetValue() int32 { @@ -2769,7 +2849,7 @@ type OptionalUInt32 struct { func (x *OptionalUInt32) Reset() { *x = OptionalUInt32{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[38] + mi := &file_pkg_api_api_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2782,7 +2862,7 @@ func (x *OptionalUInt32) String() string { func (*OptionalUInt32) ProtoMessage() {} func (x *OptionalUInt32) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[38] + mi := &file_pkg_api_api_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2795,7 +2875,7 @@ func (x *OptionalUInt32) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalUInt32.ProtoReflect.Descriptor instead. func (*OptionalUInt32) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{38} + return file_pkg_api_api_proto_rawDescGZIP(), []int{39} } func (x *OptionalUInt32) GetValue() uint32 { @@ -2817,7 +2897,7 @@ type OptionalInt64 struct { func (x *OptionalInt64) Reset() { *x = OptionalInt64{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[39] + mi := &file_pkg_api_api_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2830,7 +2910,7 @@ func (x *OptionalInt64) String() string { func (*OptionalInt64) ProtoMessage() {} func (x *OptionalInt64) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[39] + mi := &file_pkg_api_api_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2843,7 +2923,7 @@ func (x *OptionalInt64) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalInt64.ProtoReflect.Descriptor instead. func (*OptionalInt64) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{39} + return file_pkg_api_api_proto_rawDescGZIP(), []int{40} } func (x *OptionalInt64) GetValue() int64 { @@ -2865,7 +2945,7 @@ type OptionalUInt64 struct { func (x *OptionalUInt64) Reset() { *x = OptionalUInt64{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[40] + mi := &file_pkg_api_api_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2878,7 +2958,7 @@ func (x *OptionalUInt64) String() string { func (*OptionalUInt64) ProtoMessage() {} func (x *OptionalUInt64) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[40] + mi := &file_pkg_api_api_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2891,7 +2971,7 @@ func (x *OptionalUInt64) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalUInt64.ProtoReflect.Descriptor instead. func (*OptionalUInt64) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{40} + return file_pkg_api_api_proto_rawDescGZIP(), []int{41} } func (x *OptionalUInt64) GetValue() uint64 { @@ -2913,7 +2993,7 @@ type OptionalBool struct { func (x *OptionalBool) Reset() { *x = OptionalBool{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[41] + mi := &file_pkg_api_api_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2926,7 +3006,7 @@ func (x *OptionalBool) String() string { func (*OptionalBool) ProtoMessage() {} func (x *OptionalBool) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[41] + mi := &file_pkg_api_api_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2939,7 +3019,7 @@ func (x *OptionalBool) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalBool.ProtoReflect.Descriptor instead. func (*OptionalBool) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{41} + return file_pkg_api_api_proto_rawDescGZIP(), []int{42} } func (x *OptionalBool) GetValue() bool { @@ -2961,7 +3041,7 @@ type OptionalFileMode struct { func (x *OptionalFileMode) Reset() { *x = OptionalFileMode{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_api_api_proto_msgTypes[42] + mi := &file_pkg_api_api_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2974,7 +3054,7 @@ func (x *OptionalFileMode) String() string { func (*OptionalFileMode) ProtoMessage() {} func (x *OptionalFileMode) ProtoReflect() protoreflect.Message { - mi := &file_pkg_api_api_proto_msgTypes[42] + mi := &file_pkg_api_api_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2987,7 +3067,7 @@ func (x *OptionalFileMode) ProtoReflect() protoreflect.Message { // Deprecated: Use OptionalFileMode.ProtoReflect.Descriptor instead. func (*OptionalFileMode) Descriptor() ([]byte, []int) { - return file_pkg_api_api_proto_rawDescGZIP(), []int{42} + return file_pkg_api_api_proto_rawDescGZIP(), []int{43} } func (x *OptionalFileMode) GetValue() uint32 { @@ -3175,7 +3255,7 @@ var file_pkg_api_api_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x81, 0x05, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xbe, 0x05, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x6f, 0x64, 0x5f, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6f, 0x64, @@ -3207,374 +3287,386 @@ var file_pkg_api_api_proto_rawDesc = []byte{ 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x12, 0x10, 0x0a, 0x03, - 0x70, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x1a, 0x39, - 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6f, 0x0a, 0x05, 0x4d, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x80, 0x03, 0x0a, 0x05, 0x48, - 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x36, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, + 0x70, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x3b, + 0x0a, 0x07, 0x72, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x4f, 0x53, 0x49, 0x58, 0x52, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x52, 0x07, 0x72, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6f, 0x0a, 0x05, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x80, 0x03, 0x0a, 0x05, 0x48, 0x6f, 0x6f, 0x6b, + 0x73, 0x12, 0x36, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, + 0x08, 0x70, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x41, 0x0a, 0x0e, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x0d, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x10, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, - 0x6f, 0x6b, 0x52, 0x08, 0x70, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x41, 0x0a, 0x0e, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, + 0x6f, 0x6b, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, + 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x70, 0x6f, 0x73, 0x74, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, + 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x09, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x12, 0x36, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x74, 0x6f, 0x70, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, - 0x52, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, - 0x45, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, - 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x0e, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x70, - 0x6f, 0x73, 0x74, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x52, 0x09, 0x70, 0x6f, 0x73, 0x74, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x36, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x74, 0x6f, - 0x70, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, - 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, - 0x6f, 0x6f, 0x6b, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x74, 0x6f, 0x70, 0x22, 0x7d, 0x0a, - 0x04, 0x48, 0x6f, 0x6f, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x10, 0x0a, - 0x03, 0x65, 0x6e, 0x76, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, - 0x3b, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x49, 0x6e, 0x74, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xc1, 0x02, 0x0a, - 0x0e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, - 0x44, 0x0a, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, - 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, - 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x52, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x73, 0x74, 0x6f, 0x70, 0x22, 0x7d, 0x0a, 0x04, 0x48, 0x6f, + 0x6f, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, + 0x76, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x3b, 0x0a, 0x07, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, - 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x50, 0x61, 0x74, 0x68, - 0x22, 0x38, 0x0a, 0x0e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x96, 0x02, 0x0a, 0x0b, 0x4c, - 0x69, 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x43, - 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x26, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, - 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x36, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xc1, 0x02, 0x0a, 0x0e, 0x4c, 0x69, + 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x0a, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x03, 0x67, - 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, - 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x03, - 0x67, 0x69, 0x64, 0x22, 0xcb, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x43, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x39, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x39, - 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, - 0x36, 0x34, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x22, 0xa5, 0x04, 0x0a, 0x0e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, - 0x78, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, - 0x30, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, - 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x50, 0x55, 0x52, 0x03, 0x63, 0x70, - 0x75, 0x12, 0x4c, 0x0a, 0x0f, 0x68, 0x75, 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x48, 0x75, 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, - 0x0e, 0x68, 0x75, 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, - 0x49, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6f, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x69, 0x6f, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x64, - 0x74, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x52, 0x08, 0x72, 0x64, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x4b, 0x0a, - 0x07, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, + 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x52, 0x0b, 0x6f, + 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x50, 0x61, 0x74, 0x68, 0x22, 0x38, 0x0a, + 0x0e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x96, 0x02, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x75, + 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, + 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x43, 0x0a, 0x09, 0x66, + 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x2e, 0x55, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x07, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6e, 0x72, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, + 0x6c, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x36, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, + 0x74, 0x33, 0x32, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x52, 0x03, 0x67, 0x69, 0x64, + 0x22, 0xcb, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x43, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x39, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, + 0x6e, 0x74, 0x36, 0x34, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x39, 0x0a, 0x05, 0x6d, + 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, + 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, + 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0xa5, + 0x04, 0x0a, 0x0e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x12, 0x39, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x4d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x30, 0x0a, 0x03, + 0x63, 0x70, 0x75, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, 0x72, 0x69, 0x2e, + 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x50, 0x55, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x4c, + 0x0a, 0x0f, 0x68, 0x75, 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, + 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, + 0x75, 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x0e, 0x68, 0x75, + 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x0d, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6f, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x69, 0x6f, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x64, 0x74, 0x5f, 0x63, + 0x6c, 0x61, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, + 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x52, 0x08, 0x72, 0x64, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x4b, 0x0a, 0x07, 0x75, 0x6e, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x3a, 0x0a, - 0x0c, 0x55, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaa, 0x04, 0x0a, 0x0b, 0x4c, 0x69, - 0x6e, 0x75, 0x78, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x6c, 0x69, 0x6d, - 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, + 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x2e, 0x55, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, + 0x75, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x05, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x12, 0x45, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, - 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x0b, - 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x04, 0x73, - 0x77, 0x61, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, - 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x04, - 0x73, 0x77, 0x61, 0x70, 0x12, 0x3b, 0x0a, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, - 0x6c, 0x12, 0x42, 0x0a, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x74, 0x63, 0x70, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, + 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x55, 0x6e, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaa, 0x04, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x75, 0x78, + 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x09, 0x6b, 0x65, 0x72, 0x6e, - 0x65, 0x6c, 0x54, 0x63, 0x70, 0x12, 0x44, 0x0a, 0x0a, 0x73, 0x77, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, - 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, - 0x0a, 0x73, 0x77, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x50, 0x0a, 0x12, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x6b, 0x69, 0x6c, 0x6c, 0x65, - 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, - 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x10, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x4f, 0x6f, 0x6d, 0x4b, 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x47, 0x0a, - 0x0d, 0x75, 0x73, 0x65, 0x5f, 0x68, 0x69, 0x65, 0x72, 0x61, 0x72, 0x63, 0x68, 0x79, 0x18, 0x08, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x12, 0x45, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x0b, 0x72, 0x65, 0x73, + 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x04, 0x73, 0x77, 0x61, + 0x70, 0x12, 0x3b, 0x0a, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, 0x42, + 0x0a, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5f, 0x74, 0x63, 0x70, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x09, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x54, + 0x63, 0x70, 0x12, 0x44, 0x0a, 0x0a, 0x73, 0x77, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x0a, 0x73, 0x77, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x50, 0x0a, 0x12, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x6b, 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x48, 0x69, 0x65, - 0x72, 0x61, 0x72, 0x63, 0x68, 0x79, 0x22, 0x88, 0x03, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x75, 0x78, - 0x43, 0x50, 0x55, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x73, 0x12, 0x39, 0x0a, 0x05, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x10, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, + 0x65, 0x4f, 0x6f, 0x6d, 0x4b, 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x47, 0x0a, 0x0d, 0x75, 0x73, + 0x65, 0x5f, 0x68, 0x69, 0x65, 0x72, 0x61, 0x72, 0x63, 0x68, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x42, 0x6f, 0x6f, 0x6c, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x48, 0x69, 0x65, 0x72, 0x61, 0x72, + 0x63, 0x68, 0x79, 0x22, 0x88, 0x03, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x50, 0x55, + 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x05, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x06, - 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, - 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, - 0x36, 0x34, 0x52, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x4e, 0x0a, 0x10, 0x72, 0x65, - 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x6c, 0x74, - 0x69, 0x6d, 0x65, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0f, 0x72, 0x65, - 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x0e, 0x72, 0x65, 0x61, 0x6c, 0x74, - 0x69, 0x6d, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x70, 0x75, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x70, 0x75, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x6d, 0x65, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, - 0x73, 0x22, 0x42, 0x0a, 0x0d, 0x48, 0x75, 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x93, 0x03, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x5c, 0x0a, - 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x33, 0x0a, 0x06, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x72, - 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, - 0x12, 0x30, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x39, + 0x0a, 0x05, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x65, - 0x6e, 0x76, 0x12, 0x31, 0x0a, 0x05, 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x05, - 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x44, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, - 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x1a, 0x3e, 0x0a, 0x10, 0x41, - 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe, 0x01, 0x0a, 0x18, - 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x41, 0x64, - 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, + 0x36, 0x34, 0x52, 0x05, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x06, 0x70, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, - 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x50, 0x61, 0x74, 0x68, 0x22, 0x9d, 0x01, 0x0a, - 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x05, - 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, - 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x22, 0x5a, 0x0a, 0x14, - 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, - 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, - 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4e, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x45, 0x76, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x32, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x26, 0x0a, 0x0e, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x49, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x25, 0x0a, 0x0d, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x26, 0x0a, 0x0e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x25, 0x0a, 0x0d, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0x26, 0x0a, 0x0e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x24, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x28, 0x0a, - 0x10, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x9c, 0x02, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, - 0x0a, 0x0f, 0x52, 0x55, 0x4e, 0x5f, 0x50, 0x4f, 0x44, 0x5f, 0x53, 0x41, 0x4e, 0x44, 0x42, 0x4f, - 0x58, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x50, 0x4f, 0x44, 0x5f, - 0x53, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x58, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x4d, - 0x4f, 0x56, 0x45, 0x5f, 0x50, 0x4f, 0x44, 0x5f, 0x53, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x58, 0x10, - 0x03, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, - 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x4f, 0x53, 0x54, 0x5f, - 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, - 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x54, - 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x4f, 0x53, 0x54, 0x5f, - 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, - 0x07, 0x12, 0x14, 0x0a, 0x10, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, - 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x08, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x4f, 0x53, 0x54, 0x5f, - 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, - 0x10, 0x09, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, - 0x49, 0x4e, 0x45, 0x52, 0x10, 0x0a, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, - 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x0b, 0x12, 0x08, 0x0a, 0x04, - 0x4c, 0x41, 0x53, 0x54, 0x10, 0x0c, 0x2a, 0x82, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, - 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x43, 0x52, - 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x4e, 0x54, 0x41, - 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x44, 0x10, 0x02, 0x12, 0x15, 0x0a, - 0x11, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, - 0x4e, 0x47, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, - 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x04, 0x32, 0xd8, 0x01, 0x0a, 0x07, - 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x2b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, + 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, + 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x4e, 0x0a, 0x10, 0x72, 0x65, 0x61, 0x6c, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x23, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x0f, 0x72, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, + 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0f, 0x72, 0x65, 0x61, 0x6c, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x0e, 0x72, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, + 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x70, 0x75, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x70, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, + 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x73, 0x22, 0x42, + 0x0a, 0x0d, 0x48, 0x75, 0x67, 0x65, 0x70, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x22, 0x49, 0x0a, 0x0b, 0x50, 0x4f, 0x53, 0x49, 0x58, 0x52, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x04, 0x68, 0x61, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6f, 0x66, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x6f, 0x66, 0x74, 0x22, 0xd0, 0x03, + 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x41, 0x64, 0x6a, 0x75, 0x73, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x5c, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x6e, 0x72, 0x69, + 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x41, 0x64, 0x6a, 0x75, 0x73, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x33, 0x0a, 0x06, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x52, 0x06, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4b, 0x65, 0x79, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x31, 0x0a, 0x05, 0x68, 0x6f, + 0x6f, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x71, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, - 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xae, 0x05, 0x0a, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x12, 0x5c, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x12, 0x26, - 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x62, 0x0a, 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x12, 0x28, - 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, - 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, - 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x6e, + 0x2e, 0x48, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x05, 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x44, 0x0a, + 0x05, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x6e, 0x0a, 0x0f, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x6e, + 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x6c, 0x69, + 0x6e, 0x75, 0x78, 0x12, 0x3b, 0x0a, 0x07, 0x72, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x4f, 0x53, 0x49, + 0x58, 0x52, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x07, 0x72, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, + 0x1a, 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0xbe, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x0a, + 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x50, 0x61, 0x74, + 0x68, 0x22, 0x9d, 0x01, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x75, + 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, + 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, + 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, + 0x65, 0x22, 0x5a, 0x0a, 0x14, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x6e, 0x72, 0x69, - 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0f, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x6e, + 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4e, 0x0a, + 0x11, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x45, 0x76, 0x69, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x32, 0x0a, + 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x26, 0x0a, 0x0e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x25, + 0x0a, 0x0d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x26, 0x0a, 0x0e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x25, 0x0a, + 0x0d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0x26, 0x0a, 0x0e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x24, 0x0a, 0x0c, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x28, 0x0a, 0x10, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, + 0x6c, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a, 0x9c, 0x02, 0x0a, + 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x55, 0x4e, 0x5f, 0x50, 0x4f, 0x44, 0x5f, 0x53, + 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x58, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x4f, 0x50, + 0x5f, 0x50, 0x4f, 0x44, 0x5f, 0x53, 0x41, 0x4e, 0x44, 0x42, 0x4f, 0x58, 0x10, 0x02, 0x12, 0x16, + 0x0a, 0x12, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x50, 0x4f, 0x44, 0x5f, 0x53, 0x41, 0x4e, + 0x44, 0x42, 0x4f, 0x58, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, + 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, + 0x50, 0x4f, 0x53, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, + 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x52, 0x54, + 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, + 0x50, 0x4f, 0x53, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, + 0x49, 0x4e, 0x45, 0x52, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, + 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x08, 0x12, 0x19, 0x0a, 0x15, + 0x50, 0x4f, 0x53, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, + 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x09, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x4f, 0x50, 0x5f, + 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, 0x0a, 0x12, 0x14, 0x0a, 0x10, 0x52, + 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x10, + 0x0b, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x41, 0x53, 0x54, 0x10, 0x0c, 0x2a, 0x82, 0x01, 0x0a, 0x0e, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, + 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, + 0x45, 0x52, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, + 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x44, + 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, + 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4e, + 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x04, + 0x32, 0xd8, 0x01, 0x0a, 0x07, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x0e, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x2b, + 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6e, 0x72, + 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x71, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x6e, 0x72, 0x69, - 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x53, 0x74, 0x6f, - 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x6e, 0x72, 0x69, - 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, - 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x12, 0x26, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x1b, 0x2e, 0x6e, 0x72, 0x69, - 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, - 0x2f, 0x6e, 0x72, 0x69, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x6e, 0x72, + 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xae, 0x05, 0x0a, 0x06, + 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x5c, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x65, 0x12, 0x26, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6e, 0x72, + 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, + 0x69, 0x7a, 0x65, 0x12, 0x28, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, + 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, + 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x6e, + 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x12, 0x2c, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2d, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, + 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x12, 0x2c, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2d, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, + 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x2a, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6e, 0x72, + 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x26, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, + 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, + 0x1b, 0x2e, 0x6e, 0x72, 0x69, 0x2e, 0x70, 0x6b, 0x67, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x27, 0x5a, 0x25, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x6e, 0x72, 0x69, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, + 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3590,7 +3682,7 @@ func file_pkg_api_api_proto_rawDescGZIP() []byte { } var file_pkg_api_api_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pkg_api_api_proto_msgTypes = make([]protoimpl.MessageInfo, 49) +var file_pkg_api_api_proto_msgTypes = make([]protoimpl.MessageInfo, 50) var file_pkg_api_api_proto_goTypes = []interface{}{ (Event)(0), // 0: nri.pkg.api.v1alpha1.Event (ContainerState)(0), // 1: nri.pkg.api.v1alpha1.ContainerState @@ -3623,131 +3715,134 @@ var file_pkg_api_api_proto_goTypes = []interface{}{ (*LinuxMemory)(nil), // 28: nri.pkg.api.v1alpha1.LinuxMemory (*LinuxCPU)(nil), // 29: nri.pkg.api.v1alpha1.LinuxCPU (*HugepageLimit)(nil), // 30: nri.pkg.api.v1alpha1.HugepageLimit - (*ContainerAdjustment)(nil), // 31: nri.pkg.api.v1alpha1.ContainerAdjustment - (*LinuxContainerAdjustment)(nil), // 32: nri.pkg.api.v1alpha1.LinuxContainerAdjustment - (*ContainerUpdate)(nil), // 33: nri.pkg.api.v1alpha1.ContainerUpdate - (*LinuxContainerUpdate)(nil), // 34: nri.pkg.api.v1alpha1.LinuxContainerUpdate - (*ContainerEviction)(nil), // 35: nri.pkg.api.v1alpha1.ContainerEviction - (*KeyValue)(nil), // 36: nri.pkg.api.v1alpha1.KeyValue - (*OptionalString)(nil), // 37: nri.pkg.api.v1alpha1.OptionalString - (*OptionalInt)(nil), // 38: nri.pkg.api.v1alpha1.OptionalInt - (*OptionalInt32)(nil), // 39: nri.pkg.api.v1alpha1.OptionalInt32 - (*OptionalUInt32)(nil), // 40: nri.pkg.api.v1alpha1.OptionalUInt32 - (*OptionalInt64)(nil), // 41: nri.pkg.api.v1alpha1.OptionalInt64 - (*OptionalUInt64)(nil), // 42: nri.pkg.api.v1alpha1.OptionalUInt64 - (*OptionalBool)(nil), // 43: nri.pkg.api.v1alpha1.OptionalBool - (*OptionalFileMode)(nil), // 44: nri.pkg.api.v1alpha1.OptionalFileMode - nil, // 45: nri.pkg.api.v1alpha1.PodSandbox.LabelsEntry - nil, // 46: nri.pkg.api.v1alpha1.PodSandbox.AnnotationsEntry - nil, // 47: nri.pkg.api.v1alpha1.Container.LabelsEntry - nil, // 48: nri.pkg.api.v1alpha1.Container.AnnotationsEntry - nil, // 49: nri.pkg.api.v1alpha1.LinuxResources.UnifiedEntry - nil, // 50: nri.pkg.api.v1alpha1.ContainerAdjustment.AnnotationsEntry + (*POSIXRlimit)(nil), // 31: nri.pkg.api.v1alpha1.POSIXRlimit + (*ContainerAdjustment)(nil), // 32: nri.pkg.api.v1alpha1.ContainerAdjustment + (*LinuxContainerAdjustment)(nil), // 33: nri.pkg.api.v1alpha1.LinuxContainerAdjustment + (*ContainerUpdate)(nil), // 34: nri.pkg.api.v1alpha1.ContainerUpdate + (*LinuxContainerUpdate)(nil), // 35: nri.pkg.api.v1alpha1.LinuxContainerUpdate + (*ContainerEviction)(nil), // 36: nri.pkg.api.v1alpha1.ContainerEviction + (*KeyValue)(nil), // 37: nri.pkg.api.v1alpha1.KeyValue + (*OptionalString)(nil), // 38: nri.pkg.api.v1alpha1.OptionalString + (*OptionalInt)(nil), // 39: nri.pkg.api.v1alpha1.OptionalInt + (*OptionalInt32)(nil), // 40: nri.pkg.api.v1alpha1.OptionalInt32 + (*OptionalUInt32)(nil), // 41: nri.pkg.api.v1alpha1.OptionalUInt32 + (*OptionalInt64)(nil), // 42: nri.pkg.api.v1alpha1.OptionalInt64 + (*OptionalUInt64)(nil), // 43: nri.pkg.api.v1alpha1.OptionalUInt64 + (*OptionalBool)(nil), // 44: nri.pkg.api.v1alpha1.OptionalBool + (*OptionalFileMode)(nil), // 45: nri.pkg.api.v1alpha1.OptionalFileMode + nil, // 46: nri.pkg.api.v1alpha1.PodSandbox.LabelsEntry + nil, // 47: nri.pkg.api.v1alpha1.PodSandbox.AnnotationsEntry + nil, // 48: nri.pkg.api.v1alpha1.Container.LabelsEntry + nil, // 49: nri.pkg.api.v1alpha1.Container.AnnotationsEntry + nil, // 50: nri.pkg.api.v1alpha1.LinuxResources.UnifiedEntry + nil, // 51: nri.pkg.api.v1alpha1.ContainerAdjustment.AnnotationsEntry } var file_pkg_api_api_proto_depIdxs = []int32{ - 33, // 0: nri.pkg.api.v1alpha1.UpdateContainersRequest.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate - 35, // 1: nri.pkg.api.v1alpha1.UpdateContainersRequest.evict:type_name -> nri.pkg.api.v1alpha1.ContainerEviction - 33, // 2: nri.pkg.api.v1alpha1.UpdateContainersResponse.failed:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate + 34, // 0: nri.pkg.api.v1alpha1.UpdateContainersRequest.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate + 36, // 1: nri.pkg.api.v1alpha1.UpdateContainersRequest.evict:type_name -> nri.pkg.api.v1alpha1.ContainerEviction + 34, // 2: nri.pkg.api.v1alpha1.UpdateContainersResponse.failed:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate 17, // 3: nri.pkg.api.v1alpha1.SynchronizeRequest.pods:type_name -> nri.pkg.api.v1alpha1.PodSandbox 19, // 4: nri.pkg.api.v1alpha1.SynchronizeRequest.containers:type_name -> nri.pkg.api.v1alpha1.Container - 33, // 5: nri.pkg.api.v1alpha1.SynchronizeResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate + 34, // 5: nri.pkg.api.v1alpha1.SynchronizeResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate 17, // 6: nri.pkg.api.v1alpha1.CreateContainerRequest.pod:type_name -> nri.pkg.api.v1alpha1.PodSandbox 19, // 7: nri.pkg.api.v1alpha1.CreateContainerRequest.container:type_name -> nri.pkg.api.v1alpha1.Container - 31, // 8: nri.pkg.api.v1alpha1.CreateContainerResponse.adjust:type_name -> nri.pkg.api.v1alpha1.ContainerAdjustment - 33, // 9: nri.pkg.api.v1alpha1.CreateContainerResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate - 35, // 10: nri.pkg.api.v1alpha1.CreateContainerResponse.evict:type_name -> nri.pkg.api.v1alpha1.ContainerEviction + 32, // 8: nri.pkg.api.v1alpha1.CreateContainerResponse.adjust:type_name -> nri.pkg.api.v1alpha1.ContainerAdjustment + 34, // 9: nri.pkg.api.v1alpha1.CreateContainerResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate + 36, // 10: nri.pkg.api.v1alpha1.CreateContainerResponse.evict:type_name -> nri.pkg.api.v1alpha1.ContainerEviction 17, // 11: nri.pkg.api.v1alpha1.UpdateContainerRequest.pod:type_name -> nri.pkg.api.v1alpha1.PodSandbox 19, // 12: nri.pkg.api.v1alpha1.UpdateContainerRequest.container:type_name -> nri.pkg.api.v1alpha1.Container 27, // 13: nri.pkg.api.v1alpha1.UpdateContainerRequest.linux_resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources - 33, // 14: nri.pkg.api.v1alpha1.UpdateContainerResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate - 35, // 15: nri.pkg.api.v1alpha1.UpdateContainerResponse.evict:type_name -> nri.pkg.api.v1alpha1.ContainerEviction + 34, // 14: nri.pkg.api.v1alpha1.UpdateContainerResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate + 36, // 15: nri.pkg.api.v1alpha1.UpdateContainerResponse.evict:type_name -> nri.pkg.api.v1alpha1.ContainerEviction 17, // 16: nri.pkg.api.v1alpha1.StopContainerRequest.pod:type_name -> nri.pkg.api.v1alpha1.PodSandbox 19, // 17: nri.pkg.api.v1alpha1.StopContainerRequest.container:type_name -> nri.pkg.api.v1alpha1.Container - 33, // 18: nri.pkg.api.v1alpha1.StopContainerResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate + 34, // 18: nri.pkg.api.v1alpha1.StopContainerResponse.update:type_name -> nri.pkg.api.v1alpha1.ContainerUpdate 0, // 19: nri.pkg.api.v1alpha1.StateChangeEvent.event:type_name -> nri.pkg.api.v1alpha1.Event 17, // 20: nri.pkg.api.v1alpha1.StateChangeEvent.pod:type_name -> nri.pkg.api.v1alpha1.PodSandbox 19, // 21: nri.pkg.api.v1alpha1.StateChangeEvent.container:type_name -> nri.pkg.api.v1alpha1.Container - 45, // 22: nri.pkg.api.v1alpha1.PodSandbox.labels:type_name -> nri.pkg.api.v1alpha1.PodSandbox.LabelsEntry - 46, // 23: nri.pkg.api.v1alpha1.PodSandbox.annotations:type_name -> nri.pkg.api.v1alpha1.PodSandbox.AnnotationsEntry + 46, // 22: nri.pkg.api.v1alpha1.PodSandbox.labels:type_name -> nri.pkg.api.v1alpha1.PodSandbox.LabelsEntry + 47, // 23: nri.pkg.api.v1alpha1.PodSandbox.annotations:type_name -> nri.pkg.api.v1alpha1.PodSandbox.AnnotationsEntry 18, // 24: nri.pkg.api.v1alpha1.PodSandbox.linux:type_name -> nri.pkg.api.v1alpha1.LinuxPodSandbox 27, // 25: nri.pkg.api.v1alpha1.LinuxPodSandbox.pod_overhead:type_name -> nri.pkg.api.v1alpha1.LinuxResources 27, // 26: nri.pkg.api.v1alpha1.LinuxPodSandbox.pod_resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources 24, // 27: nri.pkg.api.v1alpha1.LinuxPodSandbox.namespaces:type_name -> nri.pkg.api.v1alpha1.LinuxNamespace 27, // 28: nri.pkg.api.v1alpha1.LinuxPodSandbox.resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources 1, // 29: nri.pkg.api.v1alpha1.Container.state:type_name -> nri.pkg.api.v1alpha1.ContainerState - 47, // 30: nri.pkg.api.v1alpha1.Container.labels:type_name -> nri.pkg.api.v1alpha1.Container.LabelsEntry - 48, // 31: nri.pkg.api.v1alpha1.Container.annotations:type_name -> nri.pkg.api.v1alpha1.Container.AnnotationsEntry + 48, // 30: nri.pkg.api.v1alpha1.Container.labels:type_name -> nri.pkg.api.v1alpha1.Container.LabelsEntry + 49, // 31: nri.pkg.api.v1alpha1.Container.annotations:type_name -> nri.pkg.api.v1alpha1.Container.AnnotationsEntry 20, // 32: nri.pkg.api.v1alpha1.Container.mounts:type_name -> nri.pkg.api.v1alpha1.Mount 21, // 33: nri.pkg.api.v1alpha1.Container.hooks:type_name -> nri.pkg.api.v1alpha1.Hooks 23, // 34: nri.pkg.api.v1alpha1.Container.linux:type_name -> nri.pkg.api.v1alpha1.LinuxContainer - 22, // 35: nri.pkg.api.v1alpha1.Hooks.prestart:type_name -> nri.pkg.api.v1alpha1.Hook - 22, // 36: nri.pkg.api.v1alpha1.Hooks.create_runtime:type_name -> nri.pkg.api.v1alpha1.Hook - 22, // 37: nri.pkg.api.v1alpha1.Hooks.create_container:type_name -> nri.pkg.api.v1alpha1.Hook - 22, // 38: nri.pkg.api.v1alpha1.Hooks.start_container:type_name -> nri.pkg.api.v1alpha1.Hook - 22, // 39: nri.pkg.api.v1alpha1.Hooks.poststart:type_name -> nri.pkg.api.v1alpha1.Hook - 22, // 40: nri.pkg.api.v1alpha1.Hooks.poststop:type_name -> nri.pkg.api.v1alpha1.Hook - 38, // 41: nri.pkg.api.v1alpha1.Hook.timeout:type_name -> nri.pkg.api.v1alpha1.OptionalInt - 24, // 42: nri.pkg.api.v1alpha1.LinuxContainer.namespaces:type_name -> nri.pkg.api.v1alpha1.LinuxNamespace - 25, // 43: nri.pkg.api.v1alpha1.LinuxContainer.devices:type_name -> nri.pkg.api.v1alpha1.LinuxDevice - 27, // 44: nri.pkg.api.v1alpha1.LinuxContainer.resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources - 38, // 45: nri.pkg.api.v1alpha1.LinuxContainer.oom_score_adj:type_name -> nri.pkg.api.v1alpha1.OptionalInt - 44, // 46: nri.pkg.api.v1alpha1.LinuxDevice.file_mode:type_name -> nri.pkg.api.v1alpha1.OptionalFileMode - 40, // 47: nri.pkg.api.v1alpha1.LinuxDevice.uid:type_name -> nri.pkg.api.v1alpha1.OptionalUInt32 - 40, // 48: nri.pkg.api.v1alpha1.LinuxDevice.gid:type_name -> nri.pkg.api.v1alpha1.OptionalUInt32 - 41, // 49: nri.pkg.api.v1alpha1.LinuxDeviceCgroup.major:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 41, // 50: nri.pkg.api.v1alpha1.LinuxDeviceCgroup.minor:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 28, // 51: nri.pkg.api.v1alpha1.LinuxResources.memory:type_name -> nri.pkg.api.v1alpha1.LinuxMemory - 29, // 52: nri.pkg.api.v1alpha1.LinuxResources.cpu:type_name -> nri.pkg.api.v1alpha1.LinuxCPU - 30, // 53: nri.pkg.api.v1alpha1.LinuxResources.hugepage_limits:type_name -> nri.pkg.api.v1alpha1.HugepageLimit - 37, // 54: nri.pkg.api.v1alpha1.LinuxResources.blockio_class:type_name -> nri.pkg.api.v1alpha1.OptionalString - 37, // 55: nri.pkg.api.v1alpha1.LinuxResources.rdt_class:type_name -> nri.pkg.api.v1alpha1.OptionalString - 49, // 56: nri.pkg.api.v1alpha1.LinuxResources.unified:type_name -> nri.pkg.api.v1alpha1.LinuxResources.UnifiedEntry - 26, // 57: nri.pkg.api.v1alpha1.LinuxResources.devices:type_name -> nri.pkg.api.v1alpha1.LinuxDeviceCgroup - 41, // 58: nri.pkg.api.v1alpha1.LinuxMemory.limit:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 41, // 59: nri.pkg.api.v1alpha1.LinuxMemory.reservation:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 41, // 60: nri.pkg.api.v1alpha1.LinuxMemory.swap:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 41, // 61: nri.pkg.api.v1alpha1.LinuxMemory.kernel:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 41, // 62: nri.pkg.api.v1alpha1.LinuxMemory.kernel_tcp:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 42, // 63: nri.pkg.api.v1alpha1.LinuxMemory.swappiness:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 - 43, // 64: nri.pkg.api.v1alpha1.LinuxMemory.disable_oom_killer:type_name -> nri.pkg.api.v1alpha1.OptionalBool - 43, // 65: nri.pkg.api.v1alpha1.LinuxMemory.use_hierarchy:type_name -> nri.pkg.api.v1alpha1.OptionalBool - 42, // 66: nri.pkg.api.v1alpha1.LinuxCPU.shares:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 - 41, // 67: nri.pkg.api.v1alpha1.LinuxCPU.quota:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 42, // 68: nri.pkg.api.v1alpha1.LinuxCPU.period:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 - 41, // 69: nri.pkg.api.v1alpha1.LinuxCPU.realtime_runtime:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 - 42, // 70: nri.pkg.api.v1alpha1.LinuxCPU.realtime_period:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 - 50, // 71: nri.pkg.api.v1alpha1.ContainerAdjustment.annotations:type_name -> nri.pkg.api.v1alpha1.ContainerAdjustment.AnnotationsEntry - 20, // 72: nri.pkg.api.v1alpha1.ContainerAdjustment.mounts:type_name -> nri.pkg.api.v1alpha1.Mount - 36, // 73: nri.pkg.api.v1alpha1.ContainerAdjustment.env:type_name -> nri.pkg.api.v1alpha1.KeyValue - 21, // 74: nri.pkg.api.v1alpha1.ContainerAdjustment.hooks:type_name -> nri.pkg.api.v1alpha1.Hooks - 32, // 75: nri.pkg.api.v1alpha1.ContainerAdjustment.linux:type_name -> nri.pkg.api.v1alpha1.LinuxContainerAdjustment - 25, // 76: nri.pkg.api.v1alpha1.LinuxContainerAdjustment.devices:type_name -> nri.pkg.api.v1alpha1.LinuxDevice - 27, // 77: nri.pkg.api.v1alpha1.LinuxContainerAdjustment.resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources - 34, // 78: nri.pkg.api.v1alpha1.ContainerUpdate.linux:type_name -> nri.pkg.api.v1alpha1.LinuxContainerUpdate - 27, // 79: nri.pkg.api.v1alpha1.LinuxContainerUpdate.resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources - 2, // 80: nri.pkg.api.v1alpha1.Runtime.RegisterPlugin:input_type -> nri.pkg.api.v1alpha1.RegisterPluginRequest - 3, // 81: nri.pkg.api.v1alpha1.Runtime.UpdateContainers:input_type -> nri.pkg.api.v1alpha1.UpdateContainersRequest - 5, // 82: nri.pkg.api.v1alpha1.Plugin.Configure:input_type -> nri.pkg.api.v1alpha1.ConfigureRequest - 7, // 83: nri.pkg.api.v1alpha1.Plugin.Synchronize:input_type -> nri.pkg.api.v1alpha1.SynchronizeRequest - 16, // 84: nri.pkg.api.v1alpha1.Plugin.Shutdown:input_type -> nri.pkg.api.v1alpha1.Empty - 9, // 85: nri.pkg.api.v1alpha1.Plugin.CreateContainer:input_type -> nri.pkg.api.v1alpha1.CreateContainerRequest - 11, // 86: nri.pkg.api.v1alpha1.Plugin.UpdateContainer:input_type -> nri.pkg.api.v1alpha1.UpdateContainerRequest - 13, // 87: nri.pkg.api.v1alpha1.Plugin.StopContainer:input_type -> nri.pkg.api.v1alpha1.StopContainerRequest - 15, // 88: nri.pkg.api.v1alpha1.Plugin.StateChange:input_type -> nri.pkg.api.v1alpha1.StateChangeEvent - 16, // 89: nri.pkg.api.v1alpha1.Runtime.RegisterPlugin:output_type -> nri.pkg.api.v1alpha1.Empty - 4, // 90: nri.pkg.api.v1alpha1.Runtime.UpdateContainers:output_type -> nri.pkg.api.v1alpha1.UpdateContainersResponse - 6, // 91: nri.pkg.api.v1alpha1.Plugin.Configure:output_type -> nri.pkg.api.v1alpha1.ConfigureResponse - 8, // 92: nri.pkg.api.v1alpha1.Plugin.Synchronize:output_type -> nri.pkg.api.v1alpha1.SynchronizeResponse - 16, // 93: nri.pkg.api.v1alpha1.Plugin.Shutdown:output_type -> nri.pkg.api.v1alpha1.Empty - 10, // 94: nri.pkg.api.v1alpha1.Plugin.CreateContainer:output_type -> nri.pkg.api.v1alpha1.CreateContainerResponse - 12, // 95: nri.pkg.api.v1alpha1.Plugin.UpdateContainer:output_type -> nri.pkg.api.v1alpha1.UpdateContainerResponse - 14, // 96: nri.pkg.api.v1alpha1.Plugin.StopContainer:output_type -> nri.pkg.api.v1alpha1.StopContainerResponse - 16, // 97: nri.pkg.api.v1alpha1.Plugin.StateChange:output_type -> nri.pkg.api.v1alpha1.Empty - 89, // [89:98] is the sub-list for method output_type - 80, // [80:89] is the sub-list for method input_type - 80, // [80:80] is the sub-list for extension type_name - 80, // [80:80] is the sub-list for extension extendee - 0, // [0:80] is the sub-list for field type_name + 31, // 35: nri.pkg.api.v1alpha1.Container.rlimits:type_name -> nri.pkg.api.v1alpha1.POSIXRlimit + 22, // 36: nri.pkg.api.v1alpha1.Hooks.prestart:type_name -> nri.pkg.api.v1alpha1.Hook + 22, // 37: nri.pkg.api.v1alpha1.Hooks.create_runtime:type_name -> nri.pkg.api.v1alpha1.Hook + 22, // 38: nri.pkg.api.v1alpha1.Hooks.create_container:type_name -> nri.pkg.api.v1alpha1.Hook + 22, // 39: nri.pkg.api.v1alpha1.Hooks.start_container:type_name -> nri.pkg.api.v1alpha1.Hook + 22, // 40: nri.pkg.api.v1alpha1.Hooks.poststart:type_name -> nri.pkg.api.v1alpha1.Hook + 22, // 41: nri.pkg.api.v1alpha1.Hooks.poststop:type_name -> nri.pkg.api.v1alpha1.Hook + 39, // 42: nri.pkg.api.v1alpha1.Hook.timeout:type_name -> nri.pkg.api.v1alpha1.OptionalInt + 24, // 43: nri.pkg.api.v1alpha1.LinuxContainer.namespaces:type_name -> nri.pkg.api.v1alpha1.LinuxNamespace + 25, // 44: nri.pkg.api.v1alpha1.LinuxContainer.devices:type_name -> nri.pkg.api.v1alpha1.LinuxDevice + 27, // 45: nri.pkg.api.v1alpha1.LinuxContainer.resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources + 39, // 46: nri.pkg.api.v1alpha1.LinuxContainer.oom_score_adj:type_name -> nri.pkg.api.v1alpha1.OptionalInt + 45, // 47: nri.pkg.api.v1alpha1.LinuxDevice.file_mode:type_name -> nri.pkg.api.v1alpha1.OptionalFileMode + 41, // 48: nri.pkg.api.v1alpha1.LinuxDevice.uid:type_name -> nri.pkg.api.v1alpha1.OptionalUInt32 + 41, // 49: nri.pkg.api.v1alpha1.LinuxDevice.gid:type_name -> nri.pkg.api.v1alpha1.OptionalUInt32 + 42, // 50: nri.pkg.api.v1alpha1.LinuxDeviceCgroup.major:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 42, // 51: nri.pkg.api.v1alpha1.LinuxDeviceCgroup.minor:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 28, // 52: nri.pkg.api.v1alpha1.LinuxResources.memory:type_name -> nri.pkg.api.v1alpha1.LinuxMemory + 29, // 53: nri.pkg.api.v1alpha1.LinuxResources.cpu:type_name -> nri.pkg.api.v1alpha1.LinuxCPU + 30, // 54: nri.pkg.api.v1alpha1.LinuxResources.hugepage_limits:type_name -> nri.pkg.api.v1alpha1.HugepageLimit + 38, // 55: nri.pkg.api.v1alpha1.LinuxResources.blockio_class:type_name -> nri.pkg.api.v1alpha1.OptionalString + 38, // 56: nri.pkg.api.v1alpha1.LinuxResources.rdt_class:type_name -> nri.pkg.api.v1alpha1.OptionalString + 50, // 57: nri.pkg.api.v1alpha1.LinuxResources.unified:type_name -> nri.pkg.api.v1alpha1.LinuxResources.UnifiedEntry + 26, // 58: nri.pkg.api.v1alpha1.LinuxResources.devices:type_name -> nri.pkg.api.v1alpha1.LinuxDeviceCgroup + 42, // 59: nri.pkg.api.v1alpha1.LinuxMemory.limit:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 42, // 60: nri.pkg.api.v1alpha1.LinuxMemory.reservation:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 42, // 61: nri.pkg.api.v1alpha1.LinuxMemory.swap:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 42, // 62: nri.pkg.api.v1alpha1.LinuxMemory.kernel:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 42, // 63: nri.pkg.api.v1alpha1.LinuxMemory.kernel_tcp:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 43, // 64: nri.pkg.api.v1alpha1.LinuxMemory.swappiness:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 + 44, // 65: nri.pkg.api.v1alpha1.LinuxMemory.disable_oom_killer:type_name -> nri.pkg.api.v1alpha1.OptionalBool + 44, // 66: nri.pkg.api.v1alpha1.LinuxMemory.use_hierarchy:type_name -> nri.pkg.api.v1alpha1.OptionalBool + 43, // 67: nri.pkg.api.v1alpha1.LinuxCPU.shares:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 + 42, // 68: nri.pkg.api.v1alpha1.LinuxCPU.quota:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 43, // 69: nri.pkg.api.v1alpha1.LinuxCPU.period:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 + 42, // 70: nri.pkg.api.v1alpha1.LinuxCPU.realtime_runtime:type_name -> nri.pkg.api.v1alpha1.OptionalInt64 + 43, // 71: nri.pkg.api.v1alpha1.LinuxCPU.realtime_period:type_name -> nri.pkg.api.v1alpha1.OptionalUInt64 + 51, // 72: nri.pkg.api.v1alpha1.ContainerAdjustment.annotations:type_name -> nri.pkg.api.v1alpha1.ContainerAdjustment.AnnotationsEntry + 20, // 73: nri.pkg.api.v1alpha1.ContainerAdjustment.mounts:type_name -> nri.pkg.api.v1alpha1.Mount + 37, // 74: nri.pkg.api.v1alpha1.ContainerAdjustment.env:type_name -> nri.pkg.api.v1alpha1.KeyValue + 21, // 75: nri.pkg.api.v1alpha1.ContainerAdjustment.hooks:type_name -> nri.pkg.api.v1alpha1.Hooks + 33, // 76: nri.pkg.api.v1alpha1.ContainerAdjustment.linux:type_name -> nri.pkg.api.v1alpha1.LinuxContainerAdjustment + 31, // 77: nri.pkg.api.v1alpha1.ContainerAdjustment.rlimits:type_name -> nri.pkg.api.v1alpha1.POSIXRlimit + 25, // 78: nri.pkg.api.v1alpha1.LinuxContainerAdjustment.devices:type_name -> nri.pkg.api.v1alpha1.LinuxDevice + 27, // 79: nri.pkg.api.v1alpha1.LinuxContainerAdjustment.resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources + 35, // 80: nri.pkg.api.v1alpha1.ContainerUpdate.linux:type_name -> nri.pkg.api.v1alpha1.LinuxContainerUpdate + 27, // 81: nri.pkg.api.v1alpha1.LinuxContainerUpdate.resources:type_name -> nri.pkg.api.v1alpha1.LinuxResources + 2, // 82: nri.pkg.api.v1alpha1.Runtime.RegisterPlugin:input_type -> nri.pkg.api.v1alpha1.RegisterPluginRequest + 3, // 83: nri.pkg.api.v1alpha1.Runtime.UpdateContainers:input_type -> nri.pkg.api.v1alpha1.UpdateContainersRequest + 5, // 84: nri.pkg.api.v1alpha1.Plugin.Configure:input_type -> nri.pkg.api.v1alpha1.ConfigureRequest + 7, // 85: nri.pkg.api.v1alpha1.Plugin.Synchronize:input_type -> nri.pkg.api.v1alpha1.SynchronizeRequest + 16, // 86: nri.pkg.api.v1alpha1.Plugin.Shutdown:input_type -> nri.pkg.api.v1alpha1.Empty + 9, // 87: nri.pkg.api.v1alpha1.Plugin.CreateContainer:input_type -> nri.pkg.api.v1alpha1.CreateContainerRequest + 11, // 88: nri.pkg.api.v1alpha1.Plugin.UpdateContainer:input_type -> nri.pkg.api.v1alpha1.UpdateContainerRequest + 13, // 89: nri.pkg.api.v1alpha1.Plugin.StopContainer:input_type -> nri.pkg.api.v1alpha1.StopContainerRequest + 15, // 90: nri.pkg.api.v1alpha1.Plugin.StateChange:input_type -> nri.pkg.api.v1alpha1.StateChangeEvent + 16, // 91: nri.pkg.api.v1alpha1.Runtime.RegisterPlugin:output_type -> nri.pkg.api.v1alpha1.Empty + 4, // 92: nri.pkg.api.v1alpha1.Runtime.UpdateContainers:output_type -> nri.pkg.api.v1alpha1.UpdateContainersResponse + 6, // 93: nri.pkg.api.v1alpha1.Plugin.Configure:output_type -> nri.pkg.api.v1alpha1.ConfigureResponse + 8, // 94: nri.pkg.api.v1alpha1.Plugin.Synchronize:output_type -> nri.pkg.api.v1alpha1.SynchronizeResponse + 16, // 95: nri.pkg.api.v1alpha1.Plugin.Shutdown:output_type -> nri.pkg.api.v1alpha1.Empty + 10, // 96: nri.pkg.api.v1alpha1.Plugin.CreateContainer:output_type -> nri.pkg.api.v1alpha1.CreateContainerResponse + 12, // 97: nri.pkg.api.v1alpha1.Plugin.UpdateContainer:output_type -> nri.pkg.api.v1alpha1.UpdateContainerResponse + 14, // 98: nri.pkg.api.v1alpha1.Plugin.StopContainer:output_type -> nri.pkg.api.v1alpha1.StopContainerResponse + 16, // 99: nri.pkg.api.v1alpha1.Plugin.StateChange:output_type -> nri.pkg.api.v1alpha1.Empty + 91, // [91:100] is the sub-list for method output_type + 82, // [82:91] is the sub-list for method input_type + 82, // [82:82] is the sub-list for extension type_name + 82, // [82:82] is the sub-list for extension extendee + 0, // [0:82] is the sub-list for field type_name } func init() { file_pkg_api_api_proto_init() } @@ -4105,7 +4200,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ContainerAdjustment); i { + switch v := v.(*POSIXRlimit); i { case 0: return &v.state case 1: @@ -4117,7 +4212,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LinuxContainerAdjustment); i { + switch v := v.(*ContainerAdjustment); i { case 0: return &v.state case 1: @@ -4129,7 +4224,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ContainerUpdate); i { + switch v := v.(*LinuxContainerAdjustment); i { case 0: return &v.state case 1: @@ -4141,7 +4236,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LinuxContainerUpdate); i { + switch v := v.(*ContainerUpdate); i { case 0: return &v.state case 1: @@ -4153,7 +4248,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ContainerEviction); i { + switch v := v.(*LinuxContainerUpdate); i { case 0: return &v.state case 1: @@ -4165,7 +4260,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyValue); i { + switch v := v.(*ContainerEviction); i { case 0: return &v.state case 1: @@ -4177,7 +4272,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptionalString); i { + switch v := v.(*KeyValue); i { case 0: return &v.state case 1: @@ -4189,7 +4284,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptionalInt); i { + switch v := v.(*OptionalString); i { case 0: return &v.state case 1: @@ -4201,7 +4296,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptionalInt32); i { + switch v := v.(*OptionalInt); i { case 0: return &v.state case 1: @@ -4213,7 +4308,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptionalUInt32); i { + switch v := v.(*OptionalInt32); i { case 0: return &v.state case 1: @@ -4225,7 +4320,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptionalInt64); i { + switch v := v.(*OptionalUInt32); i { case 0: return &v.state case 1: @@ -4237,7 +4332,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptionalUInt64); i { + switch v := v.(*OptionalInt64); i { case 0: return &v.state case 1: @@ -4249,7 +4344,7 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OptionalBool); i { + switch v := v.(*OptionalUInt64); i { case 0: return &v.state case 1: @@ -4261,6 +4356,18 @@ func file_pkg_api_api_proto_init() { } } file_pkg_api_api_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OptionalBool); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_api_api_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OptionalFileMode); i { case 0: return &v.state @@ -4279,7 +4386,7 @@ func file_pkg_api_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_api_api_proto_rawDesc, NumEnums: 2, - NumMessages: 49, + NumMessages: 50, NumExtensions: 0, NumServices: 2, }, diff --git a/vendor/github.com/containerd/nri/pkg/api/api.proto b/vendor/github.com/containerd/nri/pkg/api/api.proto index 25ae8f87c85..7c64adec093 100644 --- a/vendor/github.com/containerd/nri/pkg/api/api.proto +++ b/vendor/github.com/containerd/nri/pkg/api/api.proto @@ -246,6 +246,7 @@ message Container { Hooks hooks = 10; LinuxContainer linux = 11; uint32 pid = 12; // for NRI v1 emulation + repeated POSIXRlimit rlimits = 13; } // Possible container states. @@ -358,6 +359,13 @@ message HugepageLimit { uint64 limit = 2; } +// Container rlimits +message POSIXRlimit { + string type = 1; + uint64 hard = 2; + uint64 soft = 3; +} + // Requested adjustments to a container being created. message ContainerAdjustment { map annotations = 2; @@ -365,6 +373,7 @@ message ContainerAdjustment { repeated KeyValue env = 4; Hooks hooks = 5; LinuxContainerAdjustment linux = 6; + repeated POSIXRlimit rlimits = 7; } // Adjustments to (linux) resources. diff --git a/vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go b/vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go index e6737454e23..c047ec5fd7d 100644 --- a/vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go +++ b/vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go @@ -8,25 +8,27 @@ import ( ) type RuntimeService interface { - RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*Empty, error) - UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error) + RegisterPlugin(context.Context, *RegisterPluginRequest) (*Empty, error) + UpdateContainers(context.Context, *UpdateContainersRequest) (*UpdateContainersResponse, error) } func RegisterRuntimeService(srv *ttrpc.Server, svc RuntimeService) { - srv.Register("nri.pkg.api.v1alpha1.Runtime", map[string]ttrpc.Method{ - "RegisterPlugin": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req RegisterPluginRequest - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.RegisterPlugin(ctx, &req) - }, - "UpdateContainers": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req UpdateContainersRequest - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.UpdateContainers(ctx, &req) + srv.RegisterService("nri.pkg.api.v1alpha1.Runtime", &ttrpc.ServiceDesc{ + Methods: map[string]ttrpc.Method{ + "RegisterPlugin": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req RegisterPluginRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.RegisterPlugin(ctx, &req) + }, + "UpdateContainers": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req UpdateContainersRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.UpdateContainers(ctx, &req) + }, }, }) } @@ -40,6 +42,7 @@ func NewRuntimeClient(client *ttrpc.Client) RuntimeService { client: client, } } + func (c *runtimeClient) RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*Empty, error) { var resp Empty if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Runtime", "RegisterPlugin", req, &resp); err != nil { @@ -47,6 +50,7 @@ func (c *runtimeClient) RegisterPlugin(ctx context.Context, req *RegisterPluginR } return &resp, nil } + func (c *runtimeClient) UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error) { var resp UpdateContainersResponse if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Runtime", "UpdateContainers", req, &resp); err != nil { @@ -56,65 +60,67 @@ func (c *runtimeClient) UpdateContainers(ctx context.Context, req *UpdateContain } type PluginService interface { - Configure(ctx context.Context, req *ConfigureRequest) (*ConfigureResponse, error) - Synchronize(ctx context.Context, req *SynchronizeRequest) (*SynchronizeResponse, error) - Shutdown(ctx context.Context, req *Empty) (*Empty, error) - CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) - UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) - StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) - StateChange(ctx context.Context, req *StateChangeEvent) (*Empty, error) + Configure(context.Context, *ConfigureRequest) (*ConfigureResponse, error) + Synchronize(context.Context, *SynchronizeRequest) (*SynchronizeResponse, error) + Shutdown(context.Context, *Empty) (*Empty, error) + CreateContainer(context.Context, *CreateContainerRequest) (*CreateContainerResponse, error) + UpdateContainer(context.Context, *UpdateContainerRequest) (*UpdateContainerResponse, error) + StopContainer(context.Context, *StopContainerRequest) (*StopContainerResponse, error) + StateChange(context.Context, *StateChangeEvent) (*Empty, error) } func RegisterPluginService(srv *ttrpc.Server, svc PluginService) { - srv.Register("nri.pkg.api.v1alpha1.Plugin", map[string]ttrpc.Method{ - "Configure": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req ConfigureRequest - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.Configure(ctx, &req) - }, - "Synchronize": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req SynchronizeRequest - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.Synchronize(ctx, &req) - }, - "Shutdown": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req Empty - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.Shutdown(ctx, &req) - }, - "CreateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req CreateContainerRequest - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.CreateContainer(ctx, &req) - }, - "UpdateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req UpdateContainerRequest - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.UpdateContainer(ctx, &req) - }, - "StopContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req StopContainerRequest - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.StopContainer(ctx, &req) - }, - "StateChange": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { - var req StateChangeEvent - if err := unmarshal(&req); err != nil { - return nil, err - } - return svc.StateChange(ctx, &req) + srv.RegisterService("nri.pkg.api.v1alpha1.Plugin", &ttrpc.ServiceDesc{ + Methods: map[string]ttrpc.Method{ + "Configure": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req ConfigureRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.Configure(ctx, &req) + }, + "Synchronize": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req SynchronizeRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.Synchronize(ctx, &req) + }, + "Shutdown": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req Empty + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.Shutdown(ctx, &req) + }, + "CreateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req CreateContainerRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.CreateContainer(ctx, &req) + }, + "UpdateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req UpdateContainerRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.UpdateContainer(ctx, &req) + }, + "StopContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req StopContainerRequest + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.StopContainer(ctx, &req) + }, + "StateChange": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) { + var req StateChangeEvent + if err := unmarshal(&req); err != nil { + return nil, err + } + return svc.StateChange(ctx, &req) + }, }, }) } @@ -128,6 +134,7 @@ func NewPluginClient(client *ttrpc.Client) PluginService { client: client, } } + func (c *pluginClient) Configure(ctx context.Context, req *ConfigureRequest) (*ConfigureResponse, error) { var resp ConfigureResponse if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Configure", req, &resp); err != nil { @@ -135,6 +142,7 @@ func (c *pluginClient) Configure(ctx context.Context, req *ConfigureRequest) (*C } return &resp, nil } + func (c *pluginClient) Synchronize(ctx context.Context, req *SynchronizeRequest) (*SynchronizeResponse, error) { var resp SynchronizeResponse if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Synchronize", req, &resp); err != nil { @@ -142,6 +150,7 @@ func (c *pluginClient) Synchronize(ctx context.Context, req *SynchronizeRequest) } return &resp, nil } + func (c *pluginClient) Shutdown(ctx context.Context, req *Empty) (*Empty, error) { var resp Empty if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Shutdown", req, &resp); err != nil { @@ -149,6 +158,7 @@ func (c *pluginClient) Shutdown(ctx context.Context, req *Empty) (*Empty, error) } return &resp, nil } + func (c *pluginClient) CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) { var resp CreateContainerResponse if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "CreateContainer", req, &resp); err != nil { @@ -156,6 +166,7 @@ func (c *pluginClient) CreateContainer(ctx context.Context, req *CreateContainer } return &resp, nil } + func (c *pluginClient) UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) { var resp UpdateContainerResponse if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "UpdateContainer", req, &resp); err != nil { @@ -163,6 +174,7 @@ func (c *pluginClient) UpdateContainer(ctx context.Context, req *UpdateContainer } return &resp, nil } + func (c *pluginClient) StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) { var resp StopContainerResponse if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "StopContainer", req, &resp); err != nil { @@ -170,6 +182,7 @@ func (c *pluginClient) StopContainer(ctx context.Context, req *StopContainerRequ } return &resp, nil } + func (c *pluginClient) StateChange(ctx context.Context, req *StateChangeEvent) (*Empty, error) { var resp Empty if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "StateChange", req, &resp); err != nil { diff --git a/vendor/github.com/containerd/nri/pkg/api/event.go b/vendor/github.com/containerd/nri/pkg/api/event.go index 50909f6355e..260460adaf0 100644 --- a/vendor/github.com/containerd/nri/pkg/api/event.go +++ b/vendor/github.com/containerd/nri/pkg/api/event.go @@ -82,14 +82,14 @@ func ParseEventMask(events ...string) (EventMask, error) { continue case "pod", "podsandbox": for name, bit := range bits { - if strings.Contains(name, "Pod") { + if strings.Contains(name, "pod") { mask.Set(bit) } } continue case "container": for name, bit := range bits { - if strings.Contains(name, "Container") { + if strings.Contains(name, "container") { mask.Set(bit) } } diff --git a/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go b/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go index 847383eb052..ad8c20e2a2e 100644 --- a/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go +++ b/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go @@ -119,6 +119,9 @@ func (g *Generator) Adjust(adjust *nri.ContainerAdjustment) error { if err := g.AdjustMounts(adjust.GetMounts()); err != nil { return err } + if err := g.AdjustRlimits(adjust.GetRlimits()); err != nil { + return err + } return nil } @@ -320,6 +323,20 @@ func (g *Generator) AdjustDevices(devices []*nri.LinuxDevice) { } } +func (g *Generator) AdjustRlimits(rlimits []*nri.POSIXRlimit) error { + for _, l := range rlimits { + if l == nil { + continue + } + g.Config.Process.Rlimits = append(g.Config.Process.Rlimits, rspec.POSIXRlimit{ + Type: l.Type, + Hard: l.Hard, + Soft: l.Soft, + }) + } + return nil +} + // AdjustMounts adjusts the mounts in the OCI Spec. func (g *Generator) AdjustMounts(mounts []*nri.Mount) error { if len(mounts) == 0 { diff --git a/vendor/github.com/containerd/nri/pkg/stub/stub.go b/vendor/github.com/containerd/nri/pkg/stub/stub.go index 470098657b7..dab040c62f3 100644 --- a/vendor/github.com/containerd/nri/pkg/stub/stub.go +++ b/vendor/github.com/containerd/nri/pkg/stub/stub.go @@ -47,38 +47,38 @@ type ConfigureInterface interface { // Configure the plugin with the given NRI-supplied configuration. // If a non-zero EventMask is returned, the plugin will be subscribed // to the corresponding. - Configure(config, runtime, version string) (api.EventMask, error) + Configure(ctx context.Context, config, runtime, version string) (api.EventMask, error) } // SynchronizeInterface handles Synchronize API requests. type SynchronizeInterface interface { // Synchronize the state of the plugin with the runtime. // The plugin can request updates to containers in response. - Synchronize([]*api.PodSandbox, []*api.Container) ([]*api.ContainerUpdate, error) + Synchronize(context.Context, []*api.PodSandbox, []*api.Container) ([]*api.ContainerUpdate, error) } // ShutdownInterface handles a Shutdown API request. type ShutdownInterface interface { // Shutdown notifies the plugin about the runtime shutting down. - Shutdown(*api.ShutdownRequest) + Shutdown(context.Context) } // RunPodInterface handles RunPodSandbox API events. type RunPodInterface interface { // RunPodSandbox relays a RunPodSandbox event to the plugin. - RunPodSandbox(*api.PodSandbox) error + RunPodSandbox(context.Context, *api.PodSandbox) error } // StopPodInterface handles StopPodSandbox API events. type StopPodInterface interface { // StopPodSandbox relays a StopPodSandbox event to the plugin. - StopPodSandbox(*api.PodSandbox) error + StopPodSandbox(context.Context, *api.PodSandbox) error } // RemovePodInterface handles RemovePodSandbox API events. type RemovePodInterface interface { // RemovePodSandbox relays a RemovePodSandbox event to the plugin. - RemovePodSandbox(*api.PodSandbox) error + RemovePodSandbox(context.Context, *api.PodSandbox) error } // CreateContainerInterface handles CreateContainer API requests. @@ -86,13 +86,13 @@ type CreateContainerInterface interface { // CreateContainer relays a CreateContainer request to the plugin. // The plugin can request adjustments to the container being created // and updates to other unstopped containers in response. - CreateContainer(*api.PodSandbox, *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error) + CreateContainer(context.Context, *api.PodSandbox, *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error) } // StartContainerInterface handles StartContainer API requests. type StartContainerInterface interface { // StartContainer relays a StartContainer event to the plugin. - StartContainer(*api.PodSandbox, *api.Container) error + StartContainer(context.Context, *api.PodSandbox, *api.Container) error } // UpdateContainerInterface handles UpdateContainer API requests. @@ -101,38 +101,38 @@ type UpdateContainerInterface interface { // The plugin can request updates both to the container being updated // (which then supersedes the original update) and to other unstopped // containers in response. - UpdateContainer(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error) + UpdateContainer(context.Context, *api.PodSandbox, *api.Container, *api.LinuxResources) ([]*api.ContainerUpdate, error) } // StopContainerInterface handles StopContainer API requests. type StopContainerInterface interface { // StopContainer relays a StopContainer request to the plugin. // The plugin can request updates to unstopped containers in response. - StopContainer(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error) + StopContainer(context.Context, *api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error) } // RemoveContainerInterface handles RemoveContainer API events. type RemoveContainerInterface interface { // RemoveContainer relays a RemoveContainer event to the plugin. - RemoveContainer(*api.PodSandbox, *api.Container) error + RemoveContainer(context.Context, *api.PodSandbox, *api.Container) error } // PostCreateContainerInterface handles PostCreateContainer API events. type PostCreateContainerInterface interface { // PostCreateContainer relays a PostCreateContainer event to the plugin. - PostCreateContainer(*api.PodSandbox, *api.Container) error + PostCreateContainer(context.Context, *api.PodSandbox, *api.Container) error } // PostStartContainerInterface handles PostStartContainer API events. type PostStartContainerInterface interface { // PostStartContainer relays a PostStartContainer event to the plugin. - PostStartContainer(*api.PodSandbox, *api.Container) error + PostStartContainer(context.Context, *api.PodSandbox, *api.Container) error } // PostUpdateContainerInterface handles PostUpdateContainer API events. type PostUpdateContainerInterface interface { // PostUpdateContainer relays a PostUpdateContainer event to the plugin. - PostUpdateContainer(*api.PodSandbox, *api.Container) error + PostUpdateContainer(context.Context, *api.PodSandbox, *api.Container) error } // Stub is the interface the stub provides for the plugin implementation. @@ -253,20 +253,20 @@ type stub struct { // Handlers for NRI plugin event and request. type handlers struct { - Configure func(string, string, string) (api.EventMask, error) - Synchronize func([]*api.PodSandbox, []*api.Container) ([]*api.ContainerUpdate, error) - Shutdown func(*api.ShutdownRequest) - RunPodSandbox func(*api.PodSandbox) error - StopPodSandbox func(*api.PodSandbox) error - RemovePodSandbox func(*api.PodSandbox) error - CreateContainer func(*api.PodSandbox, *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error) - StartContainer func(*api.PodSandbox, *api.Container) error - UpdateContainer func(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error) - StopContainer func(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error) - RemoveContainer func(*api.PodSandbox, *api.Container) error - PostCreateContainer func(*api.PodSandbox, *api.Container) error - PostStartContainer func(*api.PodSandbox, *api.Container) error - PostUpdateContainer func(*api.PodSandbox, *api.Container) error + Configure func(context.Context, string, string, string) (api.EventMask, error) + Synchronize func(context.Context, []*api.PodSandbox, []*api.Container) ([]*api.ContainerUpdate, error) + Shutdown func(context.Context) + RunPodSandbox func(context.Context, *api.PodSandbox) error + StopPodSandbox func(context.Context, *api.PodSandbox) error + RemovePodSandbox func(context.Context, *api.PodSandbox) error + CreateContainer func(context.Context, *api.PodSandbox, *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error) + StartContainer func(context.Context, *api.PodSandbox, *api.Container) error + UpdateContainer func(context.Context, *api.PodSandbox, *api.Container, *api.LinuxResources) ([]*api.ContainerUpdate, error) + StopContainer func(context.Context, *api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error) + RemoveContainer func(context.Context, *api.PodSandbox, *api.Container) error + PostCreateContainer func(context.Context, *api.PodSandbox, *api.Container) error + PostStartContainer func(context.Context, *api.PodSandbox, *api.Container) error + PostUpdateContainer func(context.Context, *api.PodSandbox, *api.Container) error } // New creates a stub with the given plugin and options. @@ -290,7 +290,7 @@ func New(p interface{}, opts ...Option) (Stub, error) { return nil, err } - if err := stub.getIdentity(); err != nil { + if err := stub.ensureIdentity(); err != nil { return nil, err } @@ -552,7 +552,7 @@ func (stub *stub) Configure(ctx context.Context, req *api.ConfigureRequest) (rpl if handler := stub.handlers.Configure; handler == nil { events = stub.events } else { - events, err = handler(req.Config, req.RuntimeName, req.RuntimeVersion) + events, err = handler(ctx, req.Config, req.RuntimeName, req.RuntimeVersion) if err != nil { log.Errorf(ctx, "Plugin configuration failed: %v", err) return nil, err @@ -585,7 +585,7 @@ func (stub *stub) Synchronize(ctx context.Context, req *api.SynchronizeRequest) if handler == nil { return &api.SynchronizeResponse{}, nil } - update, err := handler(req.Pods, req.Containers) + update, err := handler(ctx, req.Pods, req.Containers) return &api.SynchronizeResponse{ Update: update, }, err @@ -595,7 +595,7 @@ func (stub *stub) Synchronize(ctx context.Context, req *api.SynchronizeRequest) func (stub *stub) Shutdown(ctx context.Context, req *api.ShutdownRequest) (*api.ShutdownResponse, error) { handler := stub.handlers.Shutdown if handler != nil { - handler(req) + handler(ctx) } return &api.ShutdownResponse{}, nil } @@ -606,7 +606,7 @@ func (stub *stub) CreateContainer(ctx context.Context, req *api.CreateContainerR if handler == nil { return nil, nil } - adjust, update, err := handler(req.Pod, req.Container) + adjust, update, err := handler(ctx, req.Pod, req.Container) return &api.CreateContainerResponse{ Adjust: adjust, Update: update, @@ -619,7 +619,7 @@ func (stub *stub) UpdateContainer(ctx context.Context, req *api.UpdateContainerR if handler == nil { return nil, nil } - update, err := handler(req.Pod, req.Container) + update, err := handler(ctx, req.Pod, req.Container, req.LinuxResources) return &api.UpdateContainerResponse{ Update: update, }, err @@ -631,7 +631,7 @@ func (stub *stub) StopContainer(ctx context.Context, req *api.StopContainerReque if handler == nil { return nil, nil } - update, err := handler(req.Pod, req.Container) + update, err := handler(ctx, req.Pod, req.Container) return &api.StopContainerResponse{ Update: update, }, err @@ -643,43 +643,43 @@ func (stub *stub) StateChange(ctx context.Context, evt *api.StateChangeEvent) (* switch evt.Event { case api.Event_RUN_POD_SANDBOX: if handler := stub.handlers.RunPodSandbox; handler != nil { - err = handler(evt.Pod) + err = handler(ctx, evt.Pod) } case api.Event_STOP_POD_SANDBOX: if handler := stub.handlers.StopPodSandbox; handler != nil { - err = handler(evt.Pod) + err = handler(ctx, evt.Pod) } case api.Event_REMOVE_POD_SANDBOX: if handler := stub.handlers.RemovePodSandbox; handler != nil { - err = handler(evt.Pod) + err = handler(ctx, evt.Pod) } case api.Event_POST_CREATE_CONTAINER: if handler := stub.handlers.PostCreateContainer; handler != nil { - err = handler(evt.Pod, evt.Container) + err = handler(ctx, evt.Pod, evt.Container) } case api.Event_START_CONTAINER: if handler := stub.handlers.StartContainer; handler != nil { - err = handler(evt.Pod, evt.Container) + err = handler(ctx, evt.Pod, evt.Container) } case api.Event_POST_START_CONTAINER: if handler := stub.handlers.PostStartContainer; handler != nil { - err = handler(evt.Pod, evt.Container) + err = handler(ctx, evt.Pod, evt.Container) } case api.Event_POST_UPDATE_CONTAINER: if handler := stub.handlers.PostUpdateContainer; handler != nil { - err = handler(evt.Pod, evt.Container) + err = handler(ctx, evt.Pod, evt.Container) } case api.Event_REMOVE_CONTAINER: if handler := stub.handlers.RemoveContainer; handler != nil { - err = handler(evt.Pod, evt.Container) + err = handler(ctx, evt.Pod, evt.Container) } } return &api.StateChangeResponse{}, err } -// getIdentity gets plugin index and name from the binary if those are unset. -func (stub *stub) getIdentity() error { +// ensureIdentity sets plugin index and name from the binary if those are unset. +func (stub *stub) ensureIdentity() error { if stub.idx != "" && stub.name != "" { return nil } diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go index b071cea51dd..6aba0ef1f69 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go @@ -436,9 +436,8 @@ func importTar(in io.ReaderAt) (*tarFile, error) { if err != nil { if err == io.EOF { break - } else { - return nil, fmt.Errorf("failed to parse tar file, %w", err) } + return nil, fmt.Errorf("failed to parse tar file, %w", err) } switch cleanEntryName(h.Name) { case PrefetchLandmark, NoPrefetchLandmark: diff --git a/vendor/github.com/containers/common/internal/attributedstring/slice.go b/vendor/github.com/containers/common/internal/attributedstring/slice.go new file mode 100644 index 00000000000..ad4acc5ec1d --- /dev/null +++ b/vendor/github.com/containers/common/internal/attributedstring/slice.go @@ -0,0 +1,102 @@ +package attributedstring + +import ( + "bytes" + "fmt" + + "github.com/BurntSushi/toml" +) + +// Slice allows for extending a TOML string array with custom +// attributes that control how the array is marshaled into a Go string. +// +// Specifically, an Slice can be configured to avoid it being +// overridden by a subsequent unmarshal sequence. When the `append` attribute +// is specified, the array will be appended instead (e.g., `array=["9", +// {append=true}]`). +type Slice struct { // A "mixed-type array" in TOML. + // Note that the fields below _must_ be exported. Otherwise the TOML + // encoder would fail during type reflection. + Values []string + Attributes struct { // Using a struct allows for adding more attributes in the future. + Append *bool // Nil if not set by the user + } +} + +// NewSlice creates a new slice with the specified values. +func NewSlice(values []string) Slice { + return Slice{Values: values} +} + +// Get returns the Slice values or an empty string slice. +func (a *Slice) Get() []string { + if a.Values == nil { + return []string{} + } + return a.Values +} + +// Set overrides the values of the Slice. +func (a *Slice) Set(values []string) { + a.Values = values +} + +// UnmarshalTOML is the custom unmarshal method for Slice. +func (a *Slice) UnmarshalTOML(data interface{}) error { + iFaceSlice, ok := data.([]interface{}) + if !ok { + return fmt.Errorf("unable to cast to interface array: %v", data) + } + + var loadedStrings []string + for _, x := range iFaceSlice { // Iterate over each item in the slice. + switch val := x.(type) { + case string: // Strings are directly appended to the slice. + loadedStrings = append(loadedStrings, val) + case map[string]interface{}: // The attribute struct is represented as a map. + for k, v := range val { // Iterate over all _supported_ keys. + switch k { + case "append": + boolVal, ok := v.(bool) + if !ok { + return fmt.Errorf("unable to cast append to bool: %v", k) + } + a.Attributes.Append = &boolVal + default: // Unsupported map key. + return fmt.Errorf("unsupported key %q in map: %v", k, val) + } + } + default: // Unsupported item. + return fmt.Errorf("unsupported item in attributed string slice: %v", x) + } + } + + if a.Attributes.Append != nil && *a.Attributes.Append { // If _explicitly_ configured, append the loaded slice. + a.Values = append(a.Values, loadedStrings...) + } else { // Default: override the existing Slice. + a.Values = loadedStrings + } + return nil +} + +// MarshalTOML is the custom marshal method for Slice. +func (a *Slice) MarshalTOML() ([]byte, error) { + iFaceSlice := make([]interface{}, 0, len(a.Values)) + + for _, x := range a.Values { + iFaceSlice = append(iFaceSlice, x) + } + + if a.Attributes.Append != nil { + Attributes := make(map[string]any) + Attributes["append"] = *a.Attributes.Append + iFaceSlice = append(iFaceSlice, Attributes) + } + + buf := new(bytes.Buffer) + enc := toml.NewEncoder(buf) + if err := enc.Encode(iFaceSlice); err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/vendor/github.com/containers/common/libimage/copier.go b/vendor/github.com/containers/common/libimage/copier.go index 5f277a69e59..d6acc732501 100644 --- a/vendor/github.com/containers/common/libimage/copier.go +++ b/vendor/github.com/containers/common/libimage/copier.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -5,11 +8,13 @@ import ( "errors" "fmt" "io" + "net" "os" "strings" "time" "github.com/containers/common/libimage/manifests" + "github.com/containers/common/libimage/platform" "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/retry" "github.com/containers/image/v5/copy" @@ -49,6 +54,10 @@ type CopyOptions struct { CompressionFormat *compression.Algorithm // CompressionLevel specifies what compression level is used CompressionLevel *int + // ForceCompressionFormat ensures that the compression algorithm set in + // CompressionFormat is used exclusively, and blobs of other compression + // algorithms are not reused. + ForceCompressionFormat bool // containers-auth.json(5) file to use when authenticating against // container registries. @@ -67,7 +76,7 @@ type CopyOptions struct { // Default 3. MaxRetries *uint // RetryDelay used for the exponential back off of MaxRetries. - // Default 1 time.Scond. + // Default 1 time.Second. RetryDelay *time.Duration // ManifestMIMEType is the desired media type the image will be // converted to if needed. Note that it must contain the exact MIME @@ -146,14 +155,19 @@ type CopyOptions struct { // Additional tags when creating or copying a docker-archive. dockerArchiveAdditionalTags []reference.NamedTagged + + // If set it points to a NOTIFY_SOCKET the copier will use to extend + // the systemd timeout while copying. + extendTimeoutSocket string } // copier is an internal helper to conveniently copy images. type copier struct { - imageCopyOptions copy.Options - retryOptions retry.Options - systemContext *types.SystemContext - policyContext *signature.PolicyContext + extendTimeoutSocket string + imageCopyOptions copy.Options + retryOptions retry.Options + systemContext *types.SystemContext + policyContext *signature.PolicyContext sourceLookup LookupReferenceFunc destinationLookup LookupReferenceFunc @@ -204,7 +218,7 @@ func getDockerAuthConfig(name, passwd, creds, idToken string) (*types.DockerAuth // counterparts of the specified system context. Please make sure to call // `(*copier).close()`. func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { - c := copier{} + c := copier{extendTimeoutSocket: options.extendTimeoutSocket} c.systemContext = r.systemContextCopy() if options.SourceLookupReferenceFunc != nil { @@ -229,7 +243,7 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { c.systemContext.DockerArchiveAdditionalTags = options.dockerArchiveAdditionalTags - c.systemContext.OSChoice, c.systemContext.ArchitectureChoice, c.systemContext.VariantChoice = NormalizePlatform(options.OS, options.Architecture, options.Variant) + c.systemContext.OSChoice, c.systemContext.ArchitectureChoice, c.systemContext.VariantChoice = platform.Normalize(options.OS, options.Architecture, options.Variant) if options.SignaturePolicyPath != "" { c.systemContext.SignaturePolicyPath = options.SignaturePolicyPath @@ -294,6 +308,7 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { c.imageCopyOptions.ProgressInterval = time.Second } + c.imageCopyOptions.ForceCompressionFormat = options.ForceCompressionFormat c.imageCopyOptions.ForceManifestMIMEType = options.ManifestMIMEType c.imageCopyOptions.SourceCtx = c.systemContext c.imageCopyOptions.DestinationCtx = c.systemContext @@ -328,6 +343,65 @@ func (c *copier) close() error { func (c *copier) copy(ctx context.Context, source, destination types.ImageReference) ([]byte, error) { logrus.Debugf("Copying source image %s to destination image %s", source.StringWithinTransport(), destination.StringWithinTransport()) + // Avoid running out of time when running inside a systemd unit by + // regularly increasing the timeout. + if c.extendTimeoutSocket != "" { + socketAddr := &net.UnixAddr{ + Name: c.extendTimeoutSocket, + Net: "unixgram", + } + conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr) + if err != nil { + return nil, err + } + defer conn.Close() + + numExtensions := 10 + extension := 30 * time.Second + timerFrequency := 25 * time.Second // Fire the timer at a higher frequency to avoid a race + timer := time.NewTicker(timerFrequency) + socketCtx, cancel := context.WithCancel(ctx) + defer cancel() + defer timer.Stop() + + fmt.Fprintf(c.imageCopyOptions.ReportWriter, + "Pulling image %s inside systemd: setting pull timeout to %s\n", + source.StringWithinTransport(), + time.Duration(numExtensions)*extension, + ) + + // From `man systemd.service(5)`: + // + // "If a service of Type=notify/Type=notify-reload sends "EXTEND_TIMEOUT_USEC=...", this may cause + // the start time to be extended beyond TimeoutStartSec=. The first receipt of this message must + // occur before TimeoutStartSec= is exceeded, and once the start time has extended beyond + // TimeoutStartSec=, the service manager will allow the service to continue to start, provided the + // service repeats "EXTEND_TIMEOUT_USEC=..." within the interval specified until the service startup + // status is finished by "READY=1"." + extendValue := []byte(fmt.Sprintf("EXTEND_TIMEOUT_USEC=%d", extension.Microseconds())) + extendTimeout := func() { + if _, err := conn.Write(extendValue); err != nil { + logrus.Errorf("Increasing EXTEND_TIMEOUT_USEC failed: %v", err) + } + numExtensions-- + } + + extendTimeout() + go func() { + for { + select { + case <-socketCtx.Done(): + return + case <-timer.C: + if numExtensions == 0 { + return + } + extendTimeout() + } + } + }() + } + var err error if c.sourceLookup != nil { diff --git a/vendor/github.com/containers/common/libimage/define/manifests.go b/vendor/github.com/containers/common/libimage/define/manifests.go new file mode 100644 index 00000000000..1e02984b2a4 --- /dev/null +++ b/vendor/github.com/containers/common/libimage/define/manifests.go @@ -0,0 +1,27 @@ +package define + +import ( + "github.com/containers/image/v5/manifest" +) + +// ManifestListDescriptor references a platform-specific manifest. +// Contains exclusive field like `annotations` which is only present in +// OCI spec and not in docker image spec. +type ManifestListDescriptor struct { + manifest.Schema2Descriptor + Platform manifest.Schema2PlatformSpec `json:"platform"` + // Annotations contains arbitrary metadata for the image index. + Annotations map[string]string `json:"annotations,omitempty"` +} + +// ManifestListData is a list of platform-specific manifests, specifically used to +// generate output struct for `podman manifest inspect`. Reason for maintaining and +// having this type is to ensure we can have a common type which contains exclusive +// fields from both Docker manifest format and OCI manifest format. +type ManifestListData struct { + SchemaVersion int `json:"schemaVersion"` + MediaType string `json:"mediaType"` + Manifests []ManifestListDescriptor `json:"manifests"` + // Annotations contains arbitrary metadata for the image index. + Annotations map[string]string `json:"annotations,omitempty"` +} diff --git a/vendor/github.com/containers/common/libimage/define/platform.go b/vendor/github.com/containers/common/libimage/define/platform.go new file mode 100644 index 00000000000..7e13abffd7c --- /dev/null +++ b/vendor/github.com/containers/common/libimage/define/platform.go @@ -0,0 +1,11 @@ +package define + +// PlatformPolicy controls the behavior of image-platform matching. +type PlatformPolicy int + +const ( + // Only debug log if an image does not match the expected platform. + PlatformPolicyDefault PlatformPolicy = iota + // Warn if an image does not match the expected platform. + PlatformPolicyWarn +) diff --git a/vendor/github.com/containers/common/libimage/disk_usage.go b/vendor/github.com/containers/common/libimage/disk_usage.go index f27edc03bd5..765b0df862f 100644 --- a/vendor/github.com/containers/common/libimage/disk_usage.go +++ b/vendor/github.com/containers/common/libimage/disk_usage.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/events.go b/vendor/github.com/containers/common/libimage/events.go index c7733564db5..5d82efa6a17 100644 --- a/vendor/github.com/containers/common/libimage/events.go +++ b/vendor/github.com/containers/common/libimage/events.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/filter/filter.go b/vendor/github.com/containers/common/libimage/filter/filter.go new file mode 100644 index 00000000000..098d2998dd6 --- /dev/null +++ b/vendor/github.com/containers/common/libimage/filter/filter.go @@ -0,0 +1,55 @@ +package filter + +import ( + "fmt" + "strconv" + "strings" + + "github.com/containers/common/libimage/define" + "github.com/containers/image/v5/types" +) + +// SearchFilter allows filtering images while searching. +type SearchFilter struct { + // Stars describes the minimal amount of starts of an image. + Stars int + // IsAutomated decides if only images from automated builds are displayed. + IsAutomated types.OptionalBool + // IsOfficial decides if only official images are displayed. + IsOfficial types.OptionalBool +} + +// ParseSearchFilter turns the filter into a SearchFilter that can be used for +// searching images. +func ParseSearchFilter(filter []string) (*SearchFilter, error) { + sFilter := new(SearchFilter) + for _, f := range filter { + arr := strings.SplitN(f, "=", 2) + switch arr[0] { + case define.SearchFilterStars: + if len(arr) < 2 { + return nil, fmt.Errorf("invalid filter %q, should be stars=", filter) + } + stars, err := strconv.Atoi(arr[1]) + if err != nil { + return nil, fmt.Errorf("incorrect value type for stars filter: %w", err) + } + sFilter.Stars = stars + case define.SearchFilterAutomated: + if len(arr) == 2 && arr[1] == "false" { + sFilter.IsAutomated = types.OptionalBoolFalse + } else { + sFilter.IsAutomated = types.OptionalBoolTrue + } + case define.SearchFilterOfficial: + if len(arr) == 2 && arr[1] == "false" { + sFilter.IsOfficial = types.OptionalBoolFalse + } else { + sFilter.IsOfficial = types.OptionalBoolTrue + } + default: + return nil, fmt.Errorf("invalid filter type %q", f) + } + } + return sFilter, nil +} diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go index 995f89c7848..b51853af19d 100644 --- a/vendor/github.com/containers/common/libimage/filters.go +++ b/vendor/github.com/containers/common/libimage/filters.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -109,7 +112,6 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp key = split[0] value = split[1] switch key { - case "after", "since": img, err := r.time(key, value) if err != nil { @@ -147,7 +149,11 @@ func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOp filter = filterID(value) case "digest": - filter = filterDigest(value) + f, err := filterDigest(value) + if err != nil { + return nil, err + } + filter = f case "intermediate": intermediate, err := r.bool(duplicate, key, value) @@ -239,7 +245,7 @@ func (r *Runtime) until(value string) (time.Time, error) { func (r *Runtime) time(key, value string) (*Image, error) { img, _, err := r.LookupImage(value, nil) if err != nil { - return nil, fmt.Errorf("could not find local image for filter filter %q=%q: %w", key, value, err) + return nil, fmt.Errorf("could not find local image for filter %q=%q: %w", key, value, err) } return img, nil } @@ -286,7 +292,7 @@ func filterReferences(r *Runtime, value string) filterFunc { refString := ref.String() // FQN with tag/digest candidates := []string{refString} - // Split the reference into 3 components (twice if diggested/tagged): + // Split the reference into 3 components (twice if digested/tagged): // 1) Fully-qualified reference // 2) Without domain // 3) Without domain and path @@ -390,17 +396,18 @@ func filterDangling(ctx context.Context, value bool, tree *layerTree) filterFunc // filterID creates an image-ID filter for matching the specified value. func filterID(value string) filterFunc { return func(img *Image) (bool, error) { - return img.ID() == value, nil + return strings.HasPrefix(img.ID(), value), nil } } // filterDigest creates a digest filter for matching the specified value. -func filterDigest(value string) filterFunc { - // TODO: return an error if value is not a digest - // if _, err := digest.Parse(value); err != nil {...} - return func(img *Image) (bool, error) { - return img.hasDigest(value), nil +func filterDigest(value string) (filterFunc, error) { + if !strings.HasPrefix(value, "sha256:") { + return nil, fmt.Errorf("invalid value %q for digest filter", value) } + return func(img *Image) (bool, error) { + return img.containsDigestPrefix(value), nil + }, nil } // filterIntermediate creates an intermediate filter for images. An image is diff --git a/vendor/github.com/containers/common/libimage/history.go b/vendor/github.com/containers/common/libimage/history.go index ad989b528a6..ccd810962ca 100644 --- a/vendor/github.com/containers/common/libimage/history.go +++ b/vendor/github.com/containers/common/libimage/history.go @@ -1,10 +1,12 @@ +//go:build !remote +// +build !remote + package libimage import ( "context" + "fmt" "time" - - "github.com/containers/storage" ) // ImageHistory contains the history information of an image. @@ -29,17 +31,19 @@ func (i *Image) History(ctx context.Context) ([]ImageHistory, error) { return nil, err } - var allHistory []ImageHistory - var layer *storage.Layer + var nextNode *layerNode if i.TopLayer() != "" { - layer, err = i.runtime.store.Layer(i.TopLayer()) + layer, err := i.runtime.store.Layer(i.TopLayer()) if err != nil { return nil, err } + nextNode = layerTree.node(layer.ID) } // Iterate in reverse order over the history entries, and lookup the - // corresponding image ID, size and get the next later if needed. + // corresponding image ID, size. If it's a non-empty history entry, + // pick the next "storage" layer by walking the layer tree. + var allHistory []ImageHistory numHistories := len(ociImage.History) - 1 usedIDs := make(map[string]bool) // prevents assigning images IDs more than once for x := numHistories; x >= 0; x-- { @@ -50,31 +54,25 @@ func (i *Image) History(ctx context.Context) ([]ImageHistory, error) { Comment: ociImage.History[x].Comment, } - if layer != nil { - if !ociImage.History[x].EmptyLayer { - history.Size = layer.UncompressedSize + if nextNode != nil && len(nextNode.images) > 0 { + id := nextNode.images[0].ID() // always use the first one + if _, used := usedIDs[id]; !used { + history.ID = id + usedIDs[id] = true } - // Query the layer tree if it's the top layer of an - // image. - node := layerTree.node(layer.ID) - if len(node.images) > 0 { - id := node.images[0].ID() // always use the first one - if _, used := usedIDs[id]; !used { - history.ID = id - usedIDs[id] = true - } - for i := range node.images { - history.Tags = append(history.Tags, node.images[i].Names()...) - } + for i := range nextNode.images { + history.Tags = append(history.Tags, nextNode.images[i].Names()...) } - if layer.Parent == "" { - layer = nil - } else if !ociImage.History[x].EmptyLayer { - layer, err = i.runtime.store.Layer(layer.Parent) - if err != nil { - return nil, err - } + } + + if !ociImage.History[x].EmptyLayer { + if nextNode == nil { // If no layer's left, something's wrong. + return nil, fmt.Errorf("no layer left for non-empty history entry: %v", history) } + + history.Size = nextNode.layer.UncompressedSize + + nextNode = nextNode.parent } allHistory = append(allHistory, history) diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index dc47030c561..4d106d42f87 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -9,6 +12,8 @@ import ( "strings" "time" + "github.com/containerd/containerd/platforms" + "github.com/containers/common/libimage/platform" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/manifest" storageTransport "github.com/containers/image/v5/storage" @@ -91,13 +96,14 @@ func (i *Image) isCorrupted(name string) error { return err } - if _, err := ref.NewImage(context.Background(), nil); err != nil { + img, err := ref.NewImage(context.Background(), nil) + if err != nil { if name == "" { name = i.ID()[:12] } return fmt.Errorf("Image %s exists in local storage but may be corrupted (remove the image to resolve the issue): %v", name, err) } - return nil + return img.Close() } // Names returns associated names with the image which may be a mix of tags and @@ -159,10 +165,20 @@ func (i *Image) Digests() []digest.Digest { // hasDigest returns whether the specified value matches any digest of the // image. -func (i *Image) hasDigest(value string) bool { - // TODO: change the argument to a typed digest.Digest +func (i *Image) hasDigest(wantedDigest digest.Digest) bool { for _, d := range i.Digests() { - if string(d) == value { + if d == wantedDigest { + return true + } + } + return false +} + +// containsDigestPrefix returns whether the specified value matches any digest of the +// image. It checks for the prefix and not a full match. +func (i *Image) containsDigestPrefix(wantedDigestPrefix string) bool { + for _, d := range i.Digests() { + if strings.HasPrefix(d.String(), wantedDigestPrefix) { return true } } @@ -567,8 +583,7 @@ func (i *Image) Tag(name string) error { defer i.runtime.writeEvent(&Event{ID: i.ID(), Name: name, Time: time.Now(), Type: EventTypeImageTag}) } - newNames := append(i.Names(), ref.String()) - if err := i.runtime.store.SetNames(i.ID(), newNames); err != nil { + if err := i.runtime.store.AddNames(i.ID(), []string{ref.String()}); err != nil { return err } @@ -592,7 +607,7 @@ func (i *Image) Untag(name string) error { ref, err := NormalizeName(name) if err != nil { - return fmt.Errorf("normalizing name %q: %w", name, err) + return err } // FIXME: this is breaking Podman CI but must be re-enabled once @@ -607,26 +622,25 @@ func (i *Image) Untag(name string) error { name = ref.String() - logrus.Debugf("Untagging %q from image %s", ref.String(), i.ID()) - if i.runtime.eventChannel != nil { - defer i.runtime.writeEvent(&Event{ID: i.ID(), Name: name, Time: time.Now(), Type: EventTypeImageUntag}) - } - - removedName := false - newNames := []string{} + foundName := false for _, n := range i.Names() { if n == name { - removedName = true - continue + foundName = true + break } - newNames = append(newNames, n) } - - if !removedName { + // Return an error if the name is not found, the c/storage + // RemoveNames() API does not create one if no match is found. + if !foundName { return fmt.Errorf("%s: %w", name, errTagUnknown) } - if err := i.runtime.store.SetNames(i.ID(), newNames); err != nil { + logrus.Debugf("Untagging %q from image %s", ref.String(), i.ID()) + if i.runtime.eventChannel != nil { + defer i.runtime.writeEvent(&Event{ID: i.ID(), Name: name, Time: time.Now(), Type: EventTypeImageUntag}) + } + + if err := i.runtime.store.RemoveNames(i.ID(), []string{name}); err != nil { return err } @@ -686,24 +700,22 @@ func (i *Image) NamedRepoTags() ([]reference.Named, error) { return repoTags, nil } -// inRepoTags looks for the specified name/tag in the image's repo tags. If -// `ignoreTag` is set, only the repo must match and the tag is ignored. -func (i *Image) inRepoTags(namedTagged reference.NamedTagged, ignoreTag bool) (reference.Named, error) { +// referenceFuzzilyMatchingRepoAndTag checks if the image’s repo (and tag if requiredTag != "") matches a fuzzy short input, +// and if so, returns the matching reference. +// +// DO NOT ADD ANY NEW USERS OF THIS SEMANTICS. Rely on existing libimage calls like LookupImage instead, +// and handle unqualified the way it does (c/image/pkg/shortnames). +func (i *Image) referenceFuzzilyMatchingRepoAndTag(requiredRepo reference.Named, requiredTag string) (reference.Named, error) { repoTags, err := i.NamedRepoTags() if err != nil { return nil, err } - name := namedTagged.Name() - tag := namedTagged.Tag() + name := requiredRepo.Name() for _, r := range repoTags { - if !ignoreTag { - var repoTag string + if requiredTag != "" { tagged, isTagged := r.(reference.NamedTagged) - if isTagged { - repoTag = tagged.Tag() - } - if !isTagged || tag != repoTag { + if !isTagged || tagged.Tag() != requiredTag { continue } } @@ -875,6 +887,7 @@ func (i *Image) hasDifferentDigestWithSystemContext(ctx context.Context, remoteR if err != nil { return false, err } + defer remoteImg.Close() rawManifest, rawManifestMIMEType, err := remoteImg.Manifest(ctx) if err != nil { @@ -1011,3 +1024,35 @@ func getImageID(ctx context.Context, src types.ImageReference, sys *types.System } return "@" + imageDigest.Encoded(), nil } + +// Checks whether the image matches the specified platform. +// Returns +// - 1) a matching error that can be used for logging (or returning) what does not match +// - 2) a bool indicating whether architecture, os or variant were set (some callers need that to decide whether they need to throw an error) +// - 3) a fatal error that occurred prior to check for matches (e.g., storage errors etc.) +func (i *Image) matchesPlatform(ctx context.Context, os, arch, variant string) (error, bool, error) { + if err := i.isCorrupted(""); err != nil { + return err, false, nil + } + inspectInfo, err := i.inspectInfo(ctx) + if err != nil { + return nil, false, fmt.Errorf("inspecting image: %w", err) + } + + customPlatform := len(os)+len(arch)+len(variant) != 0 + + expected, err := platforms.Parse(platform.ToString(os, arch, variant)) + if err != nil { + return nil, false, fmt.Errorf("parsing host platform: %v", err) + } + fromImage, err := platforms.Parse(platform.ToString(inspectInfo.Os, inspectInfo.Architecture, inspectInfo.Variant)) + if err != nil { + return nil, false, fmt.Errorf("parsing image platform: %v", err) + } + + if platforms.NewMatcher(expected).Match(fromImage) { + return nil, customPlatform, nil + } + + return fmt.Errorf("image platform (%s) does not match the expected platform (%s)", platforms.Format(fromImage), platforms.Format(expected)), customPlatform, nil +} diff --git a/vendor/github.com/containers/common/libimage/image_config.go b/vendor/github.com/containers/common/libimage/image_config.go index b311aa22e3f..9f5841fe142 100644 --- a/vendor/github.com/containers/common/libimage/image_config.go +++ b/vendor/github.com/containers/common/libimage/image_config.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -88,7 +91,7 @@ func ImageConfigFromChanges(changes []string) (*ImageConfig, error) { // nolint: case "ENV": // Format is either: // ENV key=value - // ENV key=value key=value ... + // ENV key-1=value key-2=value ... // ENV key value // Both keys and values can be surrounded by quotes to group them. // For now: we only support key=value diff --git a/vendor/github.com/containers/common/libimage/image_tree.go b/vendor/github.com/containers/common/libimage/image_tree.go index 9c958ce6b1e..8143d3779c3 100644 --- a/vendor/github.com/containers/common/libimage/image_tree.go +++ b/vendor/github.com/containers/common/libimage/image_tree.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/import.go b/vendor/github.com/containers/common/libimage/import.go index 6e739f93fc2..5519f02ba7a 100644 --- a/vendor/github.com/containers/common/libimage/import.go +++ b/vendor/github.com/containers/common/libimage/import.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -66,7 +69,7 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption u, err := url.ParseRequestURI(path) if err == nil && u.Scheme != "" { // If source is a URL, download the file. - fmt.Printf("Downloading from %q\n", path) + fmt.Printf("Downloading from %q\n", path) //nolint:forbidigo file, err := download.FromURL(r.systemContext.BigFilesTemporaryDir, path) if err != nil { return "", err diff --git a/vendor/github.com/containers/common/libimage/inspect.go b/vendor/github.com/containers/common/libimage/inspect.go index c6632d9a23b..1003b6483e2 100644 --- a/vendor/github.com/containers/common/libimage/inspect.go +++ b/vendor/github.com/containers/common/libimage/inspect.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/layer_tree.go b/vendor/github.com/containers/common/libimage/layer_tree.go index e6b012f908f..71eafb0e703 100644 --- a/vendor/github.com/containers/common/libimage/layer_tree.go +++ b/vendor/github.com/containers/common/libimage/layer_tree.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -199,6 +202,17 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I if parent.TopLayer() == "" { for i := range t.emptyImages { empty := t.emptyImages[i] + isManifest, err := empty.IsManifestList(ctx) + if err != nil { + return nil, err + } + if isManifest { + // If this is a manifest list and is already + // marked as empty then no instance can be + // selected from this list therefore its + // better to skip this. + continue + } isParent, err := checkParent(empty) if err != nil { return nil, err @@ -289,6 +303,17 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { if childID == empty.ID() { continue } + isManifest, err := empty.IsManifestList(ctx) + if err != nil { + return nil, err + } + if isManifest { + // If this is a manifest list and is already + // marked as empty then no instance can be + // selected from this list therefore its + // better to skip this. + continue + } emptyOCI, err := t.toOCI(ctx, empty) if err != nil { if ErrorIsImageUnknown(err) { diff --git a/vendor/github.com/containers/common/libimage/load.go b/vendor/github.com/containers/common/libimage/load.go index 72c56f122ac..36283a99b95 100644 --- a/vendor/github.com/containers/common/libimage/load.go +++ b/vendor/github.com/containers/common/libimage/load.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/manifest_list.go b/vendor/github.com/containers/common/libimage/manifest_list.go index 0223fb3557e..c36bfda968c 100644 --- a/vendor/github.com/containers/common/libimage/manifest_list.go +++ b/vendor/github.com/containers/common/libimage/manifest_list.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -6,6 +9,7 @@ import ( "fmt" "time" + "github.com/containers/common/libimage/define" "github.com/containers/common/libimage/manifests" imageCopy "github.com/containers/image/v5/copy" "github.com/containers/image/v5/docker" @@ -40,28 +44,6 @@ type ManifestList struct { list manifests.List } -// ManifestListDescriptor references a platform-specific manifest. -// Contains exclusive field like `annotations` which is only present in -// OCI spec and not in docker image spec. -type ManifestListDescriptor struct { - manifest.Schema2Descriptor - Platform manifest.Schema2PlatformSpec `json:"platform"` - // Annotations contains arbitrary metadata for the image index. - Annotations map[string]string `json:"annotations,omitempty"` -} - -// ManifestListData is a list of platform-specific manifests, specifically used to -// generate output struct for `podman manifest inspect`. Reason for maintaining and -// having this type is to ensure we can have a common type which contains exclusive -// fields from both Docker manifest format and OCI manifest format. -type ManifestListData struct { - SchemaVersion int `json:"schemaVersion"` - MediaType string `json:"mediaType"` - Manifests []ManifestListDescriptor `json:"manifests"` - // Annotations contains arbitrary metadata for the image index. - Annotations map[string]string `json:"annotations,omitempty"` -} - // ID returns the ID of the manifest list. func (m *ManifestList) ID() string { return m.image.ID() @@ -238,8 +220,8 @@ func (i *Image) IsManifestList(ctx context.Context) (bool, error) { } // Inspect returns a dockerized version of the manifest list. -func (m *ManifestList) Inspect() (*ManifestListData, error) { - inspectList := ManifestListData{} +func (m *ManifestList) Inspect() (*define.ManifestListData, error) { + inspectList := define.ManifestListData{} dockerFormat := m.list.Docker() err := structcopier.Copy(&inspectList, &dockerFormat) if err != nil { @@ -415,6 +397,8 @@ type ManifestListPushOptions struct { ImageListSelection imageCopy.ImageListSelection // Use when selecting only specific imags. Instances []digest.Digest + // Add existing instances with requested compression algorithms to manifest list + AddCompression []string } // Push pushes a manifest to the specified destination. @@ -446,6 +430,7 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma defer copier.close() pushOptions := manifests.PushOptions{ + AddCompression: options.AddCompression, Store: m.image.runtime.store, SystemContext: copier.systemContext, ImageListSelection: options.ImageListSelection, @@ -458,6 +443,9 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma SignSigstorePrivateKeyPassphrase: options.SignSigstorePrivateKeyPassphrase, RemoveSignatures: options.RemoveSignatures, ManifestType: options.ManifestMIMEType, + MaxRetries: options.MaxRetries, + RetryDelay: options.RetryDelay, + ForceCompressionFormat: options.ForceCompressionFormat, } _, d, err := m.list.Push(ctx, dest, pushOptions) diff --git a/vendor/github.com/containers/common/libimage/manifests/manifests.go b/vendor/github.com/containers/common/libimage/manifests/manifests.go index 7a51b84237b..d28ac87bba0 100644 --- a/vendor/github.com/containers/common/libimage/manifests/manifests.go +++ b/vendor/github.com/containers/common/libimage/manifests/manifests.go @@ -4,16 +4,18 @@ import ( "context" "encoding/json" "errors" - stderrors "errors" "fmt" "io" + "time" "github.com/containers/common/pkg/manifests" + "github.com/containers/common/pkg/retry" "github.com/containers/common/pkg/supplemented" cp "github.com/containers/image/v5/copy" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/image" "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/pkg/compression" "github.com/containers/image/v5/signature" "github.com/containers/image/v5/signature/signer" is "github.com/containers/image/v5/storage" @@ -27,6 +29,10 @@ import ( "github.com/sirupsen/logrus" ) +const ( + defaultMaxRetries = 3 +) + const instancesData = "instances.json" // LookupReferenceFunc return an image reference based on the specified one. @@ -37,7 +43,7 @@ type LookupReferenceFunc func(ref types.ImageReference) (types.ImageReference, e // ErrListImageUnknown is returned when we attempt to create an image reference // for a List that has not yet been saved to an image. -var ErrListImageUnknown = stderrors.New("unable to determine which image holds the manifest list") +var ErrListImageUnknown = errors.New("unable to determine which image holds the manifest list") type list struct { manifests.List @@ -70,6 +76,13 @@ type PushOptions struct { RemoveSignatures bool // true to discard signatures in images ManifestType string // the format to use when saving the list - possible options are oci, v2s1, and v2s2 SourceFilter LookupReferenceFunc // filter the list source + AddCompression []string // add existing instances with requested compression algorithms to manifest list + ForceCompressionFormat bool // force push with requested compression ignoring the blobs which can be reused. + // Maximum number of retries with exponential backoff when facing + // transient network errors. Default 3. + MaxRetries *uint + // RetryDelay used for the exponential back off of MaxRetries. + RetryDelay *time.Duration } // Create creates a new list containing information about the specified image, @@ -239,6 +252,10 @@ func (l *list) Push(ctx context.Context, dest types.ImageReference, options Push return nil, "", err } } + compressionVariants, err := prepareAddWithCompression(options.AddCompression) + if err != nil { + return nil, "", err + } copyOptions := &cp.Options{ ImageListSelection: options.ImageListSelection, Instances: options.Instances, @@ -252,18 +269,47 @@ func (l *list) Push(ctx context.Context, dest types.ImageReference, options Push SignBySigstorePrivateKeyFile: options.SignBySigstorePrivateKeyFile, SignSigstorePrivateKeyPassphrase: options.SignSigstorePrivateKeyPassphrase, ForceManifestMIMEType: singleImageManifestType, + EnsureCompressionVariantsExist: compressionVariants, + ForceCompressionFormat: options.ForceCompressionFormat, + } + + retryOptions := retry.Options{} + retryOptions.MaxRetry = defaultMaxRetries + if options.MaxRetries != nil { + retryOptions.MaxRetry = int(*options.MaxRetries) + } + if options.RetryDelay != nil { + retryOptions.Delay = *options.RetryDelay } // Copy whatever we were asked to copy. - manifestBytes, err := cp.Image(ctx, policyContext, dest, src, copyOptions) - if err != nil { - return nil, "", err + var manifestDigest digest.Digest + f := func() error { + opts := copyOptions + var manifestBytes []byte + var digest digest.Digest + var err error + if manifestBytes, err = cp.Image(ctx, policyContext, dest, src, opts); err == nil { + if digest, err = manifest.Digest(manifestBytes); err == nil { + manifestDigest = digest + } + } + return err } - manifestDigest, err := manifest.Digest(manifestBytes) - if err != nil { - return nil, "", err + err = retry.IfNecessary(ctx, f, &retryOptions) + return nil, manifestDigest, err +} + +func prepareAddWithCompression(variants []string) ([]cp.OptionCompressionVariant, error) { + res := []cp.OptionCompressionVariant{} + for _, name := range variants { + algo, err := compression.AlgorithmByName(name) + if err != nil { + return nil, fmt.Errorf("requested algorithm %s is not supported for replication: %w", name, err) + } + res = append(res, cp.OptionCompressionVariant{Algorithm: algo}) } - return nil, manifestDigest, nil + return res, nil } // Add adds information about the specified image to the list, computing the diff --git a/vendor/github.com/containers/common/libimage/normalize.go b/vendor/github.com/containers/common/libimage/normalize.go index 9619b1a0d11..2b3402861d9 100644 --- a/vendor/github.com/containers/common/libimage/normalize.go +++ b/vendor/github.com/containers/common/libimage/normalize.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/oci.go b/vendor/github.com/containers/common/libimage/oci.go index b88d6613d74..fcbd10ada5d 100644 --- a/vendor/github.com/containers/common/libimage/oci.go +++ b/vendor/github.com/containers/common/libimage/oci.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/platform.go b/vendor/github.com/containers/common/libimage/platform.go index 06c15ee648f..c378bc27ff0 100644 --- a/vendor/github.com/containers/common/libimage/platform.go +++ b/vendor/github.com/containers/common/libimage/platform.go @@ -1,100 +1,29 @@ +//go:build !remote +// +build !remote + package libimage import ( - "context" - "fmt" - "runtime" - - "github.com/containerd/containerd/platforms" - v1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" + "github.com/containers/common/libimage/define" + "github.com/containers/common/libimage/platform" ) // PlatformPolicy controls the behavior of image-platform matching. -type PlatformPolicy int +// Deprecated: new code should use define.PlatformPolicy directly. +type PlatformPolicy = define.PlatformPolicy const ( // Only debug log if an image does not match the expected platform. - PlatformPolicyDefault PlatformPolicy = iota + // Deprecated: new code should reference define.PlatformPolicyDefault directly. + PlatformPolicyDefault = define.PlatformPolicyDefault // Warn if an image does not match the expected platform. - PlatformPolicyWarn + // Deprecated: new code should reference define.PlatformPolicyWarn directly. + PlatformPolicyWarn = define.PlatformPolicyWarn ) // NormalizePlatform normalizes (according to the OCI spec) the specified os, -// arch and variant. If left empty, the individual item will be normalized. +// arch and variant. If left empty, the individual item will be normalized. +// Deprecated: new code should call libimage/platform.Normalize() instead. func NormalizePlatform(rawOS, rawArch, rawVariant string) (os, arch, variant string) { - platformSpec := v1.Platform{ - OS: rawOS, - Architecture: rawArch, - Variant: rawVariant, - } - normalizedSpec := platforms.Normalize(platformSpec) - if normalizedSpec.Variant == "" && rawVariant != "" { - normalizedSpec.Variant = rawVariant - } - rawPlatform := toPlatformString(normalizedSpec.OS, normalizedSpec.Architecture, normalizedSpec.Variant) - normalizedPlatform, err := platforms.Parse(rawPlatform) - if err != nil { - logrus.Debugf("Error normalizing platform: %v", err) - return rawOS, rawArch, rawVariant - } - logrus.Debugf("Normalized platform %s to %s", rawPlatform, normalizedPlatform) - os = rawOS - if rawOS != "" { - os = normalizedPlatform.OS - } - arch = rawArch - if rawArch != "" { - arch = normalizedPlatform.Architecture - } - variant = rawVariant - if rawVariant != "" || (rawVariant == "" && normalizedPlatform.Variant != "") { - variant = normalizedPlatform.Variant - } - return os, arch, variant -} - -func toPlatformString(os, arch, variant string) string { - if os == "" { - os = runtime.GOOS - } - if arch == "" { - arch = runtime.GOARCH - } - if variant == "" { - return fmt.Sprintf("%s/%s", os, arch) - } - return fmt.Sprintf("%s/%s/%s", os, arch, variant) -} - -// Checks whether the image matches the specified platform. -// Returns -// - 1) a matching error that can be used for logging (or returning) what does not match -// - 2) a bool indicating whether architecture, os or variant were set (some callers need that to decide whether they need to throw an error) -// - 3) a fatal error that occurred prior to check for matches (e.g., storage errors etc.) -func (i *Image) matchesPlatform(ctx context.Context, os, arch, variant string) (error, bool, error) { - if err := i.isCorrupted(""); err != nil { - return err, false, nil - } - inspectInfo, err := i.inspectInfo(ctx) - if err != nil { - return nil, false, fmt.Errorf("inspecting image: %w", err) - } - - customPlatform := len(os)+len(arch)+len(variant) != 0 - - expected, err := platforms.Parse(toPlatformString(os, arch, variant)) - if err != nil { - return nil, false, fmt.Errorf("parsing host platform: %v", err) - } - fromImage, err := platforms.Parse(toPlatformString(inspectInfo.Os, inspectInfo.Architecture, inspectInfo.Variant)) - if err != nil { - return nil, false, fmt.Errorf("parsing image platform: %v", err) - } - - if platforms.NewMatcher(expected).Match(fromImage) { - return nil, customPlatform, nil - } - - return fmt.Errorf("image platform (%s) does not match the expected platform (%s)", platforms.Format(fromImage), platforms.Format(expected)), customPlatform, nil + return platform.Normalize(rawOS, rawArch, rawVariant) } diff --git a/vendor/github.com/containers/common/libimage/platform/platform.go b/vendor/github.com/containers/common/libimage/platform/platform.go new file mode 100644 index 00000000000..2272cee757c --- /dev/null +++ b/vendor/github.com/containers/common/libimage/platform/platform.go @@ -0,0 +1,57 @@ +package platform + +import ( + "fmt" + "runtime" + + "github.com/containerd/containerd/platforms" + v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/sirupsen/logrus" +) + +// Normalize normalizes (according to the OCI spec) the specified os, +// arch and variant. If left empty, the individual item will be normalized. +func Normalize(rawOS, rawArch, rawVariant string) (os, arch, variant string) { + platformSpec := v1.Platform{ + OS: rawOS, + Architecture: rawArch, + Variant: rawVariant, + } + normalizedSpec := platforms.Normalize(platformSpec) + if normalizedSpec.Variant == "" && rawVariant != "" { + normalizedSpec.Variant = rawVariant + } + rawPlatform := ToString(normalizedSpec.OS, normalizedSpec.Architecture, normalizedSpec.Variant) + normalizedPlatform, err := platforms.Parse(rawPlatform) + if err != nil { + logrus.Debugf("Error normalizing platform: %v", err) + return rawOS, rawArch, rawVariant + } + logrus.Debugf("Normalized platform %s to %s", rawPlatform, normalizedPlatform) + os = rawOS + if rawOS != "" { + os = normalizedPlatform.OS + } + arch = rawArch + if rawArch != "" { + arch = normalizedPlatform.Architecture + } + variant = rawVariant + if rawVariant != "" || (rawVariant == "" && normalizedPlatform.Variant != "") { + variant = normalizedPlatform.Variant + } + return os, arch, variant +} + +func ToString(os, arch, variant string) string { + if os == "" { + os = runtime.GOOS + } + if arch == "" { + arch = runtime.GOARCH + } + if variant == "" { + return fmt.Sprintf("%s/%s", os, arch) + } + return fmt.Sprintf("%s/%s/%s", os, arch, variant) +} diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go index 296d003a847..bc8e8498167 100644 --- a/vendor/github.com/containers/common/libimage/pull.go +++ b/vendor/github.com/containers/common/libimage/pull.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -5,6 +8,7 @@ import ( "errors" "fmt" "io" + "os" "runtime" "strings" "time" @@ -137,7 +141,6 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP // Dispatch the copy operation. switch ref.Transport().Name() { - // DOCKER REGISTRY case registryTransport.Transport.Name(): pulledImages, pullError = r.copyFromRegistry(ctx, ref, possiblyUnqualifiedName, pullPolicy, options) @@ -217,7 +220,6 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, // Figure out a name for the storage destination. var storageName, imageName string switch ref.Transport().Name() { - case dockerDaemonTransport.Transport.Name(): // Normalize to docker.io if needed (see containers/podman/issues/10998). named, err := reference.ParseNormalizedNamed(ref.StringWithinTransport()) @@ -229,8 +231,18 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, case ociTransport.Transport.Name(): split := strings.SplitN(ref.StringWithinTransport(), ":", 2) - storageName = toLocalImageName(split[0]) - imageName = storageName + if len(split) == 1 || split[1] == "" { + // Same trick as for the dir transport: we cannot use + // the path to a directory as the name. + storageName, err = getImageID(ctx, ref, nil) + if err != nil { + return nil, err + } + imageName = "sha256:" + storageName[1:] + } else { // If the OCI-reference includes an image reference, use it + storageName = split[1] + imageName = storageName + } case ociArchiveTransport.Transport.Name(): manifestDescriptor, err := ociArchiveTransport.LoadManifestDescriptorWithContext(r.SystemContext(), ref) @@ -592,6 +604,9 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str return nil } + if socketPath, ok := os.LookupEnv("NOTIFY_SOCKET"); ok { + options.extendTimeoutSocket = socketPath + } c, err := r.newCopier(&options.CopyOptions) if err != nil { return nil, err diff --git a/vendor/github.com/containers/common/libimage/push.go b/vendor/github.com/containers/common/libimage/push.go index 7203838aa61..ed1d90c14b9 100644 --- a/vendor/github.com/containers/common/libimage/push.go +++ b/vendor/github.com/containers/common/libimage/push.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go index 7707d2e3bd7..1948fe0ad83 100644 --- a/vendor/github.com/containers/common/libimage/runtime.go +++ b/vendor/github.com/containers/common/libimage/runtime.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( @@ -7,6 +10,8 @@ import ( "os" "strings" + "github.com/containers/common/libimage/define" + "github.com/containers/common/libimage/platform" "github.com/containers/common/pkg/config" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/pkg/shortnames" @@ -184,7 +189,7 @@ type LookupImageOptions struct { Variant string // Controls the behavior when checking the platform of an image. - PlatformPolicy PlatformPolicy + PlatformPolicy define.PlatformPolicy // If set, do not look for items/instances in the manifest list that // match the current platform but return the manifest list as is. @@ -283,7 +288,7 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image, options.Variant = r.systemContext.VariantChoice } // Normalize platform to be OCI compatible (e.g., "aarch64" -> "arm64"). - options.OS, options.Architecture, options.Variant = NormalizePlatform(options.OS, options.Architecture, options.Variant) + options.OS, options.Architecture, options.Variant = platform.Normalize(options.OS, options.Architecture, options.Variant) // Second, try out the candidates as resolved by shortnames. This takes // "localhost/" prefixed images into account as well. @@ -435,9 +440,9 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, namedCandida return nil, nil } switch options.PlatformPolicy { - case PlatformPolicyDefault: + case define.PlatformPolicyDefault: logrus.Debugf("%v", matchError) - case PlatformPolicyWarn: + case define.PlatformPolicyWarn: logrus.Warnf("%v", matchError) } } @@ -454,28 +459,20 @@ func (r *Runtime) lookupImageInDigestsAndRepoTags(name string, possiblyUnqualifi if possiblyUnqualifiedNamedReference == nil { return nil, "", fmt.Errorf("%s: %w", originalName, storage.ErrImageUnknown) } - - // In case of a digested reference, we strip off the digest and require - // any image matching the repo/tag to also match the specified digest. - var requiredDigest digest.Digest - digested, isDigested := possiblyUnqualifiedNamedReference.(reference.Digested) - if isDigested { - requiredDigest = digested.Digest() - possiblyUnqualifiedNamedReference = reference.TrimNamed(possiblyUnqualifiedNamedReference) - name = possiblyUnqualifiedNamedReference.String() - } - if !shortnames.IsShortName(name) { return nil, "", fmt.Errorf("%s: %w", originalName, storage.ErrImageUnknown) } - // Docker compat: make sure to add the "latest" tag if needed. The tag - // will be ignored if we're looking for a digest match. - possiblyUnqualifiedNamedReference = reference.TagNameOnly(possiblyUnqualifiedNamedReference) - namedTagged, isNamedTagged := possiblyUnqualifiedNamedReference.(reference.NamedTagged) - if !isNamedTagged { - // NOTE: this should never happen since we already stripped off - // the digest. + var requiredDigest digest.Digest // or "" + var requiredTag string // or "" + + possiblyUnqualifiedNamedReference = reference.TagNameOnly(possiblyUnqualifiedNamedReference) // Docker compat: make sure to add the "latest" tag if needed. + if digested, ok := possiblyUnqualifiedNamedReference.(reference.Digested); ok { + requiredDigest = digested.Digest() + name = reference.TrimNamed(possiblyUnqualifiedNamedReference).String() + } else if namedTagged, ok := possiblyUnqualifiedNamedReference.(reference.NamedTagged); ok { + requiredTag = namedTagged.Tag() + } else { // This should never happen after the reference.TagNameOnly above. return nil, "", fmt.Errorf("%s: %w (could not cast to tagged)", originalName, storage.ErrImageUnknown) } @@ -485,7 +482,7 @@ func (r *Runtime) lookupImageInDigestsAndRepoTags(name string, possiblyUnqualifi } for _, image := range allImages { - named, err := image.inRepoTags(namedTagged, isDigested) + named, err := image.referenceFuzzilyMatchingRepoAndTag(possiblyUnqualifiedNamedReference, requiredTag) if err != nil { return nil, "", err } @@ -497,8 +494,8 @@ func (r *Runtime) lookupImageInDigestsAndRepoTags(name string, possiblyUnqualifi return nil, "", err } if img != nil { - if isDigested { - if !img.hasDigest(requiredDigest.String()) { + if requiredDigest != "" { + if !img.hasDigest(requiredDigest) { continue } named = reference.TrimNamed(named) diff --git a/vendor/github.com/containers/common/libimage/save.go b/vendor/github.com/containers/common/libimage/save.go index a42bbb4973e..47a3a566bd8 100644 --- a/vendor/github.com/containers/common/libimage/save.go +++ b/vendor/github.com/containers/common/libimage/save.go @@ -1,3 +1,6 @@ +//go:build !remote +// +build !remote + package libimage import ( diff --git a/vendor/github.com/containers/common/libimage/search.go b/vendor/github.com/containers/common/libimage/search.go index 132307d13ba..9ef0e8320f5 100644 --- a/vendor/github.com/containers/common/libimage/search.go +++ b/vendor/github.com/containers/common/libimage/search.go @@ -1,13 +1,15 @@ +//go:build !remote +// +build !remote + package libimage import ( "context" "fmt" - "strconv" "strings" "sync" - "github.com/containers/common/libimage/define" + "github.com/containers/common/libimage/filter" registryTransport "github.com/containers/image/v5/docker" "github.com/containers/image/v5/pkg/sysregistriesv2" "github.com/containers/image/v5/transports/alltransports" @@ -46,7 +48,7 @@ type SearchResult struct { // SearchOptions customize searching images. type SearchOptions struct { // Filter allows to filter the results. - Filter SearchFilter + Filter filter.SearchFilter // Limit limits the number of queries per index (default: 25). Must be // greater than 0 to overwrite the default value. Limit int @@ -77,51 +79,6 @@ type SearchOptions struct { Registries []string } -// SearchFilter allows filtering images while searching. -type SearchFilter struct { - // Stars describes the minimal amount of starts of an image. - Stars int - // IsAutomated decides if only images from automated builds are displayed. - IsAutomated types.OptionalBool - // IsOfficial decides if only official images are displayed. - IsOfficial types.OptionalBool -} - -// ParseSearchFilter turns the filter into a SearchFilter that can be used for -// searching images. -func ParseSearchFilter(filter []string) (*SearchFilter, error) { - sFilter := new(SearchFilter) - for _, f := range filter { - arr := strings.SplitN(f, "=", 2) - switch arr[0] { - case define.SearchFilterStars: - if len(arr) < 2 { - return nil, fmt.Errorf("invalid filter %q, should be stars=", filter) - } - stars, err := strconv.Atoi(arr[1]) - if err != nil { - return nil, fmt.Errorf("incorrect value type for stars filter: %w", err) - } - sFilter.Stars = stars - case define.SearchFilterAutomated: - if len(arr) == 2 && arr[1] == "false" { - sFilter.IsAutomated = types.OptionalBoolFalse - } else { - sFilter.IsAutomated = types.OptionalBoolTrue - } - case define.SearchFilterOfficial: - if len(arr) == 2 && arr[1] == "false" { - sFilter.IsOfficial = types.OptionalBoolFalse - } else { - sFilter.IsOfficial = types.OptionalBoolTrue - } - default: - return nil, fmt.Errorf("invalid filter type %q", f) - } - } - return sFilter, nil -} - // Search searches term. If term includes a registry, only this registry will // be used for searching. Otherwise, the unqualified-search registries in // containers-registries.conf(5) or the ones specified in the options will be @@ -261,7 +218,7 @@ func (r *Runtime) searchImageInRegistry(ctx context.Context, term, registry stri paramsArr := []SearchResult{} for i := 0; i < limit; i++ { // Check whether query matches filters - if !(options.Filter.matchesAutomatedFilter(results[i]) && options.Filter.matchesOfficialFilter(results[i]) && options.Filter.matchesStarFilter(results[i])) { + if !(filterMatchesAutomatedFilter(&options.Filter, results[i]) && filterMatchesOfficialFilter(&options.Filter, results[i]) && filterMatchesStarFilter(&options.Filter, results[i])) { continue } official := "" @@ -330,18 +287,18 @@ func searchRepositoryTags(ctx context.Context, sys *types.SystemContext, registr return paramsArr, nil } -func (f *SearchFilter) matchesStarFilter(result registryTransport.SearchResult) bool { +func filterMatchesStarFilter(f *filter.SearchFilter, result registryTransport.SearchResult) bool { return result.StarCount >= f.Stars } -func (f *SearchFilter) matchesAutomatedFilter(result registryTransport.SearchResult) bool { +func filterMatchesAutomatedFilter(f *filter.SearchFilter, result registryTransport.SearchResult) bool { if f.IsAutomated != types.OptionalBoolUndefined { return result.IsAutomated == (f.IsAutomated == types.OptionalBoolTrue) } return true } -func (f *SearchFilter) matchesOfficialFilter(result registryTransport.SearchResult) bool { +func filterMatchesOfficialFilter(f *filter.SearchFilter, result registryTransport.SearchResult) bool { if f.IsOfficial != types.OptionalBoolUndefined { return result.IsOfficial == (f.IsOfficial == types.OptionalBoolTrue) } diff --git a/vendor/github.com/containers/common/libnetwork/cni/network.go b/vendor/github.com/containers/common/libnetwork/cni/network.go index 8180b49b2d1..49d20b915d0 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/network.go +++ b/vendor/github.com/containers/common/libnetwork/cni/network.go @@ -9,6 +9,7 @@ import ( "encoding/hex" "errors" "fmt" + "io/fs" "os" "path/filepath" "strings" @@ -17,7 +18,7 @@ import ( "github.com/containernetworking/cni/libcni" "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/config" - cutil "github.com/containers/common/pkg/util" + "github.com/containers/common/pkg/version" "github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/unshare" "github.com/sirupsen/logrus" @@ -201,7 +202,10 @@ func (n *cniNetwork) loadNetworks() error { net, err := createNetworkFromCNIConfigList(conf, file) if err != nil { - logrus.Errorf("CNI config list %s could not be converted to a libpod config, skipping: %v", file, err) + // ignore ENOENT as the config has been removed in the meantime so we can just ignore this case + if !errors.Is(err, fs.ErrNotExist) { + logrus.Errorf("CNI config list %s could not be converted to a libpod config, skipping: %v", file, err) + } continue } logrus.Debugf("Successfully loaded network %s: %v", net.Name, net) @@ -302,8 +306,8 @@ func (n *cniNetwork) NetworkInfo() types.NetworkInfo { path := "" packageVersion := "" for _, p := range n.cniPluginDirs { - ver := cutil.PackageVersion(p) - if ver != cutil.UnknownPackage { + ver := version.Package(p) + if ver != version.UnknownPackage { path = p packageVersion = ver break @@ -317,8 +321,8 @@ func (n *cniNetwork) NetworkInfo() types.NetworkInfo { } dnsPath := filepath.Join(path, "dnsname") - dnsPackage := cutil.PackageVersion(dnsPath) - dnsProgram, err := cutil.ProgramVersionDnsname(dnsPath) + dnsPackage := version.Package(dnsPath) + dnsProgram, err := version.ProgramDnsname(dnsPath) if err != nil { logrus.Infof("Failed to get the dnsname plugin version: %v", err) } diff --git a/vendor/github.com/containers/common/libnetwork/cni/run_freebsd.go b/vendor/github.com/containers/common/libnetwork/cni/run_freebsd.go index c356a864a7f..cca00aa83fc 100644 --- a/vendor/github.com/containers/common/libnetwork/cni/run_freebsd.go +++ b/vendor/github.com/containers/common/libnetwork/cni/run_freebsd.go @@ -8,6 +8,12 @@ import ( // add the default address. Note: this will also add ::1 as a side // effect. func setupLoopback(namespacePath string) error { - // The jexec wrapper runs the ifconfig command inside the jail. + // Try to run the command using ifconfig's -j flag (supported in 13.3 and later) + if err := exec.Command("ifconfig", "-j", namespacePath, "lo0", "inet", "127.0.0.1").Run(); err == nil { + return nil + } + + // Fall back to using the jexec wrapper to run the ifconfig command + // inside the jail. return exec.Command("jexec", namespacePath, "ifconfig", "lo0", "inet", "127.0.0.1").Run() } diff --git a/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go b/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go index 408922c5e9a..ed65921cedb 100644 --- a/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go +++ b/vendor/github.com/containers/common/libnetwork/etchosts/hosts.go @@ -14,7 +14,9 @@ import ( const ( HostContainersInternal = "host.containers.internal" + HostGateway = "host-gateway" localhost = "localhost" + hostDockerInternal = "host.docker.internal" ) type HostEntries []HostEntry @@ -98,7 +100,7 @@ func Remove(file string, entries HostEntries) error { // new see comment on New() func newHost(params *Params) error { - entries, err := parseExtraHosts(params.ExtraHosts) + entries, err := parseExtraHosts(params.ExtraHosts, params.HostContainersInternalIP) if err != nil { return err } @@ -118,7 +120,7 @@ func newHost(params *Params) error { l2 := HostEntry{IP: "::1", Names: lh} containerIPs = append(containerIPs, l1, l2) if params.HostContainersInternalIP != "" { - e := HostEntry{IP: params.HostContainersInternalIP, Names: []string{HostContainersInternal}} + e := HostEntry{IP: params.HostContainersInternalIP, Names: []string{HostContainersInternal, hostDockerInternal}} containerIPs = append(containerIPs, e) } containerIPs = append(containerIPs, params.ContainerIPs...) @@ -230,7 +232,7 @@ func checkIfEntryExists(current HostEntry, entries HostEntries) bool { // parseExtraHosts converts a slice of "name:ip" string to entries. // Because podman and buildah both store the extra hosts in this format // we convert it here instead of having to this on the caller side. -func parseExtraHosts(extraHosts []string) (HostEntries, error) { +func parseExtraHosts(extraHosts []string, hostContainersInternalIP string) (HostEntries, error) { entries := make(HostEntries, 0, len(extraHosts)) for _, entry := range extraHosts { values := strings.SplitN(entry, ":", 2) @@ -243,7 +245,14 @@ func parseExtraHosts(extraHosts []string) (HostEntries, error) { if values[1] == "" { return nil, fmt.Errorf("IP address in host entry %q is empty", entry) } - e := HostEntry{IP: values[1], Names: []string{values[0]}} + ip := values[1] + if values[1] == HostGateway { + if hostContainersInternalIP == "" { + return nil, fmt.Errorf("unable to replace %q of host entry %q: host containers internal IP address is empty", HostGateway, entry) + } + ip = hostContainersInternalIP + } + e := HostEntry{IP: ip, Names: []string{values[0]}} entries = append(entries, e) } return entries, nil diff --git a/vendor/github.com/containers/common/libnetwork/internal/util/util.go b/vendor/github.com/containers/common/libnetwork/internal/util/util.go index 545e7a59bca..2ab24c56358 100644 --- a/vendor/github.com/containers/common/libnetwork/internal/util/util.go +++ b/vendor/github.com/containers/common/libnetwork/internal/util/util.go @@ -28,9 +28,7 @@ func GetBridgeInterfaceNames(n NetUtil) []string { func GetUsedNetworkNames(n NetUtil) []string { names := make([]string, 0, n.Len()) n.ForEach(func(net types.Network) { - if net.Driver == types.BridgeNetworkDriver { - names = append(names, net.NetworkInterface) - } + names = append(names, net.Name) }) return names } diff --git a/vendor/github.com/containers/common/libnetwork/netavark/config.go b/vendor/github.com/containers/common/libnetwork/netavark/config.go index 45b49bf22b7..de7af9575cc 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/config.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/config.go @@ -204,7 +204,10 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo } // rust only support "true" or "false" while go can parse 1 and 0 as well so we need to change it newNetwork.Options[types.NoDefaultRoute] = strconv.FormatBool(val) - + case types.VRFOption: + if len(value) == 0 { + return nil, errors.New("invalid vrf name") + } default: return nil, fmt.Errorf("unsupported bridge network option %s", key) } diff --git a/vendor/github.com/containers/common/libnetwork/netavark/exec.go b/vendor/github.com/containers/common/libnetwork/netavark/exec.go index 000d39051f2..20934a3f9ab 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/exec.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/exec.go @@ -23,7 +23,7 @@ type netavarkError struct { func (e *netavarkError) Error() string { ec := "" - // only add the exit code the the error message if we have at least info log level + // only add the exit code the error message if we have at least info log level // the normal user does not need to care about the number if e.exitCode > 0 && logrus.IsLevelEnabled(logrus.InfoLevel) { ec = " (exit code " + strconv.Itoa(e.exitCode) + ")" diff --git a/vendor/github.com/containers/common/libnetwork/netavark/ipam.go b/vendor/github.com/containers/common/libnetwork/netavark/ipam.go index d611dc60fe1..65f21c1e3b0 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/ipam.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/ipam.go @@ -65,7 +65,7 @@ func (n *netavarkNetwork) openDB() (*bbolt.DB, error) { return db, nil } -// allocIPs will allocate ips for the the container. It will change the +// allocIPs will allocate ips for the container. It will change the // NetworkOptions in place. When static ips are given it will validate // that these are free to use and will allocate them to the container. func (n *netavarkNetwork) allocIPs(opts *types.NetworkOptions) error { diff --git a/vendor/github.com/containers/common/libnetwork/netavark/network.go b/vendor/github.com/containers/common/libnetwork/netavark/network.go index cadf5e71896..0d323db28b1 100644 --- a/vendor/github.com/containers/common/libnetwork/netavark/network.go +++ b/vendor/github.com/containers/common/libnetwork/netavark/network.go @@ -15,7 +15,7 @@ import ( "github.com/containers/common/libnetwork/internal/util" "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/config" - cutil "github.com/containers/common/pkg/util" + "github.com/containers/common/pkg/version" "github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/unshare" "github.com/sirupsen/logrus" @@ -44,7 +44,7 @@ type netavarkNetwork struct { // defaultsubnetPools contains the subnets which must be used to allocate a free subnet by network create defaultsubnetPools []config.SubnetPool - // dnsBindPort is set the the port to pass to netavark for aardvark + // dnsBindPort is set the port to pass to netavark for aardvark dnsBindPort uint16 // pluginDirs list of directories were netavark plugins are located @@ -53,7 +53,7 @@ type netavarkNetwork struct { // ipamDBPath is the path to the ip allocation bolt db ipamDBPath string - // syslog describes whenever the netavark debbug output should be log to the syslog as well. + // syslog describes whenever the netavark debug output should be log to the syslog as well. // This will use logrus to do so, make sure logrus is set up to log to the syslog. syslog bool @@ -87,13 +87,13 @@ type InitConfig struct { // DefaultsubnetPools contains the subnets which must be used to allocate a free subnet by network create DefaultsubnetPools []config.SubnetPool - // DNSBindPort is set the the port to pass to netavark for aardvark + // DNSBindPort is set the port to pass to netavark for aardvark DNSBindPort uint16 // PluginDirs list of directories were netavark plugins are located PluginDirs []string - // Syslog describes whenever the netavark debbug output should be log to the syslog as well. + // Syslog describes whenever the netavark debug output should be log to the syslog as well. // This will use logrus to do so, make sure logrus is set up to log to the syslog. Syslog bool } @@ -341,8 +341,8 @@ func (n *netavarkNetwork) DefaultInterfaceName() string { // package version and program version. func (n *netavarkNetwork) NetworkInfo() types.NetworkInfo { path := n.netavarkBinary - packageVersion := cutil.PackageVersion(path) - programVersion, err := cutil.ProgramVersion(path) + packageVersion := version.Package(path) + programVersion, err := version.Program(path) if err != nil { logrus.Infof("Failed to get the netavark version: %v", err) } @@ -354,8 +354,8 @@ func (n *netavarkNetwork) NetworkInfo() types.NetworkInfo { } dnsPath := n.aardvarkBinary - dnsPackage := cutil.PackageVersion(dnsPath) - dnsProgram, err := cutil.ProgramVersion(dnsPath) + dnsPackage := version.Package(dnsPath) + dnsProgram, err := version.Program(dnsPath) if err != nil { logrus.Infof("Failed to get the aardvark version: %v", err) } diff --git a/vendor/github.com/containers/common/libnetwork/network/interface.go b/vendor/github.com/containers/common/libnetwork/network/interface.go index 775df1b67f2..aeac8d9c15b 100644 --- a/vendor/github.com/containers/common/libnetwork/network/interface.go +++ b/vendor/github.com/containers/common/libnetwork/network/interface.go @@ -35,7 +35,7 @@ const ( // NetworkBackend returns the network backend name and interface // It returns either the CNI or netavark backend depending on what is set in the config. -// If the the backend is set to "" we will automatically assign the backend on the following conditions: +// If the backend is set to "" we will automatically assign the backend on the following conditions: // 1. read ${graphroot}/defaultNetworkBackend // 2. find netavark binary (if not installed use CNI) // 3. check containers, images and CNI networks and if there are some we have an existing install and should continue to use CNI @@ -81,7 +81,7 @@ func NetworkBackend(store storage.Store, conf *config.Config, syslog bool) (type NetworkRunDir: runDir, NetavarkBinary: netavarkBin, AardvarkBinary: aardvarkBin, - PluginDirs: conf.Network.NetavarkPluginDirs, + PluginDirs: conf.Network.NetavarkPluginDirs.Get(), DefaultNetwork: conf.Network.DefaultNetwork, DefaultSubnet: conf.Network.DefaultSubnet, DefaultsubnetPools: conf.Network.DefaultSubnetPools, @@ -181,7 +181,7 @@ func getCniInterface(conf *config.Config) (types.ContainerNetwork, error) { } return cni.NewCNINetworkInterface(&cni.InitConfig{ CNIConfigDir: confDir, - CNIPluginDirs: conf.Network.CNIPluginDirs, + CNIPluginDirs: conf.Network.CNIPluginDirs.Get(), RunDir: conf.Engine.TmpDir, DefaultNetwork: conf.Network.DefaultNetwork, DefaultSubnet: conf.Network.DefaultSubnet, diff --git a/vendor/github.com/containers/common/libnetwork/pasta/pasta.go b/vendor/github.com/containers/common/libnetwork/pasta/pasta.go index 6a53afe3d4a..b787a7814c2 100644 --- a/vendor/github.com/containers/common/libnetwork/pasta/pasta.go +++ b/vendor/github.com/containers/common/libnetwork/pasta/pasta.go @@ -84,7 +84,7 @@ func Setup(opts *SetupOptions) error { } // first append options set in the config - cmdArgs = append(cmdArgs, opts.Config.Network.PastaOptions...) + cmdArgs = append(cmdArgs, opts.Config.Network.PastaOptions.Get()...) // then append the ones that were set on the cli cmdArgs = append(cmdArgs, opts.ExtraOptions...) diff --git a/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go b/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go index 0e53a922f64..43ca97808d6 100644 --- a/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go +++ b/vendor/github.com/containers/common/libnetwork/slirp4netns/slirp4netns.go @@ -124,8 +124,8 @@ func checkSlirpFlags(path string) (*slirpFeatures, error) { } func parseNetworkOptions(config *config.Config, extraOptions []string) (*networkOptions, error) { - options := make([]string, 0, len(config.Engine.NetworkCmdOptions)+len(extraOptions)) - options = append(options, config.Engine.NetworkCmdOptions...) + options := make([]string, 0, len(config.Engine.NetworkCmdOptions.Get())+len(extraOptions)) + options = append(options, config.Engine.NetworkCmdOptions.Get()...) options = append(options, extraOptions...) opts := &networkOptions{ // overwrite defaults diff --git a/vendor/github.com/containers/common/libnetwork/types/const.go b/vendor/github.com/containers/common/libnetwork/types/const.go index 83103ef6ef5..a9161820077 100644 --- a/vendor/github.com/containers/common/libnetwork/types/const.go +++ b/vendor/github.com/containers/common/libnetwork/types/const.go @@ -43,6 +43,7 @@ const ( MetricOption = "metric" NoDefaultRoute = "no_default_route" BclimOption = "bclim" + VRFOption = "vrf" ) type NetworkBackend string diff --git a/vendor/github.com/containers/common/libnetwork/util/filters.go b/vendor/github.com/containers/common/libnetwork/util/filters.go index 782c5d2b9ed..70f90918c7f 100644 --- a/vendor/github.com/containers/common/libnetwork/util/filters.go +++ b/vendor/github.com/containers/common/libnetwork/util/filters.go @@ -38,7 +38,7 @@ func createFilterFuncs(key string, filterValues []string) (types.FilterFunc, err case "id": // matches part of one id return func(net types.Network) bool { - return util.FilterID(net.ID, filterValues) + return filters.FilterID(net.ID, filterValues) }, nil // TODO: add dns enabled, internal filter @@ -67,7 +67,7 @@ func createPruneFilterFuncs(key string, filterValues []string) (types.FilterFunc }, nil case "label!": return func(net types.Network) bool { - return !filters.MatchLabelFilters(filterValues, net.Labels) + return filters.MatchNegatedLabelFilters(filterValues, net.Labels) }, nil case "until": until, err := filters.ComputeUntilTimestamp(filterValues) diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go index 7ba63ba7447..435422c27de 100644 --- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go +++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go @@ -212,6 +212,11 @@ func parseAAParserVersion(output string) (int, error) { words := strings.Split(lines[0], " ") version := words[len(words)-1] + // trim "-beta1" suffix from version="3.0.0-beta1" if exists + version = strings.SplitN(version, "-", 2)[0] + // also trim "~..." suffix used historically (https://gitlab.com/apparmor/apparmor/-/commit/bca67d3d27d219d11ce8c9cc70612bd637f88c10) + version = strings.SplitN(version, "~", 2)[0] + // split by major minor version v := strings.Split(version, ".") if len(v) == 0 || len(v) > 3 { diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go index 667fa9f2655..99e0e14e23f 100644 --- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go +++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go @@ -43,7 +43,7 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) { deny /sys/kernel/security/** rwklx, {{if ge .Version 208095}} - # suppress ptrace denials when using using 'ps' inside a container + # suppress ptrace denials when using 'ps' inside a container ptrace (trace,read) peer={{.Name}}, {{end}} } diff --git a/vendor/github.com/containers/common/pkg/cgroups/blkio.go b/vendor/github.com/containers/common/pkg/cgroups/blkio.go deleted file mode 100644 index e157e6faf50..00000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/blkio.go +++ /dev/null @@ -1,151 +0,0 @@ -//go:build !linux -// +build !linux - -package cgroups - -import ( - "bufio" - "errors" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - - spec "github.com/opencontainers/runtime-spec/specs-go" -) - -type blkioHandler struct{} - -func getBlkioHandler() *blkioHandler { - return &blkioHandler{} -} - -// Apply set the specified constraints -func (c *blkioHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { - if res.BlockIO == nil { - return nil - } - return fmt.Errorf("blkio apply function not implemented yet") -} - -// Create the cgroup -func (c *blkioHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(Blkio) -} - -// Destroy the cgroup -func (c *blkioHandler) Destroy(ctr *CgroupControl) error { - return rmDirRecursively(ctr.getCgroupv1Path(Blkio)) -} - -// Stat fills a metrics structure with usage stats for the controller -func (c *blkioHandler) Stat(ctr *CgroupControl, m *Metrics) error { - var ioServiceBytesRecursive []BlkIOEntry - - if ctr.cgroup2 { - // more details on the io.stat file format:X https://facebookmicrosites.github.io/cgroup2/docs/io-controller.html - values, err := readCgroup2MapFile(ctr, "io.stat") - if err != nil { - return err - } - for k, v := range values { - d := strings.Split(k, ":") - if len(d) != 2 { - continue - } - minor, err := strconv.ParseUint(d[0], 10, 0) - if err != nil { - return err - } - major, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err - } - - for _, item := range v { - d := strings.Split(item, "=") - if len(d) != 2 { - continue - } - op := d[0] - - // Accommodate the cgroup v1 naming - switch op { - case "rbytes": - op = "read" - case "wbytes": - op = "write" - } - - value, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err - } - - entry := BlkIOEntry{ - Op: op, - Major: major, - Minor: minor, - Value: value, - } - ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry) - } - } - } else { - BlkioRoot := ctr.getCgroupv1Path(Blkio) - - p := filepath.Join(BlkioRoot, "blkio.throttle.io_service_bytes_recursive") - f, err := os.Open(p) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return nil - } - return fmt.Errorf("open %s: %w", p, err) - } - defer f.Close() - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - parts := strings.Fields(line) - if len(parts) < 3 { - continue - } - d := strings.Split(parts[0], ":") - if len(d) != 2 { - continue - } - minor, err := strconv.ParseUint(d[0], 10, 0) - if err != nil { - return err - } - major, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err - } - - op := parts[1] - - value, err := strconv.ParseUint(parts[2], 10, 0) - if err != nil { - return err - } - entry := BlkIOEntry{ - Op: op, - Major: major, - Minor: minor, - Value: value, - } - ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry) - } - if err := scanner.Err(); err != nil { - return fmt.Errorf("parse %s: %w", p, err) - } - } - m.Blkio = BlkioMetrics{IoServiceBytesRecursive: ioServiceBytesRecursive} - return nil -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/blkio_linux.go b/vendor/github.com/containers/common/pkg/cgroups/blkio_linux.go index ced461e6935..dd18ed56585 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/blkio_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/blkio_linux.go @@ -34,7 +34,6 @@ func (c *linuxBlkioHandler) Apply(ctr *CgroupControl, res *configs.Resources) er return err } return man.Set(res) - } path := filepath.Join(cgroupRoot, Blkio, ctr.config.Path) return c.Blkio.Set(path, res) diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups.go deleted file mode 100644 index 73dc36ee404..00000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups.go +++ /dev/null @@ -1,614 +0,0 @@ -//go:build !linux -// +build !linux - -package cgroups - -import ( - "bufio" - "context" - "errors" - "fmt" - "math" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/containers/storage/pkg/unshare" - systemdDbus "github.com/coreos/go-systemd/v22/dbus" - "github.com/godbus/dbus/v5" - spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" -) - -var ( - // ErrCgroupDeleted means the cgroup was deleted - ErrCgroupDeleted = errors.New("cgroup deleted") - // ErrCgroupV1Rootless means the cgroup v1 were attempted to be used in rootless environment - ErrCgroupV1Rootless = errors.New("no support for CGroups V1 in rootless environments") - ErrStatCgroup = errors.New("no cgroup available for gathering user statistics") -) - -// CgroupControl controls a cgroup hierarchy -type CgroupControl struct { - cgroup2 bool - path string - systemd bool - // List of additional cgroup subsystems joined that - // do not have a custom handler. - additionalControllers []controller -} - -// CPUUsage keeps stats for the CPU usage (unit: nanoseconds) -type CPUUsage struct { - Kernel uint64 - Total uint64 - PerCPU []uint64 -} - -// MemoryUsage keeps stats for the memory usage -type MemoryUsage struct { - Usage uint64 - Limit uint64 -} - -// CPUMetrics keeps stats for the CPU usage -type CPUMetrics struct { - Usage CPUUsage -} - -// BlkIOEntry describes an entry in the blkio stats -type BlkIOEntry struct { - Op string - Major uint64 - Minor uint64 - Value uint64 -} - -// BlkioMetrics keeps usage stats for the blkio cgroup controller -type BlkioMetrics struct { - IoServiceBytesRecursive []BlkIOEntry -} - -// MemoryMetrics keeps usage stats for the memory cgroup controller -type MemoryMetrics struct { - Usage MemoryUsage -} - -// PidsMetrics keeps usage stats for the pids cgroup controller -type PidsMetrics struct { - Current uint64 -} - -// Metrics keeps usage stats for the cgroup controllers -type Metrics struct { - CPU CPUMetrics - Blkio BlkioMetrics - Memory MemoryMetrics - Pids PidsMetrics -} - -type controller struct { - name string - symlink bool -} - -type controllerHandler interface { - Create(*CgroupControl) (bool, error) - Apply(*CgroupControl, *spec.LinuxResources) error - Destroy(*CgroupControl) error - Stat(*CgroupControl, *Metrics) error -} - -const ( - cgroupRoot = "/sys/fs/cgroup" - // CPU is the cpu controller - CPU = "cpu" - // CPUAcct is the cpuacct controller - CPUAcct = "cpuacct" - // CPUset is the cpuset controller - CPUset = "cpuset" - // Memory is the memory controller - Memory = "memory" - // Pids is the pids controller - Pids = "pids" - // Blkio is the blkio controller - Blkio = "blkio" -) - -var handlers map[string]controllerHandler - -func init() { - handlers = make(map[string]controllerHandler) - handlers[CPU] = getCPUHandler() - handlers[CPUset] = getCpusetHandler() - handlers[Memory] = getMemoryHandler() - handlers[Pids] = getPidsHandler() - handlers[Blkio] = getBlkioHandler() -} - -// getAvailableControllers get the available controllers -func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]controller, error) { - if cgroup2 { - controllers := []controller{} - controllersFile := cgroupRoot + "/cgroup.controllers" - // rootless cgroupv2: check available controllers for current user, systemd or servicescope will inherit - if unshare.IsRootless() { - userSlice, err := getCgroupPathForCurrentProcess() - if err != nil { - return controllers, err - } - // userSlice already contains '/' so not adding here - basePath := cgroupRoot + userSlice - controllersFile = fmt.Sprintf("%s/cgroup.controllers", basePath) - } - controllersFileBytes, err := os.ReadFile(controllersFile) - if err != nil { - return nil, fmt.Errorf("failed while reading controllers for cgroup v2: %w", err) - } - for _, controllerName := range strings.Fields(string(controllersFileBytes)) { - c := controller{ - name: controllerName, - symlink: false, - } - controllers = append(controllers, c) - } - return controllers, nil - } - - subsystems, _ := cgroupV1GetAllSubsystems() - controllers := []controller{} - // cgroupv1 and rootless: No subsystem is available: delegation is unsafe. - if unshare.IsRootless() { - return controllers, nil - } - - for _, name := range subsystems { - if _, found := exclude[name]; found { - continue - } - fileInfo, err := os.Stat(cgroupRoot + "/" + name) - if err != nil { - continue - } - c := controller{ - name: name, - symlink: !fileInfo.IsDir(), - } - controllers = append(controllers, c) - } - - return controllers, nil -} - -// GetAvailableControllers get string:bool map of all the available controllers -func GetAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]string, error) { - availableControllers, err := getAvailableControllers(exclude, cgroup2) - if err != nil { - return nil, err - } - controllerList := []string{} - for _, controller := range availableControllers { - controllerList = append(controllerList, controller.name) - } - - return controllerList, nil -} - -func cgroupV1GetAllSubsystems() ([]string, error) { - f, err := os.Open("/proc/cgroups") - if err != nil { - return nil, err - } - defer f.Close() - - subsystems := []string{} - - s := bufio.NewScanner(f) - for s.Scan() { - text := s.Text() - if text[0] != '#' { - parts := strings.Fields(text) - if len(parts) >= 4 && parts[3] != "0" { - subsystems = append(subsystems, parts[0]) - } - } - } - if err := s.Err(); err != nil { - return nil, err - } - return subsystems, nil -} - -func getCgroupPathForCurrentProcess() (string, error) { - path := fmt.Sprintf("/proc/%d/cgroup", os.Getpid()) - f, err := os.Open(path) - if err != nil { - return "", err - } - defer f.Close() - - cgroupPath := "" - s := bufio.NewScanner(f) - for s.Scan() { - text := s.Text() - procEntries := strings.SplitN(text, "::", 2) - // set process cgroupPath only if entry is valid - if len(procEntries) > 1 { - cgroupPath = procEntries[1] - } - } - if err := s.Err(); err != nil { - return cgroupPath, err - } - return cgroupPath, nil -} - -// getCgroupv1Path is a helper function to get the cgroup v1 path -func (c *CgroupControl) getCgroupv1Path(name string) string { - return filepath.Join(cgroupRoot, name, c.path) -} - -// initialize initializes the specified hierarchy -func (c *CgroupControl) initialize() (err error) { - createdSoFar := map[string]controllerHandler{} - defer func() { - if err != nil { - for name, ctr := range createdSoFar { - if err := ctr.Destroy(c); err != nil { - logrus.Warningf("error cleaning up controller %s for %s", name, c.path) - } - } - } - }() - if c.cgroup2 { - if err := createCgroupv2Path(filepath.Join(cgroupRoot, c.path)); err != nil { - return fmt.Errorf("creating cgroup path %s: %w", c.path, err) - } - } - for name, handler := range handlers { - created, err := handler.Create(c) - if err != nil { - return err - } - if created { - createdSoFar[name] = handler - } - } - - if !c.cgroup2 { - // We won't need to do this for cgroup v2 - for _, ctr := range c.additionalControllers { - if ctr.symlink { - continue - } - path := c.getCgroupv1Path(ctr.name) - if err := os.MkdirAll(path, 0o755); err != nil { - return fmt.Errorf("creating cgroup path for %s: %w", ctr.name, err) - } - } - } - - return nil -} - -func readFileAsUint64(path string) (uint64, error) { - data, err := os.ReadFile(path) - if err != nil { - return 0, err - } - v := cleanString(string(data)) - if v == "max" { - return math.MaxUint64, nil - } - ret, err := strconv.ParseUint(v, 10, 64) - if err != nil { - return ret, fmt.Errorf("parse %s from %s: %w", v, path, err) - } - return ret, nil -} - -func readFileByKeyAsUint64(path, key string) (uint64, error) { - content, err := os.ReadFile(path) - if err != nil { - return 0, err - } - for _, line := range strings.Split(string(content), "\n") { - fields := strings.SplitN(line, " ", 2) - if fields[0] == key { - v := cleanString(string(fields[1])) - if v == "max" { - return math.MaxUint64, nil - } - ret, err := strconv.ParseUint(v, 10, 64) - if err != nil { - return ret, fmt.Errorf("parse %s from %s: %w", v, path, err) - } - return ret, nil - } - } - - return 0, fmt.Errorf("no key named %s from %s", key, path) -} - -// New creates a new cgroup control -func New(path string, resources *spec.LinuxResources) (*CgroupControl, error) { - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } - control := &CgroupControl{ - cgroup2: cgroup2, - path: path, - } - - if !cgroup2 { - controllers, err := getAvailableControllers(handlers, false) - if err != nil { - return nil, err - } - control.additionalControllers = controllers - } - - if err := control.initialize(); err != nil { - return nil, err - } - - return control, nil -} - -// NewSystemd creates a new cgroup control -func NewSystemd(path string) (*CgroupControl, error) { - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } - control := &CgroupControl{ - cgroup2: cgroup2, - path: path, - systemd: true, - } - return control, nil -} - -// Load loads an existing cgroup control -func Load(path string) (*CgroupControl, error) { - cgroup2, err := IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } - control := &CgroupControl{ - cgroup2: cgroup2, - path: path, - systemd: false, - } - if !cgroup2 { - controllers, err := getAvailableControllers(handlers, false) - if err != nil { - return nil, err - } - control.additionalControllers = controllers - } - if !cgroup2 { - oneExists := false - // check that the cgroup exists at least under one controller - for name := range handlers { - p := control.getCgroupv1Path(name) - if _, err := os.Stat(p); err == nil { - oneExists = true - break - } - } - - // if there is no controller at all, raise an error - if !oneExists { - if unshare.IsRootless() { - return nil, ErrCgroupV1Rootless - } - // compatible with the error code - // used by containerd/cgroups - return nil, ErrCgroupDeleted - } - } - return control, nil -} - -// CreateSystemdUnit creates the systemd cgroup -func (c *CgroupControl) CreateSystemdUnit(path string) error { - if !c.systemd { - return fmt.Errorf("the cgroup controller is not using systemd") - } - - conn, err := systemdDbus.NewWithContext(context.TODO()) - if err != nil { - return err - } - defer conn.Close() - - return systemdCreate(path, conn) -} - -// GetUserConnection returns a user connection to D-BUS -func GetUserConnection(uid int) (*systemdDbus.Conn, error) { - return systemdDbus.NewConnection(func() (*dbus.Conn, error) { - return dbusAuthConnection(uid, dbus.SessionBusPrivateNoAutoStartup) - }) -} - -// CreateSystemdUserUnit creates the systemd cgroup for the specified user -func (c *CgroupControl) CreateSystemdUserUnit(path string, uid int) error { - if !c.systemd { - return fmt.Errorf("the cgroup controller is not using systemd") - } - - conn, err := GetUserConnection(uid) - if err != nil { - return err - } - defer conn.Close() - - return systemdCreate(path, conn) -} - -func dbusAuthConnection(uid int, createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) { - conn, err := createBus() - if err != nil { - return nil, err - } - - methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(uid))} - - err = conn.Auth(methods) - if err != nil { - conn.Close() - return nil, err - } - if err := conn.Hello(); err != nil { - return nil, err - } - - return conn, nil -} - -// Delete cleans a cgroup -func (c *CgroupControl) Delete() error { - return c.DeleteByPath(c.path) -} - -// DeleteByPathConn deletes the specified cgroup path using the specified -// dbus connection if needed. -func (c *CgroupControl) DeleteByPathConn(path string, conn *systemdDbus.Conn) error { - if c.systemd { - return systemdDestroyConn(path, conn) - } - if c.cgroup2 { - return rmDirRecursively(filepath.Join(cgroupRoot, c.path)) - } - var lastError error - for _, h := range handlers { - if err := h.Destroy(c); err != nil { - lastError = err - } - } - - for _, ctr := range c.additionalControllers { - if ctr.symlink { - continue - } - p := c.getCgroupv1Path(ctr.name) - if err := rmDirRecursively(p); err != nil { - lastError = fmt.Errorf("remove %s: %w", p, err) - } - } - return lastError -} - -// DeleteByPath deletes the specified cgroup path -func (c *CgroupControl) DeleteByPath(path string) error { - if c.systemd { - conn, err := systemdDbus.NewWithContext(context.TODO()) - if err != nil { - return err - } - defer conn.Close() - return c.DeleteByPathConn(path, conn) - } - return c.DeleteByPathConn(path, nil) -} - -// Update updates the cgroups -func (c *CgroupControl) Update(resources *spec.LinuxResources) error { - for _, h := range handlers { - if err := h.Apply(c, resources); err != nil { - return err - } - } - return nil -} - -// AddPid moves the specified pid to the cgroup -func (c *CgroupControl) AddPid(pid int) error { - pidString := []byte(fmt.Sprintf("%d\n", pid)) - - if c.cgroup2 { - p := filepath.Join(cgroupRoot, c.path, "cgroup.procs") - if err := os.WriteFile(p, pidString, 0o644); err != nil { - return fmt.Errorf("write %s: %w", p, err) - } - return nil - } - - names := make([]string, 0, len(handlers)) - for n := range handlers { - names = append(names, n) - } - - for _, c := range c.additionalControllers { - if !c.symlink { - names = append(names, c.name) - } - } - - for _, n := range names { - // If we aren't using cgroup2, we won't write correctly to unified hierarchy - if !c.cgroup2 && n == "unified" { - continue - } - p := filepath.Join(c.getCgroupv1Path(n), "tasks") - if err := os.WriteFile(p, pidString, 0o644); err != nil { - return fmt.Errorf("write %s: %w", p, err) - } - } - return nil -} - -// Stat returns usage statistics for the cgroup -func (c *CgroupControl) Stat() (*Metrics, error) { - m := Metrics{} - found := false - for _, h := range handlers { - if err := h.Stat(c, &m); err != nil { - if !errors.Is(err, os.ErrNotExist) { - return nil, err - } - logrus.Warningf("Failed to retrieve cgroup stats: %v", err) - continue - } - found = true - } - if !found { - return nil, ErrStatCgroup - } - return &m, nil -} - -func readCgroup2MapPath(path string) (map[string][]string, error) { - ret := map[string][]string{} - f, err := os.Open(path) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return ret, nil - } - return nil, fmt.Errorf("open file %s: %w", path, err) - } - defer f.Close() - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - parts := strings.Fields(line) - if len(parts) < 2 { - continue - } - ret[parts[0]] = parts[1:] - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("parsing file %s: %w", path, err) - } - return ret, nil -} - -func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, error) { - p := filepath.Join(cgroupRoot, ctr.path, name) - - return readCgroup2MapPath(p) -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go index 03d85750d1e..7605b5006ec 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go @@ -5,6 +5,7 @@ package cgroups import ( "bufio" + "bytes" "context" "errors" "fmt" @@ -134,8 +135,8 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) return controllers, nil } -// GetAvailableControllers get string:bool map of all the available controllers -func GetAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]string, error) { +// AvailableControllers get string:bool map of all the available controllers +func AvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]string, error) { availableControllers, err := getAvailableControllers(exclude, cgroup2) if err != nil { return nil, err @@ -269,7 +270,7 @@ func readFileByKeyAsUint64(path, key string) (uint64, error) { for _, line := range strings.Split(string(content), "\n") { fields := strings.SplitN(line, " ", 2) if fields[0] == key { - v := cleanString(string(fields[1])) + v := cleanString(fields[1]) if v == "max" { return math.MaxUint64, nil } @@ -391,20 +392,13 @@ func (c *CgroupControl) CreateSystemdUnit(path string) error { return systemdCreate(c.config.Resources, path, conn) } -// GetUserConnection returns an user connection to D-BUS -func GetUserConnection(uid int) (*systemdDbus.Conn, error) { - return systemdDbus.NewConnection(func() (*dbus.Conn, error) { - return dbusAuthConnection(uid, dbus.SessionBusPrivate) - }) -} - // CreateSystemdUserUnit creates the systemd cgroup for the specified user func (c *CgroupControl) CreateSystemdUserUnit(path string, uid int) error { if !c.systemd { return fmt.Errorf("the cgroup controller is not using systemd") } - conn, err := GetUserConnection(uid) + conn, err := UserConnection(uid) if err != nil { return err } @@ -542,7 +536,7 @@ func (c *CgroupControl) Stat() (*cgroups.Stats, error) { return &m, nil } -func readCgroup2MapPath(path string) (map[string][]string, error) { +func readCgroupMapPath(path string) (map[string][]string, error) { ret := map[string][]string{} f, err := os.Open(path) if err != nil { @@ -570,5 +564,172 @@ func readCgroup2MapPath(path string) (map[string][]string, error) { func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, error) { p := filepath.Join(cgroupRoot, ctr.config.Path, name) - return readCgroup2MapPath(p) + return readCgroupMapPath(p) +} + +func (c *CgroupControl) createCgroupDirectory(controller string) (bool, error) { + cPath := c.getCgroupv1Path(controller) + _, err := os.Stat(cPath) + if err == nil { + return false, nil + } + + if !errors.Is(err, os.ErrNotExist) { + return false, err + } + + if err := os.MkdirAll(cPath, 0o755); err != nil { + return false, fmt.Errorf("creating cgroup for %s: %w", controller, err) + } + return true, nil +} + +var TestMode bool + +func createCgroupv2Path(path string) (deferredError error) { + if !strings.HasPrefix(path, cgroupRoot+"/") { + return fmt.Errorf("invalid cgroup path %s", path) + } + content, err := os.ReadFile(cgroupRoot + "/cgroup.controllers") + if err != nil { + return err + } + ctrs := bytes.Fields(content) + res := append([]byte("+"), bytes.Join(ctrs, []byte(" +"))...) + + current := "/sys/fs" + elements := strings.Split(path, "/") + for i, e := range elements[3:] { + current = filepath.Join(current, e) + if i > 0 { + if err := os.Mkdir(current, 0o755); err != nil { + if !os.IsExist(err) { + return err + } + } else { + // If the directory was created, be sure it is not left around on errors. + defer func() { + if deferredError != nil { + os.Remove(current) + } + }() + } + } + // We enable the controllers for all the path components except the last one. It is not allowed to add + // PIDs if there are already enabled controllers. + if i < len(elements[3:])-1 { + if err := os.WriteFile(filepath.Join(current, "cgroup.subtree_control"), res, 0o755); err != nil { + return err + } + } + } + return nil +} + +func cleanString(s string) string { + return strings.Trim(s, "\n") +} + +func readAcct(ctr *CgroupControl, name string) (uint64, error) { + p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name) + return readFileAsUint64(p) +} + +func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) { + p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name) + data, err := os.ReadFile(p) + if err != nil { + return nil, err + } + r := []uint64{} + for _, s := range strings.Split(string(data), " ") { + s = cleanString(s) + if s == "" { + break + } + v, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return nil, fmt.Errorf("parsing %s: %w", s, err) + } + r = append(r, v) + } + return r, nil +} + +func cpusetCopyFromParent(path string, cgroupv2 bool) error { + for _, file := range []string{"cpuset.cpus", "cpuset.mems"} { + if _, err := cpusetCopyFileFromParent(path, file, cgroupv2); err != nil { + return err + } + } + return nil +} + +func cpusetCopyFileFromParent(dir, file string, cgroupv2 bool) ([]byte, error) { + if dir == cgroupRoot { + return nil, fmt.Errorf("could not find parent to initialize cpuset %s", file) + } + path := filepath.Join(dir, file) + parentPath := path + if cgroupv2 { + parentPath = fmt.Sprintf("%s.effective", parentPath) + } + data, err := os.ReadFile(parentPath) + if err != nil { + // if the file doesn't exist, it is likely that the cpuset controller + // is not enabled in the kernel. + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + if strings.Trim(string(data), "\n") != "" { + return data, nil + } + data, err = cpusetCopyFileFromParent(filepath.Dir(dir), file, cgroupv2) + if err != nil { + return nil, err + } + if err := os.WriteFile(path, data, 0o644); err != nil { + return nil, fmt.Errorf("write %s: %w", path, err) + } + return data, nil +} + +// SystemCPUUsage returns the system usage for all the cgroups +func SystemCPUUsage() (uint64, error) { + cgroupv2, err := IsCgroup2UnifiedMode() + if err != nil { + return 0, err + } + if !cgroupv2 { + p := filepath.Join(cgroupRoot, CPUAcct, "cpuacct.usage") + return readFileAsUint64(p) + } + + files, err := os.ReadDir(cgroupRoot) + if err != nil { + return 0, err + } + var total uint64 + for _, file := range files { + if !file.IsDir() { + continue + } + p := filepath.Join(cgroupRoot, file.Name(), "cpu.stat") + + values, err := readCgroupMapPath(p) + if err != nil { + return 0, err + } + + if val, found := values["usage_usec"]; found { + v, err := strconv.ParseUint(cleanString(val[0]), 10, 64) + if err != nil { + return 0, err + } + total += v * 1000 + } + } + return total, nil } diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go index 3a86122392a..5c0cac642f7 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_supported.go @@ -15,6 +15,8 @@ import ( "syscall" "time" + systemdDbus "github.com/coreos/go-systemd/v22/dbus" + "github.com/godbus/dbus/v5" "golang.org/x/sys/unix" ) @@ -37,6 +39,13 @@ func IsCgroup2UnifiedMode() (bool, error) { return isUnified, isUnifiedErr } +// UserConnection returns an user connection to D-BUS +func UserConnection(uid int) (*systemdDbus.Conn, error) { + return systemdDbus.NewConnection(func() (*dbus.Conn, error) { + return dbusAuthConnection(uid, dbus.SessionBusPrivateNoAutoStartup) + }) +} + // UserOwnsCurrentSystemdCgroup checks whether the current EUID owns the // current cgroup. func UserOwnsCurrentSystemdCgroup() (bool, error) { diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go index b3dcb2d33da..f2558728d18 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_unsupported.go @@ -4,7 +4,10 @@ package cgroups import ( + "fmt" "os" + + systemdDbus "github.com/coreos/go-systemd/v22/dbus" ) // IsCgroup2UnifiedMode returns whether we are running in cgroup 2 cgroup2 mode. @@ -21,3 +24,8 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) { func rmDirRecursively(path string) error { return os.RemoveAll(path) } + +// UserConnection returns an user connection to D-BUS +func UserConnection(uid int) (*systemdDbus.Conn, error) { + return nil, fmt.Errorf("systemd d-bus is not supported on this platform") +} diff --git a/vendor/github.com/containers/common/pkg/cgroups/cpu.go b/vendor/github.com/containers/common/pkg/cgroups/cpu.go deleted file mode 100644 index 16293e74c96..00000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/cpu.go +++ /dev/null @@ -1,91 +0,0 @@ -//go:build !linux -// +build !linux - -package cgroups - -import ( - "errors" - "fmt" - "os" - "strconv" - - spec "github.com/opencontainers/runtime-spec/specs-go" -) - -type cpuHandler struct{} - -func getCPUHandler() *cpuHandler { - return &cpuHandler{} -} - -// Apply set the specified constraints -func (c *cpuHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { - if res.CPU == nil { - return nil - } - return fmt.Errorf("cpu apply not implemented yet") -} - -// Create the cgroup -func (c *cpuHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(CPU) -} - -// Destroy the cgroup -func (c *cpuHandler) Destroy(ctr *CgroupControl) error { - return rmDirRecursively(ctr.getCgroupv1Path(CPU)) -} - -// Stat fills a metrics structure with usage stats for the controller -func (c *cpuHandler) Stat(ctr *CgroupControl, m *Metrics) error { - var err error - usage := CPUUsage{} - if ctr.cgroup2 { - values, err := readCgroup2MapFile(ctr, "cpu.stat") - if err != nil { - return err - } - if val, found := values["usage_usec"]; found { - usage.Total, err = strconv.ParseUint(cleanString(val[0]), 10, 64) - if err != nil { - return err - } - usage.Kernel *= 1000 - } - if val, found := values["system_usec"]; found { - usage.Kernel, err = strconv.ParseUint(cleanString(val[0]), 10, 64) - if err != nil { - return err - } - usage.Total *= 1000 - } - // FIXME: How to read usage.PerCPU? - } else { - usage.Total, err = readAcct(ctr, "cpuacct.usage") - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return err - } - usage.Total = 0 - } - usage.Kernel, err = readAcct(ctr, "cpuacct.usage_sys") - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return err - } - usage.Kernel = 0 - } - usage.PerCPU, err = readAcctList(ctr, "cpuacct.usage_percpu") - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return err - } - usage.PerCPU = nil - } - } - m.CPU = CPUMetrics{Usage: usage} - return nil -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/cpuset.go b/vendor/github.com/containers/common/pkg/cgroups/cpuset.go deleted file mode 100644 index f7ec9a33b04..00000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/cpuset.go +++ /dev/null @@ -1,49 +0,0 @@ -//go:build !linux -// +build !linux - -package cgroups - -import ( - "fmt" - "path/filepath" - - spec "github.com/opencontainers/runtime-spec/specs-go" -) - -type cpusetHandler struct{} - -func getCpusetHandler() *cpusetHandler { - return &cpusetHandler{} -} - -// Apply set the specified constraints -func (c *cpusetHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { - if res.CPU == nil { - return nil - } - return fmt.Errorf("cpuset apply not implemented yet") -} - -// Create the cgroup -func (c *cpusetHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - path := filepath.Join(cgroupRoot, ctr.path) - return true, cpusetCopyFromParent(path, true) - } - - created, err := ctr.createCgroupDirectory(CPUset) - if !created || err != nil { - return created, err - } - return true, cpusetCopyFromParent(ctr.getCgroupv1Path(CPUset), false) -} - -// Destroy the cgroup -func (c *cpusetHandler) Destroy(ctr *CgroupControl) error { - return rmDirRecursively(ctr.getCgroupv1Path(CPUset)) -} - -// Stat fills a metrics structure with usage stats for the controller -func (c *cpusetHandler) Stat(ctr *CgroupControl, m *Metrics) error { - return nil -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/memory.go b/vendor/github.com/containers/common/pkg/cgroups/memory.go deleted file mode 100644 index b597b85bf65..00000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/memory.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build !linux -// +build !linux - -package cgroups - -import ( - "fmt" - "path/filepath" - - spec "github.com/opencontainers/runtime-spec/specs-go" -) - -type memHandler struct{} - -func getMemoryHandler() *memHandler { - return &memHandler{} -} - -// Apply set the specified constraints -func (c *memHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { - if res.Memory == nil { - return nil - } - return fmt.Errorf("memory apply not implemented yet") -} - -// Create the cgroup -func (c *memHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(Memory) -} - -// Destroy the cgroup -func (c *memHandler) Destroy(ctr *CgroupControl) error { - return rmDirRecursively(ctr.getCgroupv1Path(Memory)) -} - -// Stat fills a metrics structure with usage stats for the controller -func (c *memHandler) Stat(ctr *CgroupControl, m *Metrics) error { - var err error - usage := MemoryUsage{} - - var memoryRoot string - var limitFilename string - - if ctr.cgroup2 { - memoryRoot = filepath.Join(cgroupRoot, ctr.path) - limitFilename = "memory.max" - if usage.Usage, err = readFileByKeyAsUint64(filepath.Join(memoryRoot, "memory.stat"), "anon"); err != nil { - return err - } - } else { - memoryRoot = ctr.getCgroupv1Path(Memory) - limitFilename = "memory.limit_in_bytes" - if usage.Usage, err = readFileAsUint64(filepath.Join(memoryRoot, "memory.usage_in_bytes")); err != nil { - return err - } - } - - usage.Limit, err = readFileAsUint64(filepath.Join(memoryRoot, limitFilename)) - if err != nil { - return err - } - - m.Memory = MemoryMetrics{Usage: usage} - return nil -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/memory_linux.go b/vendor/github.com/containers/common/pkg/cgroups/memory_linux.go index 5d2bf5d0e1c..3335cdffe5a 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/memory_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/memory_linux.go @@ -4,7 +4,9 @@ package cgroups import ( + "fmt" "path/filepath" + "strconv" "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups/fs" @@ -63,9 +65,26 @@ func (c *linuxMemHandler) Stat(ctr *CgroupControl, m *cgroups.Stats) error { } else { memoryRoot = ctr.getCgroupv1Path(Memory) limitFilename = "memory.limit_in_bytes" - if memUsage.Usage.Usage, err = readFileAsUint64(filepath.Join(memoryRoot, "memory.usage_in_bytes")); err != nil { + + path := filepath.Join(memoryRoot, "memory.stat") + values, err := readCgroupMapPath(path) + if err != nil { return err } + + // cgroup v1 does not have a single "anon" field, but we can calculate it + // from total_active_anon and total_inactive_anon + memUsage.Usage.Usage = 0 + for _, key := range []string{"total_active_anon", "total_inactive_anon"} { + if _, found := values[key]; !found { + continue + } + res, err := strconv.ParseUint(values[key][0], 10, 64) + if err != nil { + return fmt.Errorf("parse %s from %s: %w", key, path, err) + } + memUsage.Usage.Usage += res + } } memUsage.Usage.Limit, err = readFileAsUint64(filepath.Join(memoryRoot, limitFilename)) diff --git a/vendor/github.com/containers/common/pkg/cgroups/pids.go b/vendor/github.com/containers/common/pkg/cgroups/pids.go deleted file mode 100644 index 76e983ea967..00000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/pids.go +++ /dev/null @@ -1,71 +0,0 @@ -//go:build !linux -// +build !linux - -package cgroups - -import ( - "fmt" - "os" - "path/filepath" - - spec "github.com/opencontainers/runtime-spec/specs-go" -) - -type pidHandler struct{} - -func getPidsHandler() *pidHandler { - return &pidHandler{} -} - -// Apply set the specified constraints -func (c *pidHandler) Apply(ctr *CgroupControl, res *spec.LinuxResources) error { - if res.Pids == nil { - return nil - } - var PIDRoot string - - if ctr.cgroup2 { - PIDRoot = filepath.Join(cgroupRoot, ctr.path) - } else { - PIDRoot = ctr.getCgroupv1Path(Pids) - } - - p := filepath.Join(PIDRoot, "pids.max") - return os.WriteFile(p, []byte(fmt.Sprintf("%d\n", res.Pids.Limit)), 0o644) -} - -// Create the cgroup -func (c *pidHandler) Create(ctr *CgroupControl) (bool, error) { - if ctr.cgroup2 { - return false, nil - } - return ctr.createCgroupDirectory(Pids) -} - -// Destroy the cgroup -func (c *pidHandler) Destroy(ctr *CgroupControl) error { - return rmDirRecursively(ctr.getCgroupv1Path(Pids)) -} - -// Stat fills a metrics structure with usage stats for the controller -func (c *pidHandler) Stat(ctr *CgroupControl, m *Metrics) error { - if ctr.path == "" { - // nothing we can do to retrieve the pids.current path - return nil - } - - var PIDRoot string - if ctr.cgroup2 { - PIDRoot = filepath.Join(cgroupRoot, ctr.path) - } else { - PIDRoot = ctr.getCgroupv1Path(Pids) - } - - current, err := readFileAsUint64(filepath.Join(PIDRoot, "pids.current")) - if err != nil { - return err - } - - m.Pids = PidsMetrics{Current: current} - return nil -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go index e8107604dee..906c716d112 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/systemd_linux.go @@ -29,7 +29,7 @@ func systemdCreate(resources *configs.Resources, path string, c *systemdDbus.Con systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)), systemdDbus.PropWants(slice), } - ioString := "" + var ioString string v2, _ := IsCgroup2UnifiedMode() if v2 { ioString = "IOAccounting" @@ -250,7 +250,6 @@ func resourcesToProps(res *configs.Resources, v2 bool) (map[string]uint64, map[s } else { structMap["BlockIODeviceWeight"] = append(structMap["BlockIODeviceWeight"], newWeight) } - } } diff --git a/vendor/github.com/containers/common/pkg/cgroups/utils.go b/vendor/github.com/containers/common/pkg/cgroups/utils.go deleted file mode 100644 index 8ade67878d4..00000000000 --- a/vendor/github.com/containers/common/pkg/cgroups/utils.go +++ /dev/null @@ -1,179 +0,0 @@ -package cgroups - -import ( - "bytes" - "errors" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" -) - -var TestMode bool - -func cleanString(s string) string { - return strings.Trim(s, "\n") -} - -func readAcct(ctr *CgroupControl, name string) (uint64, error) { - p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name) - return readFileAsUint64(p) -} - -func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) { - p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name) - data, err := os.ReadFile(p) - if err != nil { - return nil, err - } - r := []uint64{} - for _, s := range strings.Split(string(data), " ") { - s = cleanString(s) - if s == "" { - break - } - v, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, fmt.Errorf("parsing %s: %w", s, err) - } - r = append(r, v) - } - return r, nil -} - -// GetSystemCPUUsage returns the system usage for all the cgroups -func GetSystemCPUUsage() (uint64, error) { - cgroupv2, err := IsCgroup2UnifiedMode() - if err != nil { - return 0, err - } - if !cgroupv2 { - p := filepath.Join(cgroupRoot, CPUAcct, "cpuacct.usage") - return readFileAsUint64(p) - } - - files, err := os.ReadDir(cgroupRoot) - if err != nil { - return 0, err - } - var total uint64 - for _, file := range files { - if !file.IsDir() { - continue - } - p := filepath.Join(cgroupRoot, file.Name(), "cpu.stat") - - values, err := readCgroup2MapPath(p) - if err != nil { - return 0, err - } - - if val, found := values["usage_usec"]; found { - v, err := strconv.ParseUint(cleanString(val[0]), 10, 64) - if err != nil { - return 0, err - } - total += v * 1000 - } - } - return total, nil -} - -func cpusetCopyFileFromParent(dir, file string, cgroupv2 bool) ([]byte, error) { - if dir == cgroupRoot { - return nil, fmt.Errorf("could not find parent to initialize cpuset %s", file) - } - path := filepath.Join(dir, file) - parentPath := path - if cgroupv2 { - parentPath = fmt.Sprintf("%s.effective", parentPath) - } - data, err := os.ReadFile(parentPath) - if err != nil { - // if the file doesn't exist, it is likely that the cpuset controller - // is not enabled in the kernel. - if os.IsNotExist(err) { - return nil, nil - } - return nil, err - } - if strings.Trim(string(data), "\n") != "" { - return data, nil - } - data, err = cpusetCopyFileFromParent(filepath.Dir(dir), file, cgroupv2) - if err != nil { - return nil, err - } - if err := os.WriteFile(path, data, 0o644); err != nil { - return nil, fmt.Errorf("write %s: %w", path, err) - } - return data, nil -} - -func cpusetCopyFromParent(path string, cgroupv2 bool) error { - for _, file := range []string{"cpuset.cpus", "cpuset.mems"} { - if _, err := cpusetCopyFileFromParent(path, file, cgroupv2); err != nil { - return err - } - } - return nil -} - -// createCgroupv2Path creates the cgroupv2 path and enables all the available controllers -func createCgroupv2Path(path string) (deferredError error) { - if !strings.HasPrefix(path, cgroupRoot+"/") { - return fmt.Errorf("invalid cgroup path %s", path) - } - content, err := os.ReadFile(cgroupRoot + "/cgroup.controllers") - if err != nil { - return err - } - ctrs := bytes.Fields(content) - res := append([]byte("+"), bytes.Join(ctrs, []byte(" +"))...) - - current := "/sys/fs" - elements := strings.Split(path, "/") - for i, e := range elements[3:] { - current = filepath.Join(current, e) - if i > 0 { - if err := os.Mkdir(current, 0o755); err != nil { - if !os.IsExist(err) { - return err - } - } else { - // If the directory was created, be sure it is not left around on errors. - defer func() { - if deferredError != nil { - os.Remove(current) - } - }() - } - } - // We enable the controllers for all the path components except the last one. It is not allowed to add - // PIDs if there are already enabled controllers. - if i < len(elements[3:])-1 { - if err := os.WriteFile(filepath.Join(current, "cgroup.subtree_control"), res, 0o755); err != nil { - return err - } - } - } - return nil -} - -func (c *CgroupControl) createCgroupDirectory(controller string) (bool, error) { - cPath := c.getCgroupv1Path(controller) - _, err := os.Stat(cPath) - if err == nil { - return false, nil - } - - if !errors.Is(err, os.ErrNotExist) { - return false, err - } - - if err := os.MkdirAll(cPath, 0o755); err != nil { - return false, fmt.Errorf("creating cgroup for %s: %w", controller, err) - } - return true, nil -} diff --git a/vendor/github.com/containers/common/pkg/cgroups/utils_linux.go b/vendor/github.com/containers/common/pkg/cgroups/utils_linux.go index e4bd4d5df37..ed9f0761df8 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/utils_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/utils_linux.go @@ -26,7 +26,7 @@ func WriteFile(dir, file, data string) error { } defer fd.Close() for { - _, err := fd.Write([]byte(data)) + _, err := fd.WriteString(data) if errors.Is(err, unix.EINTR) { logrus.Infof("interrupted while writing %s to %s", data, fd.Name()) continue @@ -85,7 +85,6 @@ func OpenFile(dir, file string, flags int) (*os.File, error) { Mode: uint64(mode), }) if err != nil { - fmt.Println("Error in openat") return nil, err } @@ -105,8 +104,8 @@ func ReadFile(dir, file string) (string, error) { return buf.String(), err } -// GetBlkioFiles gets the proper files for blkio weights -func GetBlkioFiles(cgroupPath string) (wtFile, wtDevFile string) { +// BlkioFiles gets the proper files for blkio weights +func BlkioFiles(cgroupPath string) (wtFile, wtDevFile string) { var weightFile string var weightDeviceFile string // in this important since runc keeps these variables private, they won't be set diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index b5f95011819..75b917f013e 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -3,16 +3,14 @@ package config import ( "errors" "fmt" - "io/fs" "os" "os/exec" "path/filepath" "runtime" - "sort" "strings" - "sync" "github.com/BurntSushi/toml" + "github.com/containers/common/internal/attributedstring" "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/util" @@ -33,24 +31,6 @@ const ( bindirPrefix = "$BINDIR" ) -// RuntimeStateStore is a constant indicating which state store implementation -// should be used by engine -type RuntimeStateStore int - -const ( - // InvalidStateStore is an invalid state store - InvalidStateStore RuntimeStateStore = iota - // InMemoryStateStore is an in-memory state that will not persist data - // on containers and pods between engine instances or after system - // reboot - InMemoryStateStore RuntimeStateStore = iota - // SQLiteStateStore is a state backed by a SQLite database - // It is presently disabled - SQLiteStateStore RuntimeStateStore = iota - // BoltDBStateStore is a state backed by a BoltDB database - BoltDBStateStore RuntimeStateStore = iota -) - var validImageVolumeModes = []string{_typeBind, "tmpfs", "ignore"} // ProxyEnv is a list of Proxy Environment variables @@ -79,23 +59,27 @@ type Config struct { Secrets SecretConfig `toml:"secrets"` // ConfigMap section defines configurations for the configmaps management ConfigMaps ConfigMapConfig `toml:"configmaps"` + // Farms defines configurations for the buildfarm farms + Farms FarmConfig `toml:"farms"` + + loadedModules []string // only used at runtime to store which modules were loaded } // ContainersConfig represents the "containers" TOML config table // containers global options for containers tools type ContainersConfig struct { // Devices to add to all containers - Devices []string `toml:"devices,omitempty"` + Devices attributedstring.Slice `toml:"devices,omitempty"` // Volumes to add to all containers - Volumes []string `toml:"volumes,omitempty"` + Volumes attributedstring.Slice `toml:"volumes,omitempty"` // ApparmorProfile is the apparmor profile name which is used as the // default for the runtime. ApparmorProfile string `toml:"apparmor_profile,omitempty"` // Annotation to add to all containers - Annotations []string `toml:"annotations,omitempty"` + Annotations attributedstring.Slice `toml:"annotations,omitempty"` // BaseHostsFile is the path to a hosts file, the entries from this file // are added to the containers hosts file. As special value "image" is @@ -112,28 +96,28 @@ type ContainersConfig struct { // CgroupConf entries specifies a list of cgroup files to write to and their values. For example // "memory.high=1073741824" sets the memory.high limit to 1GB. - CgroupConf []string `toml:"cgroup_conf,omitempty"` + CgroupConf attributedstring.Slice `toml:"cgroup_conf,omitempty"` // Capabilities to add to all containers. - DefaultCapabilities []string `toml:"default_capabilities,omitempty"` + DefaultCapabilities attributedstring.Slice `toml:"default_capabilities,omitempty"` // Sysctls to add to all containers. - DefaultSysctls []string `toml:"default_sysctls,omitempty"` + DefaultSysctls attributedstring.Slice `toml:"default_sysctls,omitempty"` // DefaultUlimits specifies the default ulimits to apply to containers - DefaultUlimits []string `toml:"default_ulimits,omitempty"` + DefaultUlimits attributedstring.Slice `toml:"default_ulimits,omitempty"` // DefaultMountsFile is the path to the default mounts file for testing DefaultMountsFile string `toml:"-"` // DNSServers set default DNS servers. - DNSServers []string `toml:"dns_servers,omitempty"` + DNSServers attributedstring.Slice `toml:"dns_servers,omitempty"` // DNSOptions set default DNS options. - DNSOptions []string `toml:"dns_options,omitempty"` + DNSOptions attributedstring.Slice `toml:"dns_options,omitempty"` // DNSSearches set default DNS search domains. - DNSSearches []string `toml:"dns_searches,omitempty"` + DNSSearches attributedstring.Slice `toml:"dns_searches,omitempty"` // EnableKeyring tells the container engines whether to create // a kernel keyring for use within the container @@ -150,7 +134,7 @@ type ContainersConfig struct { EnableLabeledUsers bool `toml:"label_users,omitempty"` // Env is the environment variable list for container process. - Env []string `toml:"env,omitempty"` + Env attributedstring.Slice `toml:"env,omitempty"` // EnvHost Pass all host environment variables into the container. EnvHost bool `toml:"env_host,omitempty"` @@ -166,9 +150,11 @@ type ContainersConfig struct { Init bool `toml:"init,omitempty"` // InitPath is the path for init to run if the Init bool is enabled + // + // Deprecated: Do not use this field directly use conf.FindInitBinary() instead. InitPath string `toml:"init_path,omitempty"` - // IPCNS way to to create a ipc namespace for the container + // IPCNS way to create a ipc namespace for the container IPCNS string `toml:"ipcns,omitempty"` // LogDriver for the container. For example: k8s-file and journald @@ -185,6 +171,9 @@ type ContainersConfig struct { // Containers logs default to truncated container ID as a tag. LogTag string `toml:"log_tag,omitempty"` + // Mount to add to all containers + Mounts attributedstring.Slice `toml:"mounts,omitempty"` + // NetNS indicates how to create a network namespace for the container NetNS string `toml:"netns,omitempty"` @@ -209,6 +198,18 @@ type ContainersConfig struct { // performance implications. PrepareVolumeOnCreate bool `toml:"prepare_volume_on_create,omitempty"` + // Give extended privileges to all containers. A privileged container + // turns off the security features that isolate the container from the + // host. Dropped Capabilities, limited devices, read-only mount points, + // Apparmor/SELinux separation, and Seccomp filters are all disabled. + // Due to the disabled security features the privileged field should + // almost never be set as containers can easily break out of + // confinment. + // + // Containers running in a user namespace (e.g., rootless containers) + // cannot have more privileges than the user that launched them. + Privileged bool `toml:"privileged,omitempty"` + // ReadOnly causes engine to run all containers with root file system mounted read-only ReadOnly bool `toml:"read_only,omitempty"` @@ -250,15 +251,15 @@ type EngineConfig struct { // ConmonEnvVars are environment variables to pass to the Conmon binary // when it is launched. - ConmonEnvVars []string `toml:"conmon_env_vars,omitempty"` + ConmonEnvVars attributedstring.Slice `toml:"conmon_env_vars,omitempty"` // ConmonPath is the path to the Conmon binary used for managing containers. // The first path pointing to a valid file will be used. - ConmonPath []string `toml:"conmon_path,omitempty"` + ConmonPath attributedstring.Slice `toml:"conmon_path,omitempty"` // ConmonRsPath is the path to the Conmon-rs binary used for managing containers. // The first path pointing to a valid file will be used. - ConmonRsPath []string `toml:"conmonrs_path,omitempty"` + ConmonRsPath attributedstring.Slice `toml:"conmonrs_path,omitempty"` // CompatAPIEnforceDockerHub enforces using docker.io for completing // short names in Podman's compatibility REST API. Note that this will @@ -266,6 +267,17 @@ type EngineConfig struct { // in containers-registries.conf(5). CompatAPIEnforceDockerHub bool `toml:"compat_api_enforce_docker_hub,omitempty"` + // ComposeProviders specifies one or more external providers for the + // compose command. The first found provider is used for execution. + // Can be an absolute and relative path or a (file) name. Make sure to + // expand the return items via `os.ExpandEnv`. + ComposeProviders attributedstring.Slice `toml:"compose_providers,omitempty"` + + // ComposeWarningLogs emits logs on each invocation of the compose + // command indicating that an external compose provider is being + // executed. + ComposeWarningLogs bool `toml:"compose_warning_logs,omitempty"` + // DBBackend is the database backend to be used by Podman. DBBackend string `toml:"database_backend,omitempty"` @@ -282,7 +294,7 @@ type EngineConfig struct { EnablePortReservation bool `toml:"enable_port_reservation,omitempty"` // Environment variables to be used when running the container engine (e.g., Podman, Buildah). For example "http_proxy=internal.proxy.company.com" - Env []string `toml:"env,omitempty"` + Env attributedstring.Slice `toml:"env,omitempty"` // EventsLogFilePath is where the events log is stored. EventsLogFilePath string `toml:"events_logfile_path,omitempty"` @@ -304,12 +316,12 @@ type EngineConfig struct { // HelperBinariesDir is a list of directories which are used to search for // helper binaries. - HelperBinariesDir []string `toml:"helper_binaries_dir"` + HelperBinariesDir attributedstring.Slice `toml:"helper_binaries_dir,omitempty"` - // configuration files. When the same filename is present in in + // configuration files. When the same filename is present in // multiple directories, the file in the directory listed last in // this slice takes precedence. - HooksDir []string `toml:"hooks_dir,omitempty"` + HooksDir attributedstring.Slice `toml:"hooks_dir,omitempty"` // ImageBuildFormat (DEPRECATED) indicates the default image format to // building container images. Should use ImageDefaultFormat @@ -342,6 +354,8 @@ type EngineConfig struct { InfraImage string `toml:"infra_image,omitempty"` // InitPath is the path to the container-init binary. + // + // Deprecated: Do not use this field directly use conf.FindInitBinary() instead. InitPath string `toml:"init_path,omitempty"` // KubeGenerateType sets the Kubernetes kind/specification to generate by default @@ -374,7 +388,7 @@ type EngineConfig struct { // NetworkCmdOptions is the default options to pass to the slirp4netns binary. // For example "allow_host_loopback=true" - NetworkCmdOptions []string `toml:"network_cmd_options,omitempty"` + NetworkCmdOptions attributedstring.Slice `toml:"network_cmd_options,omitempty"` // NoPivotRoot sets whether to set no-pivot-root in the OCI runtime. NoPivotRoot bool `toml:"no_pivot_root,omitempty"` @@ -413,6 +427,9 @@ type EngineConfig struct { // ActiveService index to Destinations added v2.0.3 ActiveService string `toml:"active_service,omitempty"` + // Add existing instances with requested compression algorithms to manifest list + AddCompression attributedstring.Slice `toml:"add_compression,omitempty"` + // ServiceDestinations mapped by service Names ServiceDestinations map[string]Destination `toml:"service_destinations,omitempty"` @@ -423,19 +440,19 @@ type EngineConfig struct { // The first path pointing to a valid file will be used This is used only // when there are no OCIRuntime/OCIRuntimes defined. It is used only to be // backward compatible with older versions of Podman. - RuntimePath []string `toml:"runtime_path,omitempty"` + RuntimePath attributedstring.Slice `toml:"runtime_path,omitempty"` // RuntimeSupportsJSON is the list of the OCI runtimes that support // --format=json. - RuntimeSupportsJSON []string `toml:"runtime_supports_json,omitempty"` + RuntimeSupportsJSON attributedstring.Slice `toml:"runtime_supports_json,omitempty"` // RuntimeSupportsNoCgroups is a list of OCI runtimes that support // running containers without CGroups. - RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroup,omitempty"` + RuntimeSupportsNoCgroups attributedstring.Slice `toml:"runtime_supports_nocgroup,omitempty"` // RuntimeSupportsKVM is a list of OCI runtimes that support // KVM separation for containers. - RuntimeSupportsKVM []string `toml:"runtime_supports_kvm,omitempty"` + RuntimeSupportsKVM attributedstring.Slice `toml:"runtime_supports_kvm,omitempty"` // SetOptions contains a subset of config options. It's used to indicate if // a given option has either been set by the user or by the parsed @@ -453,13 +470,6 @@ type EngineConfig struct { // readiness using the SD_NOTIFY mechanism. SDNotify bool `toml:"-"` - // StateType is the type of the backing state store. Avoid using multiple - // values for this with the same containers/storage configuration on the - // same system. Different state types do not interact, and each will see a - // separate set of containers, which may cause conflicts in - // containers/storage. As such this is not exposed via the config file. - StateType RuntimeStateStore `toml:"-"` - // ServiceTimeout is the number of seconds to wait without a connection // before the `podman system service` times out and exits ServiceTimeout uint `toml:"service_timeout,omitempty,omitzero"` @@ -513,6 +523,11 @@ type EngineConfig struct { // CompressionLevel is the compression level used to compress image layers. CompressionLevel *int `toml:"compression_level,omitempty"` + + // PodmanshTimeout is the number of seconds to wait for podmansh logins. + // In other words, the timeout for the `podmansh` container to be in running + // state. + PodmanshTimeout uint `toml:"podmansh_timeout,omitempty,omitzero"` } // SetOptions contains a subset of options in a Config. It's used to indicate if @@ -538,24 +553,6 @@ type SetOptions struct { // backwards compatibility with older versions of libpod for which we must // query the database configuration. Not included in the on-disk config. StorageConfigGraphDriverNameSet bool `toml:"-"` - - // StaticDirSet indicates if the StaticDir has been explicitly set by the - // config or by the user. It's required to guarantee backwards compatibility - // with older versions of libpod for which we must query the database - // configuration. Not included in the on-disk config. - StaticDirSet bool `toml:"-"` - - // VolumePathSet indicates if the VolumePath has been explicitly set by the - // config or by the user. It's required to guarantee backwards compatibility - // with older versions of libpod for which we must query the database - // configuration. Not included in the on-disk config. - VolumePathSet bool `toml:"-"` - - // TmpDirSet indicates if the TmpDir has been explicitly set by the config - // or by the user. It's required to guarantee backwards compatibility with - // older versions of libpod for which we must query the database - // configuration. Not included in the on-disk config. - TmpDirSet bool `toml:"-"` } // NetworkConfig represents the "network" TOML config table @@ -565,10 +562,10 @@ type NetworkConfig struct { NetworkBackend string `toml:"network_backend,omitempty"` // CNIPluginDirs is where CNI plugin binaries are stored. - CNIPluginDirs []string `toml:"cni_plugin_dirs,omitempty"` + CNIPluginDirs attributedstring.Slice `toml:"cni_plugin_dirs,omitempty"` // NetavarkPluginDirs is a list of directories which contain netavark plugins. - NetavarkPluginDirs []string `toml:"netavark_plugin_dirs,omitempty"` + NetavarkPluginDirs attributedstring.Slice `toml:"netavark_plugin_dirs,omitempty"` // DefaultNetwork is the network name of the default network // to attach pods to. @@ -601,7 +598,7 @@ type NetworkConfig struct { // PastaOptions contains a default list of pasta(1) options that should // be used when running pasta. - PastaOptions []string `toml:"pasta_options,omitempty"` + PastaOptions attributedstring.Slice `toml:"pasta_options,omitempty"` } type SubnetPool struct { @@ -652,11 +649,19 @@ type MachineConfig struct { // User to use for rootless podman when init-ing a podman machine VM User string `toml:"user,omitempty"` // Volumes are host directories mounted into the VM by default. - Volumes []string `toml:"volumes"` + Volumes attributedstring.Slice `toml:"volumes,omitempty"` // Provider is the virtualization provider used to run podman-machine VM Provider string `toml:"provider,omitempty"` } +// FarmConfig represents the "farm" TOML config tables +type FarmConfig struct { + // Default is the default farm to be used when farming out builds + Default string `toml:"default,omitempty"` + // List is a map of farms created where key=farm-name and value=list of connections + List map[string][]string `toml:"list,omitempty"` +} + // Destination represents destination for remote service type Destination struct { // URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock @@ -679,166 +684,6 @@ func (c *EngineConfig) ImagePlatformToRuntime(os string, arch string) string { return c.OCIRuntime } -// NewConfig creates a new Config. It starts with an empty config and, if -// specified, merges the config at `userConfigPath` path. Depending if we're -// running as root or rootless, we then merge the system configuration followed -// by merging the default config (hard-coded default in memory). -// Note that the OCI runtime is hard-set to `crun` if we're running on a system -// with cgroupv2v2. Other OCI runtimes are not yet supporting cgroupv2v2. This -// might change in the future. -func NewConfig(userConfigPath string) (*Config, error) { - // Generate the default config for the system - config, err := DefaultConfig() - if err != nil { - return nil, err - } - - // Now, gather the system configs and merge them as needed. - configs, err := systemConfigs() - if err != nil { - return nil, fmt.Errorf("finding config on system: %w", err) - } - for _, path := range configs { - // Merge changes in later configs with the previous configs. - // Each config file that specified fields, will override the - // previous fields. - if err = readConfigFromFile(path, config); err != nil { - return nil, fmt.Errorf("reading system config %q: %w", path, err) - } - logrus.Debugf("Merged system config %q", path) - logrus.Tracef("%+v", config) - } - - // If the caller specified a config path to use, then we read it to - // override the system defaults. - if userConfigPath != "" { - var err error - // readConfigFromFile reads in container config in the specified - // file and then merge changes with the current default. - if err = readConfigFromFile(userConfigPath, config); err != nil { - return nil, fmt.Errorf("reading user config %q: %w", userConfigPath, err) - } - logrus.Debugf("Merged user config %q", userConfigPath) - logrus.Tracef("%+v", config) - } - config.addCAPPrefix() - - if err := config.Validate(); err != nil { - return nil, err - } - - if err := config.setupEnv(); err != nil { - return nil, err - } - - return config, nil -} - -// readConfigFromFile reads the specified config file at `path` and attempts to -// unmarshal its content into a Config. The config param specifies the previous -// default config. If the path, only specifies a few fields in the Toml file -// the defaults from the config parameter will be used for all other fields. -func readConfigFromFile(path string, config *Config) error { - logrus.Tracef("Reading configuration file %q", path) - meta, err := toml.DecodeFile(path, config) - if err != nil { - return fmt.Errorf("decode configuration %v: %w", path, err) - } - keys := meta.Undecoded() - if len(keys) > 0 { - logrus.Debugf("Failed to decode the keys %q from %q.", keys, path) - } - - return nil -} - -// addConfigs will search one level in the config dirPath for config files -// If the dirPath does not exist, addConfigs will return nil -func addConfigs(dirPath string, configs []string) ([]string, error) { - newConfigs := []string{} - - err := filepath.WalkDir(dirPath, - // WalkFunc to read additional configs - func(path string, d fs.DirEntry, err error) error { - switch { - case err != nil: - // return error (could be a permission problem) - return err - case d.IsDir(): - if path != dirPath { - // make sure to not recurse into sub-directories - return filepath.SkipDir - } - // ignore directories - return nil - default: - // only add *.conf files - if strings.HasSuffix(path, ".conf") { - newConfigs = append(newConfigs, path) - } - return nil - } - }, - ) - if errors.Is(err, os.ErrNotExist) { - err = nil - } - sort.Strings(newConfigs) - return append(configs, newConfigs...), err -} - -// Returns the list of configuration files, if they exist in order of hierarchy. -// The files are read in order and each new file can/will override previous -// file settings. -func systemConfigs() (configs []string, finalErr error) { - if path := os.Getenv("CONTAINERS_CONF_OVERRIDE"); path != "" { - if _, err := os.Stat(path); err != nil { - return nil, fmt.Errorf("CONTAINERS_CONF_OVERRIDE file: %w", err) - } - // Add the override config last to make sure it can override any - // previous settings. - defer func() { - if finalErr == nil { - configs = append(configs, path) - } - }() - } - - if path := os.Getenv("CONTAINERS_CONF"); path != "" { - if _, err := os.Stat(path); err != nil { - return nil, fmt.Errorf("CONTAINERS_CONF file: %w", err) - } - return append(configs, path), nil - } - if _, err := os.Stat(DefaultContainersConfig); err == nil { - configs = append(configs, DefaultContainersConfig) - } - if _, err := os.Stat(OverrideContainersConfig); err == nil { - configs = append(configs, OverrideContainersConfig) - } - - var err error - configs, err = addConfigs(OverrideContainersConfig+".d", configs) - if err != nil { - return nil, err - } - - path, err := ifRootlessConfigPath() - if err != nil { - return nil, err - } - if path != "" { - if _, err := os.Stat(path); err == nil { - configs = append(configs, path) - } - configs, err = addConfigs(path+".d", configs) - if err != nil { - return nil, err - } - } - return configs, nil -} - // CheckCgroupsAndAdjustConfig checks if we're running rootless with the systemd // cgroup manager. In case the user session isn't available, we're switching the // cgroup manager to cgroupfs. Note, this only applies to rootless. @@ -869,15 +714,15 @@ func (c *Config) CheckCgroupsAndAdjustConfig() { } func (c *Config) addCAPPrefix() { - toCAPPrefixed := func(cap string) string { - if !strings.HasPrefix(strings.ToLower(cap), "cap_") { - return "CAP_" + strings.ToUpper(cap) + caps := c.Containers.DefaultCapabilities.Get() + newCaps := make([]string, 0, len(caps)) + for _, val := range caps { + if !strings.HasPrefix(strings.ToLower(val), "cap_") { + val = "CAP_" + strings.ToUpper(val) } - return cap - } - for i, cap := range c.Containers.DefaultCapabilities { - c.Containers.DefaultCapabilities[i] = toCAPPrefixed(cap) + newCaps = append(newCaps, val) } + c.Containers.DefaultCapabilities.Set(newCaps) } // Validate is the main entry point for library configuration validation. @@ -1005,24 +850,14 @@ func (c *NetworkConfig) Validate() error { } } - if stringsEq(c.CNIPluginDirs, DefaultCNIPluginDirs) { - return nil - } - - for _, pluginDir := range c.CNIPluginDirs { - if err := isDirectory(pluginDir); err == nil { - return nil - } - } - - return fmt.Errorf("invalid cni_plugin_dirs: %s", strings.Join(c.CNIPluginDirs, ",")) + return nil } // FindConmon iterates over (*Config).ConmonPath and returns the path // to first (version) matching conmon binary. If non is found, we try // to do a path lookup of "conmon". func (c *Config) FindConmon() (string, error) { - return findConmonPath(c.Engine.ConmonPath, "conmon") + return findConmonPath(c.Engine.ConmonPath.Get(), "conmon") } func findConmonPath(paths []string, binaryName string) (string, error) { @@ -1052,7 +887,7 @@ func findConmonPath(paths []string, binaryName string) (string, error) { // to first (version) matching conmonrs binary. If non is found, we try // to do a path lookup of "conmonrs". func (c *Config) FindConmonRs() (string, error) { - return findConmonPath(c.Engine.ConmonRsPath, "conmonrs") + return findConmonPath(c.Engine.ConmonRsPath.Get(), "conmonrs") } // GetDefaultEnv returns the environment variables for the container. @@ -1076,7 +911,7 @@ func (c *Config) GetDefaultEnvEx(envHost, httpProxy bool) []string { } } } - return append(env, c.Containers.Env...) + return append(env, c.Containers.Env.Get()...) } // Capabilities returns the capabilities parses the Add and Drop capability @@ -1089,7 +924,7 @@ func (c *Config) Capabilities(user string, addCapabilities, dropCapabilities []s return true } - defaultCapabilities := c.Containers.DefaultCapabilities + defaultCapabilities := c.Containers.DefaultCapabilities.Get() if userNotRoot(user) { defaultCapabilities = []string{} } @@ -1159,27 +994,6 @@ func IsValidDeviceMode(mode string) bool { return true } -// resolveHomeDir converts a path referencing the home directory via "~" -// to an absolute path -func resolveHomeDir(path string) (string, error) { - // check if the path references the home dir to avoid work - // don't use strings.HasPrefix(path, "~") as this doesn't match "~" alone - // use strings.HasPrefix(...) to not match "something/~/something" - if !(path == "~" || strings.HasPrefix(path, "~/")) { - // path does not reference home dir -> Nothing to do - return path, nil - } - - // only get HomeDir when necessary - home, err := unshare.HomeDir() - if err != nil { - return "", err - } - - // replace the first "~" (start of path) with the HomeDir to resolve "~" - return strings.Replace(path, "~", home, 1), nil -} - func rootlessConfigPath() (string, error) { if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" { return filepath.Join(configHome, _configPath), nil @@ -1192,51 +1006,6 @@ func rootlessConfigPath() (string, error) { return filepath.Join(home, UserOverrideContainersConfig), nil } -func stringsEq(a, b []string) bool { - if len(a) != len(b) { - return false - } - - for i := range a { - if a[i] != b[i] { - return false - } - } - - return true -} - -var ( - configErr error - configMutex sync.Mutex - config *Config -) - -// Default returns the default container config. -// Configuration files will be read in the following files: -// * /usr/share/containers/containers.conf -// * /etc/containers/containers.conf -// * $HOME/.config/containers/containers.conf # When run in rootless mode -// Fields in latter files override defaults set in previous files and the -// default config. -// None of these files are required, and not all fields need to be specified -// in each file, only the fields you want to override. -// The system defaults container config files can be overwritten using the -// CONTAINERS_CONF environment variable. This is usually done for testing. -func Default() (*Config, error) { - configMutex.Lock() - defer configMutex.Unlock() - if config != nil || configErr != nil { - return config, configErr - } - return defConfig() -} - -func defConfig() (*Config, error) { - config, configErr = NewConfig("") - return config, configErr -} - func Path() string { if path := os.Getenv("CONTAINERS_CONF"); path != "" { return path @@ -1267,6 +1036,10 @@ func ReadCustomConfig() (*Config, error) { return nil, err } } + // Let's always initialize the farm list so it is never nil + if newConfig.Farms.List == nil { + newConfig.Farms.List = make(map[string][]string) + } return newConfig, nil } @@ -1301,37 +1074,7 @@ func (c *Config) Write() error { // This function is meant to be used for long-running processes that need to reload potential changes made to // the cached containers.conf files. func Reload() (*Config, error) { - configMutex.Lock() - defer configMutex.Unlock() - return defConfig() -} - -func (c *Config) ActiveDestination() (uri, identity string, machine bool, err error) { - if uri, found := os.LookupEnv("CONTAINER_HOST"); found { - if v, found := os.LookupEnv("CONTAINER_SSHKEY"); found { - identity = v - } - return uri, identity, false, nil - } - connEnv := os.Getenv("CONTAINER_CONNECTION") - switch { - case connEnv != "": - d, found := c.Engine.ServiceDestinations[connEnv] - if !found { - return "", "", false, fmt.Errorf("environment variable CONTAINER_CONNECTION=%q service destination not found", connEnv) - } - return d.URI, d.Identity, d.IsMachine, nil - - case c.Engine.ActiveService != "": - d, found := c.Engine.ServiceDestinations[c.Engine.ActiveService] - if !found { - return "", "", false, fmt.Errorf("%q service destination not found", c.Engine.ActiveService) - } - return d.URI, d.Identity, d.IsMachine, nil - case c.Engine.RemoteURI != "": - return c.Engine.RemoteURI, c.Engine.RemoteIdentity, false, nil - } - return "", "", false, errors.New("no service destination configured") + return New(&Options{SetDefault: true}) } var ( @@ -1362,7 +1105,7 @@ func findBindir() string { // FindHelperBinary will search the given binary name in the configured directories. // If searchPATH is set to true it will also search in $PATH. func (c *Config) FindHelperBinary(name string, searchPATH bool) (string, error) { - dirList := c.Engine.HelperBinariesDir + dirList := c.Engine.HelperBinariesDir.Get() bindirPath := "" bindirSearched := false @@ -1403,7 +1146,7 @@ func (c *Config) FindHelperBinary(name string, searchPATH bool) (string, error) return exec.LookPath(name) } configHint := "To resolve this error, set the helper_binaries_dir key in the `[engine]` section of containers.conf to the directory containing your helper binaries." - if len(c.Engine.HelperBinariesDir) == 0 { + if len(c.Engine.HelperBinariesDir.Get()) == 0 { return "", fmt.Errorf("could not find %q because there are no helper binary directories configured. %s", name, configHint) } return "", fmt.Errorf("could not find %q in one of %v. %s", name, c.Engine.HelperBinariesDir, configHint) @@ -1430,7 +1173,7 @@ func (c *Config) ImageCopyTmpDir() (string, error) { // setupEnv sets the environment variables for the engine func (c *Config) setupEnv() error { - for _, env := range c.Engine.Env { + for _, env := range c.Engine.Env.Get() { splitEnv := strings.SplitN(env, "=", 2) if len(splitEnv) != 2 { logrus.Warnf("invalid environment variable for engine %s, valid configuration is KEY=value pair", env) @@ -1488,3 +1231,20 @@ func ValidateImageVolumeMode(mode string) error { return fmt.Errorf("invalid image volume mode %q required value: %s", mode, strings.Join(validImageVolumeModes, ", ")) } + +// FindInitBinary will return the path to the init binary (catatonit) +func (c *Config) FindInitBinary() (string, error) { + // Sigh, for some reason we ended up with two InitPath field in containers.conf and + // both are used in podman so we have to keep supporting both to prevent regressions. + if c.Containers.InitPath != "" { + return c.Containers.InitPath, nil + } + if c.Engine.InitPath != "" { + return c.Engine.InitPath, nil + } + // keep old default working to guarantee backwards comapt + if _, err := os.Stat(DefaultInitPath); err == nil { + return DefaultInitPath, nil + } + return c.FindHelperBinary(defaultInitName, true) +} diff --git a/vendor/github.com/containers/common/pkg/config/config_darwin.go b/vendor/github.com/containers/common/pkg/config/config_darwin.go index eb83733d46b..1b40e2bae70 100644 --- a/vendor/github.com/containers/common/pkg/config/config_darwin.go +++ b/vendor/github.com/containers/common/pkg/config/config_darwin.go @@ -32,6 +32,8 @@ func ifRootlessConfigPath() (string, error) { } var defaultHelperBinariesDir = []string{ + // Relative to the binary directory + "$BINDIR/../libexec/podman", // Homebrew install paths "/usr/local/opt/podman/libexec/podman", "/opt/homebrew/opt/podman/libexec/podman", @@ -42,6 +44,4 @@ var defaultHelperBinariesDir = []string{ "/usr/local/lib/podman", "/usr/libexec/podman", "/usr/lib/podman", - // Relative to the binary directory - "$BINDIR/../libexec/podman", } diff --git a/vendor/github.com/containers/common/pkg/config/config_local.go b/vendor/github.com/containers/common/pkg/config/config_local.go index e101b062193..dae3ea0d96a 100644 --- a/vendor/github.com/containers/common/pkg/config/config_local.go +++ b/vendor/github.com/containers/common/pkg/config/config_local.go @@ -9,37 +9,11 @@ import ( "path/filepath" "regexp" "strings" - "syscall" - "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi" units "github.com/docker/go-units" + "tags.cncf.io/container-device-interface/pkg/parser" ) -// isDirectory tests whether the given path exists and is a directory. It -// follows symlinks. -func isDirectory(path string) error { - path, err := resolveHomeDir(path) - if err != nil { - return err - } - - info, err := os.Stat(path) - if err != nil { - return err - } - - if !info.Mode().IsDir() { - // Return a PathError to be consistent with os.Stat(). - return &os.PathError{ - Op: "stat", - Path: path, - Err: syscall.ENOTDIR, - } - } - - return nil -} - func (c *EngineConfig) validatePaths() error { // Relative paths can cause nasty bugs, because core paths we use could // shift between runs or even parts of the program. - The OCI runtime @@ -57,8 +31,8 @@ func (c *EngineConfig) validatePaths() error { } func (c *ContainersConfig) validateDevices() error { - for _, d := range c.Devices { - if cdi.IsQualifiedName(d) { + for _, d := range c.Devices.Get() { + if parser.IsQualifiedName(d) { continue } _, _, _, err := Device(d) @@ -70,7 +44,7 @@ func (c *ContainersConfig) validateDevices() error { } func (c *ContainersConfig) validateUlimits() error { - for _, u := range c.DefaultUlimits { + for _, u := range c.DefaultUlimits.Get() { ul, err := units.ParseUlimit(u) if err != nil { return fmt.Errorf("unrecognized ulimit %s: %w", u, err) diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index a106fd68644..8c532f0798c 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -119,7 +119,6 @@ default_sysctls = [ # #env = [ # "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", -# "TERM=xterm", #] # Pass all host environment variables into the container. @@ -150,6 +149,9 @@ default_sysctls = [ #init = false # Container init binary, if init=true, this is the init binary to be used for containers. +# If this option is not set catatonit is searched in the directories listed under +# the helper_binaries_dir option. It is recommended to just install catatonit +# there instead of configuring this option here. # #init_path = "/usr/libexec/podman/catatonit" @@ -196,6 +198,13 @@ default_sysctls = [ # #log_tag = "" +# List of mounts. Specified as +# "type=TYPE,source=,destination=,", for example: +# "type=bind,source=/var/lib/foobar,destination=/var/lib/foobar,ro". +# If it is empty or commented out, no mounts will be added +# +#mounts = [] + # Default way to to create a Network namespace for the container # Options are: # `private` Create private Network Namespace for the container. @@ -231,6 +240,18 @@ default_sysctls = [ # #prepare_volume_on_create = false +# Give extended privileges to all containers. A privileged container turns off +# the security features that isolate the container from the host. Dropped +# Capabilities, limited devices, read-only mount points, Apparmor/SELinux +# separation, and Seccomp filters are all disabled. Due to the disabled +# security features the privileged field should almost never be set as +# containers can easily break out of confinment. +# +# Containers running in a user namespace (e.g., rootless containers) cannot +# have more privileges than the user that launched them. +# +#privileged = false + # Run all containers with root file system mounted read-only # # read_only = false @@ -276,7 +297,7 @@ default_sysctls = [ # If it is empty or commented out, no volumes will be added # #volumes = [] -# + #[engine.platform_to_oci_runtime] #"wasi/wasm" = ["crun-wasm"] #"wasi/wasm32" = ["crun-wasm"] @@ -376,8 +397,28 @@ default_sysctls = [ # #active_service = "production" +#List of compression algorithms. If set makes sure that requested compression variant +#for each platform is added to the manifest list keeping original instance intact in +#the same manifest list on every `manifest push`. Supported values are (`gzip`, `zstd` and `zstd:chunked`). +# +#add_compression = ["gzip", "zstd", "zstd:chunked"] + +# Enforces using docker.io for completing short names in Podman's compatibility +# REST API. Note that this will ignore unqualified-search-registries and +# short-name aliases defined in containers-registries.conf(5). +#compat_api_enforce_docker_hub = true + +# Specify one or more external providers for the compose command. The first +# found provider is used for execution. Can be an absolute and relative path +# or a (file) name. +#compose_providers=[] + +# Emit logs on each invocation of the compose command indicating that an +# external compose provider is being executed. +#compose_warning_logs = true + # The compression format to use when pushing an image. -# Valid options are: `gzip` and `zstd`. +# Valid options are: `gzip`, `zstd` and `zstd:chunked`. # #compression_format = "gzip" @@ -416,10 +457,14 @@ default_sysctls = [ # short-name aliases defined in containers-registries.conf(5). #compat_api_enforce_docker_hub = true -# The database backend of Podman. Supported values are "boltdb" (default) and -# "sqlite". Please run `podman-system-reset` prior to changing the database +# The database backend of Podman. Supported values are "" (default), "boltdb" +# and "sqlite". An empty value means it will check whenever a boltdb already +# exists and use it when it does, otherwise it will use sqlite as default +# (e.g. new installs). This allows for backwards compatibility with older versions. +# Please run `podman-system-reset` prior to changing the database # backend of an existing deployment, to make sure Podman can operate correctly. -#database_backend="boltdb" +# +#database_backend = "" # Specify the keys sequence used to detach a container. # Format is a single character [a-Z] or a comma separated sequence of @@ -643,8 +688,8 @@ default_sysctls = [ # [engine.service_destinations.production] # URI to access the Podman service # Examples: -# rootless "unix://run/user/$UID/podman/podman.sock" (Default) -# rootful "unix://run/podman/podman.sock (Default) +# rootless "unix:///run/user/$UID/podman/podman.sock" (Default) +# rootful "unix:///run/podman/podman.sock (Default) # remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock # remote rootful ssh://root@10.10.1.136:22/run/podman/podman.sock # @@ -669,6 +714,9 @@ default_sysctls = [ # A value of 0 is treated as no timeout. #volume_plugin_timeout = 5 +# Default timeout in seconds for podmansh logins. +#podmansh_timeout = 30 + # Paths to look for a valid OCI runtime (crun, runc, kata, runsc, krun, etc) [engine.runtimes] #crun = [ @@ -775,3 +823,11 @@ default_sysctls = [ # TOML does not provide a way to end a table other than a further table being # defined, so every key hereafter will be part of [machine] and not the # main config. + +[farms] +# +# the default farm to use when farming out builds +# default = "" +# +# map of existing farms +#[farms.list] diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd b/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd index 10586d60dec..f471e307905 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd +++ b/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd @@ -29,10 +29,14 @@ # #base_hosts_file = "" -# The database backend of Podman. Supported values are "boltdb" (default) and -# "sqlite". Please run `podman-system-reset` prior to changing the database +# The database backend of Podman. Supported values are "" (default), "boltdb" +# and "sqlite". An empty value means it will check whenever a boltdb already +# exists and use it when it does, otherwise it will use sqlite as default +# (e.g. new installs). This allows for backwards compatibility with older versions. +# Please run `podman-system-reset` prior to changing the database # backend of an existing deployment, to make sure Podman can operate correctly. -#database_backend="boltdb" +# +#database_backend = "" # List of default capabilities for containers. If it is empty or commented out, # the default capabilities defined in the container engine will be added. @@ -99,7 +103,6 @@ default_sysctls = [ # #env = [ # "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", -# "TERM=xterm", #] # Pass all host environment variables into the container. @@ -130,6 +133,9 @@ default_sysctls = [ #init = false # Container init binary, if init=true, this is the init binary to be used for containers. +# If this option is not set catatonit is searched in the directories listed under +# the helper_binaries_dir option. It is recommended to just install catatonit +# there instead of configuring this option here. # #init_path = "/usr/local/libexec/podman/catatonit" @@ -201,6 +207,18 @@ default_sysctls = [ # #prepare_volume_on_create = false +# Give extended privileges to all containers. A privileged container turns off +# the security features that isolate the container from the host. Dropped +# Capabilities, limited devices, read-only mount points, Apparmor/SELinux +# separation, and Seccomp filters are all disabled. Due to the disabled +# security features the privileged field should almost never be set as +# containers can easily break out of confinment. +# +# Containers running in a user namespace (e.g., rootless containers) cannot +# have more privileges than the user that launched them. +# +#privileged = false + # Set timezone in container. Takes IANA timezones as well as "local", # which sets the timezone in the container to match the host machine. # @@ -307,7 +325,7 @@ default_sysctls = [ #active_service = production # The compression format to use when pushing an image. -# Valid options are: `gzip` and `zstd`. +# Valid options are: `gzip`, `zstd` and `zstd:chunked`. # #compression_format = "gzip" @@ -500,7 +518,7 @@ default_sysctls = [ # List of the OCI runtimes that support --format=json. When json is supported # engine will use it for reporting nicer errors. # -#runtime_supports_json = ["crun", "runc", "kata", "runsc", "youki", "krun"] +#runtime_supports_json = ["crun", "runc", "kata", "runsc", "youki", "krun", "ocijail"] # List of the OCI runtimes that supports running containers with KVM Separation. # @@ -542,8 +560,8 @@ default_sysctls = [ # [service_destinations.production] # URI to access the Podman service # Examples: -# rootless "unix://run/user/$UID/podman/podman.sock" (Default) -# rootful "unix://run/podman/podman.sock (Default) +# rootless "unix:///run/user/$UID/podman/podman.sock" (Default) +# rootful "unix:///run/podman/podman.sock (Default) # remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock # remote rootful ssh://root@10.10.1.136:22/run/podman/podman.sock # @@ -661,3 +679,11 @@ default_sysctls = [ # TOML does not provide a way to end a table other than a further table being # defined, so every key hereafter will be part of [machine] and not the # main config. + +[farms] +# +# the default farm to use when farming out builds +# default = "" +# +# map of existing farms +#[farms.list] diff --git a/vendor/github.com/containers/common/pkg/config/db_backend.go b/vendor/github.com/containers/common/pkg/config/db_backend.go index 8fd78165bbe..a2fda8e02d2 100644 --- a/vendor/github.com/containers/common/pkg/config/db_backend.go +++ b/vendor/github.com/containers/common/pkg/config/db_backend.go @@ -13,6 +13,12 @@ const ( // SQLite backend. DBBackendSQLite + // DBBackendDefault describes that no explicit backend has been set. + // It should default to sqlite unless there is already an existing boltdb, + // this allows for backwards compatibility on upgrades. The actual detection + // logic must live in podman as we only know there were to look for the file. + DBBackendDefault + stringBoltDB = "boltdb" stringSQLite = "sqlite" ) @@ -24,6 +30,8 @@ func (d DBBackend) String() string { return stringBoltDB case DBBackendSQLite: return stringSQLite + case DBBackendDefault: + return "" default: return fmt.Sprintf("unsupported database backend: %d", d) } @@ -32,7 +40,7 @@ func (d DBBackend) String() string { // Validate returns whether the DBBackend is supported. func (d DBBackend) Validate() error { switch d { - case DBBackendBoltDB, DBBackendSQLite: + case DBBackendBoltDB, DBBackendSQLite, DBBackendDefault: return nil default: return fmt.Errorf("unsupported database backend: %d", d) @@ -49,12 +57,9 @@ func ParseDBBackend(raw string) (DBBackend, error) { return DBBackendBoltDB, nil case stringSQLite: return DBBackendSQLite, nil + case "": + return DBBackendDefault, nil default: return DBBackendUnsupported, fmt.Errorf("unsupported database backend: %q", raw) } } - -// DBBackend returns the configured database backend. -func (c *Config) DBBackend() (DBBackend, error) { - return ParseDBBackend(c.Engine.DBBackend) -} diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index 985335760d0..ea2ede1cb44 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -6,8 +6,10 @@ import ( "net" "os" "path/filepath" + "runtime" "strings" + "github.com/containers/common/internal/attributedstring" nettypes "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/apparmor" "github.com/containers/common/pkg/cgroupv2" @@ -29,9 +31,36 @@ const ( // _defaultImageVolumeMode is a mode to handle built-in image volumes. _defaultImageVolumeMode = _typeBind + + // defaultInitName is the default name of the init binary + defaultInitName = "catatonit" ) var ( + DefaultMaskedPaths = []string{ + "/proc/acpi", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/sched_debug", + "/proc/scsi", + "/proc/timer_list", + "/proc/timer_stats", + "/sys/dev/block", + "/sys/devices/virtual/powercap", + "/sys/firmware", + "/sys/fs/selinux", + } + + DefaultReadOnlyPaths = []string{ + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger", + } + // DefaultInfraImage is the default image to run as infrastructure containers in pods. DefaultInfraImage = "" // DefaultRootlessSHMLockPath is the default path for rootless SHM locks. @@ -87,6 +116,18 @@ var ( // should be set during link-time, if different packagers put their // helper binary in a different location. additionalHelperBinariesDir string + + defaultUnixComposeProviders = []string{ + "docker-compose", + "$HOME/.docker/cli-plugins/docker-compose", + "/usr/local/lib/docker/cli-plugins/docker-compose", + "/usr/local/libexec/docker/cli-plugins/docker-compose", + "/usr/lib/docker/cli-plugins/docker-compose", + "/usr/libexec/docker/cli-plugins/docker-compose", + "podman-compose", + } + + defaultContainerEnv = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"} ) // nolint:unparam @@ -109,8 +150,6 @@ const ( CgroupfsCgroupsManager = "cgroupfs" // DefaultApparmorProfile specifies the default apparmor profile for the container. DefaultApparmorProfile = apparmor.Profile - // DefaultDBBackend specifies the default database backend to be used by Podman. - DefaultDBBackend = DBBackendBoltDB // DefaultHostsFile is the default path to the hosts file. DefaultHostsFile = "/etc/hosts" // SystemdCgroupsManager represents systemd native cgroup manager. @@ -147,9 +186,11 @@ const ( DefaultVolumePluginTimeout = 5 ) -// DefaultConfig defines the default values from containers.conf. -func DefaultConfig() (*Config, error) { - defaultEngineConfig, err := defaultConfigFromMemory() +// defaultConfig returns Config with builtin defaults and minimal adjustments +// to the current host only. It does not read any config files from the host or +// the environment. +func defaultConfig() (*Config, error) { + defaultEngineConfig, err := defaultEngineConfig() if err != nil { return nil, err } @@ -176,41 +217,39 @@ func DefaultConfig() (*Config, error) { return &Config{ Containers: ContainersConfig{ - Devices: []string{}, - Volumes: []string{}, - Annotations: []string{}, + Annotations: attributedstring.Slice{}, ApparmorProfile: DefaultApparmorProfile, BaseHostsFile: "", CgroupNS: cgroupNS, Cgroups: getDefaultCgroupsMode(), - DefaultCapabilities: DefaultCapabilities, - DefaultSysctls: []string{}, - DefaultUlimits: getDefaultProcessLimits(), - DNSServers: []string{}, - DNSOptions: []string{}, - DNSSearches: []string{}, + DNSOptions: attributedstring.Slice{}, + DNSSearches: attributedstring.Slice{}, + DNSServers: attributedstring.Slice{}, + DefaultCapabilities: attributedstring.NewSlice(DefaultCapabilities), + DefaultSysctls: attributedstring.Slice{}, + DefaultUlimits: attributedstring.NewSlice(getDefaultProcessLimits()), + Devices: attributedstring.Slice{}, EnableKeyring: true, EnableLabeling: selinuxEnabled(), - Env: []string{ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "TERM=xterm", - }, - EnvHost: false, - HTTPProxy: true, - Init: false, - InitPath: "", - IPCNS: "shareable", - LogDriver: defaultLogDriver(), - LogSizeMax: DefaultLogSizeMax, - NetNS: "private", - NoHosts: false, - PidsLimit: DefaultPidsLimit, - PidNS: "private", - ShmSize: DefaultShmSize, - TZ: "", - Umask: "0022", - UTSNS: "private", - UserNSSize: DefaultUserNSSize, // Deprecated + Env: attributedstring.NewSlice(defaultContainerEnv), + EnvHost: false, + HTTPProxy: true, + IPCNS: "shareable", + Init: false, + InitPath: "", + LogDriver: defaultLogDriver(), + LogSizeMax: DefaultLogSizeMax, + Mounts: attributedstring.Slice{}, + NetNS: "private", + NoHosts: false, + PidNS: "private", + PidsLimit: DefaultPidsLimit, + ShmSize: DefaultShmSize, + TZ: "", + UTSNS: "private", + Umask: "0022", + UserNSSize: DefaultUserNSSize, // Deprecated + Volumes: attributedstring.Slice{}, }, Network: NetworkConfig{ DefaultNetwork: "podman", @@ -218,12 +257,13 @@ func DefaultConfig() (*Config, error) { DefaultSubnetPools: DefaultSubnetPools, DefaultRootlessNetworkCmd: "slirp4netns", DNSBindPort: 0, - CNIPluginDirs: DefaultCNIPluginDirs, - NetavarkPluginDirs: DefaultNetavarkPluginDirs, + CNIPluginDirs: attributedstring.NewSlice(DefaultCNIPluginDirs), + NetavarkPluginDirs: attributedstring.NewSlice(DefaultNetavarkPluginDirs), }, Engine: *defaultEngineConfig, Secrets: defaultSecretConfig(), Machine: defaultMachineConfig(), + Farms: defaultFarmConfig(), }, nil } @@ -237,19 +277,31 @@ func defaultSecretConfig() SecretConfig { // defaultMachineConfig returns the default machine configuration. func defaultMachineConfig() MachineConfig { + cpus := runtime.NumCPU() / 2 + if cpus == 0 { + cpus = 1 + } return MachineConfig{ - CPUs: 1, + CPUs: uint64(cpus), DiskSize: 100, Image: getDefaultMachineImage(), Memory: 2048, User: getDefaultMachineUser(), - Volumes: getDefaultMachineVolumes(), + Volumes: attributedstring.NewSlice(getDefaultMachineVolumes()), + } +} + +// defaultFarmConfig returns the default farms configuration. +func defaultFarmConfig() FarmConfig { + emptyList := make(map[string][]string) + return FarmConfig{ + List: emptyList, } } -// defaultConfigFromMemory returns a default engine configuration. Note that the +// defaultEngineConfig returns a default engine configuration. Note that the // config is different for root and rootless. It also parses the storage.conf. -func defaultConfigFromMemory() (*EngineConfig, error) { +func defaultEngineConfig() (*EngineConfig, error) { c := new(EngineConfig) tmp, err := defaultTmpDir() if err != nil { @@ -260,6 +312,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) { c.EventsLogFileMaxSize = eventsLogMaxSize(DefaultEventsLogSizeMax) c.CompatAPIEnforceDockerHub = true + c.ComposeProviders.Set(getDefaultComposeProviders()) // may vary across supported platforms + c.ComposeWarningLogs = true if path, ok := os.LookupEnv("CONTAINERS_STORAGE_CONF"); ok { if err := types.SetDefaultConfigFilePath(path); err != nil { @@ -278,26 +332,25 @@ func defaultConfigFromMemory() (*EngineConfig, error) { c.graphRoot = storeOpts.GraphRoot c.ImageCopyTmpDir = getDefaultTmpDir() - c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod") - c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes") c.VolumePluginTimeout = DefaultVolumePluginTimeout c.CompressionFormat = "gzip" - c.HelperBinariesDir = defaultHelperBinariesDir + c.HelperBinariesDir.Set(defaultHelperBinariesDir) if additionalHelperBinariesDir != "" { - c.HelperBinariesDir = append(c.HelperBinariesDir, additionalHelperBinariesDir) + // Prioritize addtionalHelperBinariesDir over defaults. + c.HelperBinariesDir.Set(append([]string{additionalHelperBinariesDir}, c.HelperBinariesDir.Get()...)) } - c.HooksDir = DefaultHooksDirs + c.HooksDir.Set(DefaultHooksDirs) c.ImageDefaultTransport = _defaultTransport c.ImageVolumeMode = _defaultImageVolumeMode - c.StateType = BoltDBStateStore c.ImageBuildFormat = "oci" c.CgroupManager = defaultCgroupManager() c.ServiceTimeout = uint(5) c.StopTimeout = uint(10) + c.PodmanshTimeout = uint(30) c.ExitCommandDelay = uint(5 * 60) c.Remote = isRemote() c.OCIRuntimes = map[string][]string{ @@ -373,10 +426,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) { // Needs to be called after populating c.OCIRuntimes. c.OCIRuntime = c.findRuntime() - c.ConmonEnvVars = []string{ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - } - c.ConmonPath = []string{ + c.ConmonEnvVars.Set([]string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) + c.ConmonPath.Set([]string{ "/usr/libexec/podman/conmon", "/usr/local/libexec/podman/conmon", "/usr/local/lib/podman/conmon", @@ -385,8 +436,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) { "/usr/local/bin/conmon", "/usr/local/sbin/conmon", "/run/current-system/sw/bin/conmon", - } - c.ConmonRsPath = []string{ + }) + c.ConmonRsPath.Set([]string{ "/usr/libexec/podman/conmonrs", "/usr/local/libexec/podman/conmonrs", "/usr/local/lib/podman/conmonrs", @@ -395,20 +446,19 @@ func defaultConfigFromMemory() (*EngineConfig, error) { "/usr/local/bin/conmonrs", "/usr/local/sbin/conmonrs", "/run/current-system/sw/bin/conmonrs", - } + }) c.PullPolicy = DefaultPullPolicy - c.DBBackend = stringBoltDB - c.RuntimeSupportsJSON = []string{ + c.RuntimeSupportsJSON.Set([]string{ "crun", "runc", "kata", "runsc", "youki", "krun", - } - c.RuntimeSupportsNoCgroups = []string{"crun", "krun"} - c.RuntimeSupportsKVM = []string{"kata", "kata-runtime", "kata-qemu", "kata-fc", "krun"} - c.InitPath = DefaultInitPath + "ocijail", + }) + c.RuntimeSupportsNoCgroups.Set([]string{"crun", "krun"}) + c.RuntimeSupportsKVM.Set([]string{"kata", "kata-runtime", "kata-qemu", "kata-fc", "krun"}) c.NoPivotRoot = false c.InfraImage = DefaultInfraImage @@ -478,42 +528,42 @@ func (c *Config) SecurityOptions() []string { // Sysctls returns the default sysctls to set in containers. func (c *Config) Sysctls() []string { - return c.Containers.DefaultSysctls + return c.Containers.DefaultSysctls.Get() } // Volumes returns the default set of volumes that should be mounted in containers. func (c *Config) Volumes() []string { - return c.Containers.Volumes + return c.Containers.Volumes.Get() +} + +// Mounts returns the default set of mounts that should be mounted in containers. +func (c *Config) Mounts() []string { + return c.Containers.Mounts.Get() } // Devices returns the default additional devices for containers. func (c *Config) Devices() []string { - return c.Containers.Devices + return c.Containers.Devices.Get() } // DNSServers returns the default DNS servers to add to resolv.conf in containers. func (c *Config) DNSServers() []string { - return c.Containers.DNSServers + return c.Containers.DNSServers.Get() } // DNSSerches returns the default DNS searches to add to resolv.conf in containers. func (c *Config) DNSSearches() []string { - return c.Containers.DNSSearches + return c.Containers.DNSSearches.Get() } // DNSOptions returns the default DNS options to add to resolv.conf in containers. func (c *Config) DNSOptions() []string { - return c.Containers.DNSOptions + return c.Containers.DNSOptions.Get() } // Env returns the default additional environment variables to add to containers. func (c *Config) Env() []string { - return c.Containers.Env -} - -// InitPath returns location where init program added to containers when users specify the --init flag. -func (c *Config) InitPath() string { - return c.Containers.InitPath + return c.Containers.Env.Get() } // IPCNS returns the default IPC Namespace configuration to run containers with. @@ -548,7 +598,7 @@ func (c *Config) ShmSize() string { // Ulimits returns the default ulimits to use in containers. func (c *Config) Ulimits() []string { - return c.Containers.DefaultUlimits + return c.Containers.DefaultUlimits.Get() } // PidsLimit returns the default maximum number of pids to use in containers. @@ -593,7 +643,7 @@ func (c *Config) MachineEnabled() bool { // MachineVolumes returns volumes to mount into the VM. func (c *Config) MachineVolumes() ([]string, error) { - return machineVolumes(c.Machine.Volumes) + return machineVolumes(c.Machine.Volumes.Get()) } func machineVolumes(volumes []string) ([]string, error) { @@ -625,3 +675,16 @@ func useUserConfigLocations() bool { // GetRootlessUID == -1 on Windows, so exclude negative range return unshare.GetRootlessUID() > 0 } + +// getDefaultImage returns the default machine image stream +// On Windows this refers to the Fedora major release number +func getDefaultMachineImage() string { + return "testing" +} + +// getDefaultMachineUser returns the user to use for rootless podman +// This is only for the apple, hyperv, and qemu implementations. +// WSL's user will be hardcoded in podman to "user" +func getDefaultMachineUser() string { + return "core" +} diff --git a/vendor/github.com/containers/common/pkg/config/default_darwin.go b/vendor/github.com/containers/common/pkg/config/default_darwin.go index 75576662096..86fa6d5087d 100644 --- a/vendor/github.com/containers/common/pkg/config/default_darwin.go +++ b/vendor/github.com/containers/common/pkg/config/default_darwin.go @@ -20,3 +20,14 @@ func getDefaultMachineVolumes() []string { "/var/folders:/var/folders", } } + +func getDefaultComposeProviders() []string { + return []string{ + "docker-compose", + "$HOME/.docker/cli-plugins/docker-compose", + "/opt/homebrew/bin/docker-compose", + "/usr/local/bin/docker-compose", + "/Applications/Docker.app/Contents/Resources/cli-plugins/docker-compose", + "podman-compose", + } +} diff --git a/vendor/github.com/containers/common/pkg/config/default_freebsd.go b/vendor/github.com/containers/common/pkg/config/default_freebsd.go index 637abf9811f..1110edd03d7 100644 --- a/vendor/github.com/containers/common/pkg/config/default_freebsd.go +++ b/vendor/github.com/containers/common/pkg/config/default_freebsd.go @@ -26,3 +26,7 @@ func getLibpodTmpDir() string { func getDefaultMachineVolumes() []string { return []string{"$HOME:$HOME"} } + +func getDefaultComposeProviders() []string { + return defaultUnixComposeProviders +} diff --git a/vendor/github.com/containers/common/pkg/config/default_linux.go b/vendor/github.com/containers/common/pkg/config/default_linux.go index d4d04764a14..9e2ae4796b3 100644 --- a/vendor/github.com/containers/common/pkg/config/default_linux.go +++ b/vendor/github.com/containers/common/pkg/config/default_linux.go @@ -17,17 +17,6 @@ func getDefaultCgroupsMode() string { return "enabled" } -// getDefaultMachineImage returns the default machine image stream -// On Linux/Mac, this returns the FCOS stream -func getDefaultMachineImage() string { - return "testing" -} - -// getDefaultMachineUser returns the user to use for rootless podman -func getDefaultMachineUser() string { - return "core" -} - // getDefaultProcessLimits returns the nproc for the current process in ulimits format // Note that nfile sometimes cannot be set to unlimited, and the limit is hardcoded // to (oldMaxSize) 1048576 (2^20), see: http://stackoverflow.com/a/1213069/1811501 @@ -41,7 +30,7 @@ func getDefaultProcessLimits() []string { val := strings.TrimSuffix(string(dat), "\n") max, err := strconv.ParseUint(val, 10, 64) if err == nil { - rlim = unix.Rlimit{Cur: uint64(max), Max: uint64(max)} + rlim = unix.Rlimit{Cur: max, Max: max} } } defaultLimits := []string{} @@ -74,3 +63,7 @@ func getLibpodTmpDir() string { func getDefaultMachineVolumes() []string { return []string{"$HOME:$HOME"} } + +func getDefaultComposeProviders() []string { + return defaultUnixComposeProviders +} diff --git a/vendor/github.com/containers/common/pkg/config/default_unsupported.go b/vendor/github.com/containers/common/pkg/config/default_unsupported.go index 4be8267558d..0d427a05420 100644 --- a/vendor/github.com/containers/common/pkg/config/default_unsupported.go +++ b/vendor/github.com/containers/common/pkg/config/default_unsupported.go @@ -5,17 +5,6 @@ package config import "os" -// getDefaultMachineImage returns the default machine image stream -// On Linux/Mac, this returns the FCOS stream -func getDefaultMachineImage() string { - return "testing" -} - -// getDefaultMachineUser returns the user to use for rootless podman -func getDefaultMachineUser() string { - return "core" -} - // isCgroup2UnifiedMode returns whether we are running in cgroup2 mode. func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) { return false, nil diff --git a/vendor/github.com/containers/common/pkg/config/default_windows.go b/vendor/github.com/containers/common/pkg/config/default_windows.go index 08a0bf22395..4f1362bd284 100644 --- a/vendor/github.com/containers/common/pkg/config/default_windows.go +++ b/vendor/github.com/containers/common/pkg/config/default_windows.go @@ -2,17 +2,6 @@ package config import "os" -// getDefaultImage returns the default machine image stream -// On Windows this refers to the Fedora major release number -func getDefaultMachineImage() string { - return "35" -} - -// getDefaultMachineUser returns the user to use for rootless podman -func getDefaultMachineUser() string { - return "user" -} - // isCgroup2UnifiedMode returns whether we are running in cgroup2 mode. func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) { return false, nil @@ -49,3 +38,8 @@ func getLibpodTmpDir() string { func getDefaultMachineVolumes() []string { return []string{} } + +func getDefaultComposeProviders() []string { + // Rely on os.LookPath to do the trick on Windows. + return []string{"docker-compose", "podman-compose"} +} diff --git a/vendor/github.com/containers/common/pkg/config/modules.go b/vendor/github.com/containers/common/pkg/config/modules.go new file mode 100644 index 00000000000..f21671f6b1d --- /dev/null +++ b/vendor/github.com/containers/common/pkg/config/modules.go @@ -0,0 +1,95 @@ +package config + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/containers/storage/pkg/homedir" + "github.com/containers/storage/pkg/unshare" + "github.com/hashicorp/go-multierror" +) + +// The subdirectory for looking up containers.conf modules. +const moduleSubdir = "containers/containers.conf.modules" + +// Moving the base paths into variables allows for overriding them in units +// tests. +var ( + moduleBaseEtc = "/etc/" + moduleBaseUsr = "/usr/share" +) + +// LoadedModules returns absolute paths to loaded containers.conf modules. +func (c *Config) LoadedModules() []string { + // Required for conmon's callback to Podman's cleanup. + // Absolute paths make loading the modules a bit faster. + return c.loadedModules +} + +// Find the specified modules in the options. Return an error if a specific +// module cannot be located on the host. +func (o *Options) modules() ([]string, error) { + if len(o.Modules) == 0 { + return nil, nil + } + + dirs, err := ModuleDirectories() + if err != nil { + return nil, err + } + + configs := make([]string, 0, len(o.Modules)) + for _, path := range o.Modules { + resolved, err := resolveModule(path, dirs) + if err != nil { + return nil, fmt.Errorf("could not resolve module %q: %w", path, err) + } + configs = append(configs, resolved) + } + + return configs, nil +} + +// ModuleDirectories return the directories to load modules from: +// 1) XDG_CONFIG_HOME/HOME if rootless +// 2) /etc/ +// 3) /usr/share +func ModuleDirectories() ([]string, error) { // Public API for shell completions in Podman + modules := []string{ + filepath.Join(moduleBaseEtc, moduleSubdir), + filepath.Join(moduleBaseUsr, moduleSubdir), + } + + if !unshare.IsRootless() { + return modules, nil + } + + // Prepend the user modules dir. + configHome, err := homedir.GetConfigHome() + if err != nil { + return nil, err + } + return append([]string{filepath.Join(configHome, moduleSubdir)}, modules...), nil +} + +// Resolve the specified path to a module. +func resolveModule(path string, dirs []string) (string, error) { + if filepath.IsAbs(path) { + _, err := os.Stat(path) + return path, err + } + + // Collect all errors to avoid suppressing important errors (e.g., + // permission errors). + var multiErr error + for _, d := range dirs { + candidate := filepath.Join(d, path) + _, err := os.Stat(candidate) + if err == nil { + return candidate, nil + } + multiErr = multierror.Append(multiErr, err) + } + return "", multiErr +} diff --git a/vendor/github.com/containers/common/pkg/config/new.go b/vendor/github.com/containers/common/pkg/config/new.go new file mode 100644 index 00000000000..64ddf471661 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/config/new.go @@ -0,0 +1,240 @@ +package config + +import ( + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + "sort" + "strings" + "sync" + + "github.com/BurntSushi/toml" + "github.com/sirupsen/logrus" +) + +var ( + cachedConfigError error + cachedConfigMutex sync.Mutex + cachedConfig *Config +) + +const ( + // FIXME: update code base and tests to use the two constants below. + containersConfEnv = "CONTAINERS_CONF" + containersConfOverrideEnv = containersConfEnv + "_OVERRIDE" +) + +// Options to use when loading a Config via New(). +type Options struct { + // Attempt to load the following config modules. + Modules []string + + // Set the loaded config as the default one which can later on be + // accessed via Default(). + SetDefault bool + + // Additional configs to load. An internal only field to make the + // behavior observable and testable in unit tests. + additionalConfigs []string +} + +// New returns a Config as described in the containers.conf(5) man page. +func New(options *Options) (*Config, error) { + if options == nil { + options = &Options{} + } else if options.SetDefault { + cachedConfigMutex.Lock() + defer cachedConfigMutex.Unlock() + } + return newLocked(options) +} + +// Default returns the default container config. If no default config has been +// set yet, a new config will be loaded by New() and set as the default one. +// All callers are expected to use the returned Config read only. Changing +// data may impact other call sites. +func Default() (*Config, error) { + cachedConfigMutex.Lock() + defer cachedConfigMutex.Unlock() + if cachedConfig != nil || cachedConfigError != nil { + return cachedConfig, cachedConfigError + } + cachedConfig, cachedConfigError = newLocked(&Options{SetDefault: true}) + return cachedConfig, cachedConfigError +} + +// A helper function for New() expecting the caller to hold the +// cachedConfigMutex if options.SetDefault is set.. +func newLocked(options *Options) (*Config, error) { + // Start with the built-in defaults + config, err := defaultConfig() + if err != nil { + return nil, err + } + + // Now, gather the system configs and merge them as needed. + configs, err := systemConfigs() + if err != nil { + return nil, fmt.Errorf("finding config on system: %w", err) + } + for _, path := range configs { + // Merge changes in later configs with the previous configs. + // Each config file that specified fields, will override the + // previous fields. + if err = readConfigFromFile(path, config); err != nil { + return nil, fmt.Errorf("reading system config %q: %w", path, err) + } + logrus.Debugf("Merged system config %q", path) + logrus.Tracef("%+v", config) + } + + modules, err := options.modules() + if err != nil { + return nil, err + } + config.loadedModules = modules + + options.additionalConfigs = append(options.additionalConfigs, modules...) + + // The _OVERRIDE variable _must_ always win. That's a contract we need + // to honor (for the Podman CI). + if path := os.Getenv(containersConfOverrideEnv); path != "" { + if _, err := os.Stat(path); err != nil { + return nil, fmt.Errorf("%s file: %w", containersConfOverrideEnv, err) + } + options.additionalConfigs = append(options.additionalConfigs, path) + } + + // If the caller specified a config path to use, then we read it to + // override the system defaults. + for _, add := range options.additionalConfigs { + if add == "" { + continue + } + // readConfigFromFile reads in container config in the specified + // file and then merge changes with the current default. + if err := readConfigFromFile(add, config); err != nil { + return nil, fmt.Errorf("reading additional config %q: %w", add, err) + } + logrus.Debugf("Merged additional config %q", add) + logrus.Tracef("%+v", config) + } + config.addCAPPrefix() + + if err := config.Validate(); err != nil { + return nil, err + } + + if err := config.setupEnv(); err != nil { + return nil, err + } + + if options.SetDefault { + cachedConfig = config + cachedConfigError = nil + } + + return config, nil +} + +// NewConfig creates a new Config. It starts with an empty config and, if +// specified, merges the config at `userConfigPath` path. +// +// Deprecated: use new instead. +func NewConfig(userConfigPath string) (*Config, error) { + return New(&Options{additionalConfigs: []string{userConfigPath}}) +} + +// Returns the list of configuration files, if they exist in order of hierarchy. +// The files are read in order and each new file can/will override previous +// file settings. +func systemConfigs() (configs []string, finalErr error) { + if path := os.Getenv(containersConfEnv); path != "" { + if _, err := os.Stat(path); err != nil { + return nil, fmt.Errorf("%s file: %w", containersConfEnv, err) + } + return append(configs, path), nil + } + if _, err := os.Stat(DefaultContainersConfig); err == nil { + configs = append(configs, DefaultContainersConfig) + } + if _, err := os.Stat(OverrideContainersConfig); err == nil { + configs = append(configs, OverrideContainersConfig) + } + + var err error + configs, err = addConfigs(OverrideContainersConfig+".d", configs) + if err != nil { + return nil, err + } + + path, err := ifRootlessConfigPath() + if err != nil { + return nil, err + } + if path != "" { + if _, err := os.Stat(path); err == nil { + configs = append(configs, path) + } + configs, err = addConfigs(path+".d", configs) + if err != nil { + return nil, err + } + } + return configs, nil +} + +// addConfigs will search one level in the config dirPath for config files +// If the dirPath does not exist, addConfigs will return nil +func addConfigs(dirPath string, configs []string) ([]string, error) { + newConfigs := []string{} + + err := filepath.WalkDir(dirPath, + // WalkFunc to read additional configs + func(path string, d fs.DirEntry, err error) error { + switch { + case err != nil: + // return error (could be a permission problem) + return err + case d.IsDir(): + if path != dirPath { + // make sure to not recurse into sub-directories + return filepath.SkipDir + } + // ignore directories + return nil + default: + // only add *.conf files + if strings.HasSuffix(path, ".conf") { + newConfigs = append(newConfigs, path) + } + return nil + } + }, + ) + if errors.Is(err, os.ErrNotExist) { + err = nil + } + sort.Strings(newConfigs) + return append(configs, newConfigs...), err +} + +// readConfigFromFile reads the specified config file at `path` and attempts to +// unmarshal its content into a Config. The config param specifies the previous +// default config. If the path, only specifies a few fields in the Toml file +// the defaults from the config parameter will be used for all other fields. +func readConfigFromFile(path string, config *Config) error { + logrus.Tracef("Reading configuration file %q", path) + meta, err := toml.DecodeFile(path, config) + if err != nil { + return fmt.Errorf("decode configuration %v: %w", path, err) + } + keys := meta.Undecoded() + if len(keys) > 0 { + logrus.Debugf("Failed to decode the keys %q from %q.", keys, path) + } + + return nil +} diff --git a/vendor/github.com/containers/common/pkg/filters/filters.go b/vendor/github.com/containers/common/pkg/filters/filters.go index 729061dbcad..3d442a53069 100644 --- a/vendor/github.com/containers/common/pkg/filters/filters.go +++ b/vendor/github.com/containers/common/pkg/filters/filters.go @@ -5,9 +5,11 @@ import ( "fmt" "net/http" "path/filepath" + "regexp" "strings" "time" + "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/timetype" ) @@ -105,13 +107,7 @@ func PrepareFilters(r *http.Request) (map[string][]string, error) { func MatchLabelFilters(filterValues []string, labels map[string]string) bool { outer: for _, filterValue := range filterValues { - filterArray := strings.SplitN(filterValue, "=", 2) - filterKey := filterArray[0] - if len(filterArray) > 1 { - filterValue = filterArray[1] - } else { - filterValue = "" - } + filterKey, filterValue := splitFilterValue(filterValue) for labelKey, labelValue := range labels { if filterValue == "" || labelValue == filterValue { if labelKey == filterKey || matchPattern(filterKey, labelKey) { @@ -124,6 +120,32 @@ outer: return true } +// MatchNegatedLabelFilters matches negated labels and returns true if they are valid +func MatchNegatedLabelFilters(filterValues []string, labels map[string]string) bool { + for _, filterValue := range filterValues { + filterKey, filterValue := splitFilterValue(filterValue) + for labelKey, labelValue := range labels { + if filterValue == "" || labelValue == filterValue { + if labelKey == filterKey || matchPattern(filterKey, labelKey) { + return false + } + } + } + } + return true +} + +func splitFilterValue(filterValue string) (string, string) { + filterArray := strings.SplitN(filterValue, "=", 2) + filterKey := filterArray[0] + if len(filterArray) > 1 { + filterValue = filterArray[1] + } else { + filterValue = "" + } + return filterKey, filterValue +} + func matchPattern(pattern string, value string) bool { if strings.Contains(pattern, "*") { filter := fmt.Sprintf("*%s*", pattern) @@ -134,3 +156,22 @@ func matchPattern(pattern string, value string) bool { } return false } + +// FilterID is a function used to compare an id against a set of ids, if the +// input is hex we check if the prefix matches. Otherwise we assume it is a +// regex and try to match that. +// see https://github.com/containers/podman/issues/18471 for why we do this +func FilterID(id string, filters []string) bool { + for _, want := range filters { + isRegex := types.NotHexRegex.MatchString(want) + if isRegex { + match, err := regexp.MatchString(want, id) + if err == nil && match { + return true + } + } else if strings.HasPrefix(id, strings.ToLower(want)) { + return true + } + } + return false +} diff --git a/vendor/github.com/containers/common/pkg/flag/flag.go b/vendor/github.com/containers/common/pkg/flag/flag.go index 7d6b6a5343d..a8e3cc725d8 100644 --- a/vendor/github.com/containers/common/pkg/flag/flag.go +++ b/vendor/github.com/containers/common/pkg/flag/flag.go @@ -165,7 +165,7 @@ func (ob *optionalIntValue) String() string { if !ob.present { return "" // If the value is not present, just return an empty string, any other value wouldn't make sense. } - return strconv.Itoa(int(ob.value)) + return strconv.Itoa(ob.value) } // Type returns the int's type. diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go index 5cf311b4369..d47e47e1010 100644 --- a/vendor/github.com/containers/common/pkg/retry/retry.go +++ b/vendor/github.com/containers/common/pkg/retry/retry.go @@ -74,7 +74,6 @@ func IsErrorRetryable(err error) bool { } switch e := err.(type) { - case errcode.Error: switch e.Code { case errcode.ErrorCodeUnauthorized, errcode.ErrorCodeDenied, diff --git a/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go b/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go index 6068b2081f7..3054a2bb5a7 100644 --- a/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go +++ b/vendor/github.com/containers/common/pkg/secrets/filedriver/filedriver.go @@ -150,7 +150,7 @@ func (d *Driver) getAllData() (map[string][]byte, error) { return nil, err } secretData := new(map[string][]byte) - err = json.Unmarshal([]byte(byteValue), secretData) + err = json.Unmarshal(byteValue, secretData) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/common/pkg/secrets/secrets.go b/vendor/github.com/containers/common/pkg/secrets/secrets.go index 61ab9be9868..47e68840626 100644 --- a/vendor/github.com/containers/common/pkg/secrets/secrets.go +++ b/vendor/github.com/containers/common/pkg/secrets/secrets.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "path/filepath" - "strings" "time" "github.com/containers/common/pkg/secrets/filedriver" @@ -50,8 +49,8 @@ var errDataSize = errors.New("secret data must be larger than 0 and less than 51 var secretsFile = "secrets.json" // secretNameRegexp matches valid secret names -// Allowed: 253 [a-zA-Z0-9-_.] characters, and the start and end character must be [a-zA-Z0-9] -var secretNameRegexp = regexp.Delayed(`^[a-zA-Z0-9][a-zA-Z0-9_.-]*$`) +// Allowed: 253 characters, excluding ,/=\0 +var secretNameRegexp = regexp.Delayed("^[^,/=\000]+$") // SecretsManager holds information on handling secrets // @@ -217,9 +216,12 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti } if options.Replace { - err = driver.Delete(secr.ID) - if err != nil { - return "", fmt.Errorf("replacing secret %s: %w", name, err) + if err := driver.Delete(secr.ID); err != nil { + return "", fmt.Errorf("deleting secret %s: %w", secr.ID, err) + } + + if err := s.delete(secr.ID); err != nil { + return "", fmt.Errorf("deleting secret %s: %w", secr.ID, err) } } @@ -244,11 +246,6 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti // Delete removes all secret metadata and secret data associated with the specified secret. // Delete takes a name, ID, or partial ID. func (s *SecretsManager) Delete(nameOrID string) (string, error) { - err := validateSecretName(nameOrID) - if err != nil { - return "", err - } - s.lockfile.Lock() defer s.lockfile.Unlock() @@ -322,8 +319,10 @@ func (s *SecretsManager) LookupSecretData(nameOrID string) (*Secret, []byte, err // validateSecretName checks if the secret name is valid. func validateSecretName(name string) error { - if !secretNameRegexp.MatchString(name) || len(name) > 253 || strings.HasSuffix(name, "-") || strings.HasSuffix(name, ".") { - return fmt.Errorf("only 253 [a-zA-Z0-9-_.] characters allowed, and the start and end character must be [a-zA-Z0-9]: %s: %w", name, errInvalidSecretName) + if len(name) == 0 || + len(name) > 253 || + !secretNameRegexp.MatchString(name) { + return fmt.Errorf("secret name %q can not include '=', '/', ',', or the '\\0' (NULL) and be between 1 and 253 characters: %w", name, errInvalidSecretName) } return nil } diff --git a/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go b/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go index 87dc317a98f..c903ca7491b 100644 --- a/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go +++ b/vendor/github.com/containers/common/pkg/secrets/shelldriver/shelldriver.go @@ -58,7 +58,6 @@ func (cfg *driverConfig) ParseOpts(opts map[string]string) error { cfg.ListCommand == "" || cfg.LookupCommand == "" || cfg.StoreCommand == "" { - return errMissingConfig } return nil diff --git a/vendor/github.com/containers/common/pkg/ssh/connection_golang.go b/vendor/github.com/containers/common/pkg/ssh/connection_golang.go index b9c464478d2..1abb5802cd8 100644 --- a/vendor/github.com/containers/common/pkg/ssh/connection_golang.go +++ b/vendor/github.com/containers/common/pkg/ssh/connection_golang.go @@ -28,7 +28,7 @@ import ( func golangConnectionCreate(options ConnectionCreateOptions) error { var match bool var err error - if match, err = regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(options.Path)); err != nil { + if match, err = regexp.MatchString("^[A-Za-z][A-Za-z0-9+.-]*://", options.Path); err != nil { return fmt.Errorf("invalid destination: %w", err) } @@ -64,6 +64,19 @@ func golangConnectionCreate(options ConnectionCreateOptions) error { } else { cfg.Engine.ServiceDestinations[options.Name] = *dst } + + // Create or update an existing farm with the connection being added + if options.Farm != "" { + if len(cfg.Farms.List) == 0 { + cfg.Farms.Default = options.Farm + } + if val, ok := cfg.Farms.List[options.Farm]; ok { + cfg.Farms.List[options.Farm] = append(val, options.Name) + } else { + cfg.Farms.List[options.Farm] = []string{options.Name} + } + } + return cfg.Write() } @@ -216,7 +229,7 @@ func GetUserInfo(uri *url.URL) (*url.Userinfo, error) { } // ValidateAndConfigure will take a ssh url and an identity key (rsa and the like) and ensure the information given is valid -// iden iden can be blank to mean no identity key +// iden can be blank to mean no identity key // once the function validates the information it creates and returns an ssh.ClientConfig. func ValidateAndConfigure(uri *url.URL, iden string, insecureIsMachineConnection bool) (*ssh.ClientConfig, error) { var signers []ssh.Signer diff --git a/vendor/github.com/containers/common/pkg/ssh/connection_native.go b/vendor/github.com/containers/common/pkg/ssh/connection_native.go index 4c407360a3d..c725cb27da7 100644 --- a/vendor/github.com/containers/common/pkg/ssh/connection_native.go +++ b/vendor/github.com/containers/common/pkg/ssh/connection_native.go @@ -14,7 +14,7 @@ import ( func nativeConnectionCreate(options ConnectionCreateOptions) error { var match bool var err error - if match, err = regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(options.Path)); err != nil { + if match, err = regexp.MatchString("^[A-Za-z][A-Za-z0-9+.-]*://", options.Path); err != nil { return fmt.Errorf("invalid destination: %w", err) } diff --git a/vendor/github.com/containers/common/pkg/ssh/types.go b/vendor/github.com/containers/common/pkg/ssh/types.go index 16512c43f17..600655931d6 100644 --- a/vendor/github.com/containers/common/pkg/ssh/types.go +++ b/vendor/github.com/containers/common/pkg/ssh/types.go @@ -24,6 +24,7 @@ type ConnectionCreateOptions struct { Identity string Socket string Default bool + Farm string } type ConnectionDialOptions struct { diff --git a/vendor/github.com/containers/common/pkg/ssh/utils.go b/vendor/github.com/containers/common/pkg/ssh/utils.go index d2b7d4a0289..d47a9859c03 100644 --- a/vendor/github.com/containers/common/pkg/ssh/utils.go +++ b/vendor/github.com/containers/common/pkg/ssh/utils.go @@ -15,11 +15,9 @@ import ( "golang.org/x/term" ) +const sshdPort = 22 + func Validate(user *url.Userinfo, path string, port int, identity string) (*config.Destination, *url.URL, error) { - sock := "" - if strings.Contains(path, "/run") { - sock = strings.Split(path, "/run")[1] - } // url.Parse NEEDS ssh://, if this ever fails or returns some nonsense, that is why. uri, err := url.Parse(path) if err != nil { @@ -32,26 +30,18 @@ func Validate(user *url.Userinfo, path string, port int, identity string) (*conf } if uri.Port() == "" { - if port != 0 { - uri.Host = net.JoinHostPort(uri.Host, strconv.Itoa(port)) - } else { - uri.Host = net.JoinHostPort(uri.Host, "22") + if port == 0 { + port = sshdPort } + uri.Host = net.JoinHostPort(uri.Host, strconv.Itoa(port)) } if user != nil { uri.User = user } - uriStr := "" - if len(sock) > 0 { - uriStr = "ssh://" + uri.User.Username() + "@" + uri.Host + "/run" + sock - } else { - uriStr = "ssh://" + uri.User.Username() + "@" + uri.Host - } - dst := config.Destination{ - URI: uriStr, + URI: uri.String(), } if len(identity) > 0 { @@ -155,7 +145,7 @@ func ParseScpArgs(options ConnectionScpOptions) (string, string, string, bool, e if strings.Contains(localPath, "ssh://") { localPath = strings.Split(localPath, "ssh://")[1] } - remotePath := "" + var remotePath string swap := false if split := strings.Split(localPath, ":"); len(split) == 2 { // save to remote, load to local @@ -176,11 +166,15 @@ func ParseScpArgs(options ConnectionScpOptions) (string, string, string, bool, e } func DialNet(sshClient *ssh.Client, mode string, url *url.URL) (net.Conn, error) { - port, err := strconv.Atoi(url.Port()) - if err != nil { - return nil, err + port := sshdPort + if url.Port() != "" { + p, err := strconv.Atoi(url.Port()) + if err != nil { + return nil, err + } + port = p } - if _, _, err = Validate(url.User, url.Hostname(), port, ""); err != nil { + if _, _, err := Validate(url.User, url.Hostname(), port, ""); err != nil { return nil, err } return sshClient.Dial(mode, url.Path) diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go index b751f487724..6ba2154a779 100644 --- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go +++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go @@ -242,7 +242,6 @@ func addSubscriptionsFromMountsFile(filePath, mountLabel, containerRunDir string // In the event of a restart, don't want to copy subscriptions over again as they already would exist in ctrDirOrFileOnHost _, err = os.Stat(ctrDirOrFileOnHost) if errors.Is(err, os.ErrNotExist) { - hostDirOrFile, err = resolveSymbolicLink(hostDirOrFile) if err != nil { return nil, err @@ -363,6 +362,35 @@ func addFIPSModeSubscription(mounts *[]rspec.Mount, containerRunDir, mountPoint, } *mounts = append(*mounts, m) } + + // Make sure we set the config to FIPS so that the container does not overwrite + // /etc/crypto-policies/back-ends when crypto-policies-scripts is reinstalled. + cryptoPoliciesConfigFile := filepath.Join(containerRunDir, "fips-config") + file, err := os.Create(cryptoPoliciesConfigFile) + if err != nil { + return fmt.Errorf("creating fips config file in container for FIPS mode: %w", err) + } + defer file.Close() + if _, err := file.WriteString("FIPS\n"); err != nil { + return fmt.Errorf("writing fips config file in container for FIPS mode: %w", err) + } + if err = label.Relabel(cryptoPoliciesConfigFile, mountLabel, false); err != nil { + return fmt.Errorf("applying correct labels on fips-config file: %w", err) + } + if err := file.Chown(uid, gid); err != nil { + return fmt.Errorf("chown fips-config file: %w", err) + } + + policyConfig := "/etc/crypto-policies/config" + if !mountExists(*mounts, policyConfig) { + m := rspec.Mount{ + Source: cryptoPoliciesConfigFile, + Destination: policyConfig, + Type: "bind", + Options: []string{"bind", "rprivate"}, + } + *mounts = append(*mounts, m) + } return nil } diff --git a/vendor/github.com/containers/common/pkg/util/copy.go b/vendor/github.com/containers/common/pkg/util/copy.go deleted file mode 100644 index a45b82fc94c..00000000000 --- a/vendor/github.com/containers/common/pkg/util/copy.go +++ /dev/null @@ -1,57 +0,0 @@ -package util - -import ( - "errors" - "io" -) - -// ErrDetach indicates that an attach session was manually detached by -// the user. -var ErrDetach = errors.New("detached from container") - -// CopyDetachable is similar to io.Copy but support a detach key sequence to break out. -func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, err error) { - buf := make([]byte, 32*1024) - for { - nr, er := src.Read(buf) - if nr > 0 { - preservBuf := []byte{} - for i, key := range keys { - preservBuf = append(preservBuf, buf[0:nr]...) - if nr != 1 || buf[0] != key { - break - } - if i == len(keys)-1 { - return 0, ErrDetach - } - nr, er = src.Read(buf) - } - var nw int - var ew error - if len(preservBuf) > 0 { - nw, ew = dst.Write(preservBuf) - nr = len(preservBuf) - } else { - nw, ew = dst.Write(buf[0:nr]) - } - if nw > 0 { - written += int64(nw) - } - if ew != nil { - err = ew - break - } - if nr != nw { - err = io.ErrShortWrite - break - } - } - if er != nil { - if er != io.EOF { - err = er - } - break - } - } - return written, err -} diff --git a/vendor/github.com/containers/common/pkg/util/util.go b/vendor/github.com/containers/common/pkg/util/util.go index e396f0fc086..708472bac29 100644 --- a/vendor/github.com/containers/common/pkg/util/util.go +++ b/vendor/github.com/containers/common/pkg/util/util.go @@ -1,102 +1,16 @@ package util import ( - "bytes" "fmt" "os" - "os/exec" "path/filepath" "regexp" - "strings" "time" - "github.com/containers/common/libnetwork/types" "github.com/fsnotify/fsnotify" "github.com/sirupsen/logrus" ) -const ( - UnknownPackage = "Unknown" -) - -// Note: This function is copied from containers/podman libpod/util.go -// Please see https://github.com/containers/common/pull/1460 -func queryPackageVersion(cmdArg ...string) string { - output := UnknownPackage - if 1 < len(cmdArg) { - cmd := exec.Command(cmdArg[0], cmdArg[1:]...) - if outp, err := cmd.Output(); err == nil { - output = string(outp) - if cmdArg[0] == "/usr/bin/dpkg" { - r := strings.Split(output, ": ") - queryFormat := `${Package}_${Version}_${Architecture}` - cmd = exec.Command("/usr/bin/dpkg-query", "-f", queryFormat, "-W", r[0]) - if outp, err := cmd.Output(); err == nil { - output = string(outp) - } - } - } - if cmdArg[0] == "/sbin/apk" { - prefix := cmdArg[len(cmdArg)-1] + " is owned by " - output = strings.Replace(output, prefix, "", 1) - } - } - return strings.Trim(output, "\n") -} - -// Note: This function is copied from containers/podman libpod/util.go -// Please see https://github.com/containers/common/pull/1460 -func PackageVersion(program string) string { // program is full path - packagers := [][]string{ - {"/usr/bin/rpm", "-q", "-f"}, - {"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu - {"/usr/bin/pacman", "-Qo"}, // Arch - {"/usr/bin/qfile", "-qv"}, // Gentoo (quick) - {"/usr/bin/equery", "b"}, // Gentoo (slow) - {"/sbin/apk", "info", "-W"}, // Alpine - {"/usr/local/sbin/pkg", "which", "-q"}, // FreeBSD - } - - for _, cmd := range packagers { - cmd = append(cmd, program) - if out := queryPackageVersion(cmd...); out != UnknownPackage { - return out - } - } - return UnknownPackage -} - -// Note: This function is copied from containers/podman libpod/util.go -// Please see https://github.com/containers/common/pull/1460 -func ProgramVersion(program string) (string, error) { - return programVersion(program, false) -} - -func ProgramVersionDnsname(program string) (string, error) { - return programVersion(program, true) -} - -func programVersion(program string, dnsname bool) (string, error) { - cmd := exec.Command(program, "--version") - var stdout bytes.Buffer - var stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - - err := cmd.Run() - if err != nil { - return "", fmt.Errorf("`%v --version` failed: %v %v (%v)", program, stderr.String(), stdout.String(), err) - } - - output := strings.TrimSuffix(stdout.String(), "\n") - // dnsname --version returns the information to stderr - if dnsname { - output = strings.TrimSuffix(stderr.String(), "\n") - } - - return output, nil -} - // StringInSlice determines if a string is in a string slice, returns bool func StringInSlice(s string, sl []string) bool { for _, i := range sl { @@ -118,25 +32,6 @@ func StringMatchRegexSlice(s string, re []string) bool { return false } -// FilterID is a function used to compare an id against a set of ids, if the -// input is hex we check if the prefix matches. Otherwise we assume it is a -// regex and try to match that. -// see https://github.com/containers/podman/issues/18471 for why we do this -func FilterID(id string, filters []string) bool { - for _, want := range filters { - isRegex := types.NotHexRegex.MatchString(want) - if isRegex { - match, err := regexp.MatchString(want, id) - if err == nil && match { - return true - } - } else if strings.HasPrefix(id, strings.ToLower(want)) { - return true - } - } - return false -} - // WaitForFile waits until a file has been created or the given timeout has occurred func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, error) { var inotifyEvents chan fsnotify.Event diff --git a/vendor/github.com/containers/common/pkg/version/version.go b/vendor/github.com/containers/common/pkg/version/version.go new file mode 100644 index 00000000000..0d830060113 --- /dev/null +++ b/vendor/github.com/containers/common/pkg/version/version.go @@ -0,0 +1,105 @@ +package version + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "strings" +) + +const ( + UnknownPackage = "Unknown" +) + +// Note: This function is copied from containers/podman libpod/util.go +// Please see https://github.com/containers/common/pull/1460 +func queryPackageVersion(cmdArg ...string) string { + output := UnknownPackage + if 1 < len(cmdArg) { + cmd := exec.Command(cmdArg[0], cmdArg[1:]...) + if outp, err := cmd.Output(); err == nil { + output = string(outp) + deb := false + if cmdArg[0] == "/usr/bin/dlocate" { + // can return multiple matches + l := strings.Split(output, "\n") + output = l[0] + deb = true + } else if cmdArg[0] == "/usr/bin/dpkg" { + deb = true + } + if deb { + r := strings.Split(output, ": ") + queryFormat := `${Package}_${Version}_${Architecture}` + cmd = exec.Command("/usr/bin/dpkg-query", "-f", queryFormat, "-W", r[0]) + if outp, err := cmd.Output(); err == nil { + output = string(outp) + } + } + } + if cmdArg[0] == "/sbin/apk" { + prefix := cmdArg[len(cmdArg)-1] + " is owned by " + output = strings.Replace(output, prefix, "", 1) + } + } + return strings.Trim(output, "\n") +} + +// Note: This function is copied from containers/podman libpod/util.go +// Please see https://github.com/containers/common/pull/1460 +func Package(program string) string { // program is full path + _, err := os.Stat(program) + if err != nil { + return UnknownPackage + } + packagers := [][]string{ + {"/usr/bin/rpm", "-q", "-f"}, + {"/usr/bin/dlocate", "-F"}, // Debian, Ubuntu (quick) + {"/usr/bin/dpkg", "-S"}, // Debian, Ubuntu (slow) + {"/usr/bin/pacman", "-Qo"}, // Arch + {"/usr/bin/qfile", "-qv"}, // Gentoo (quick) + {"/usr/bin/equery", "b"}, // Gentoo (slow) + {"/sbin/apk", "info", "-W"}, // Alpine + {"/usr/local/sbin/pkg", "which", "-q"}, // FreeBSD + } + + for _, cmd := range packagers { + cmd = append(cmd, program) + if out := queryPackageVersion(cmd...); out != UnknownPackage { + return out + } + } + return UnknownPackage +} + +// Note: This function is copied from containers/podman libpod/util.go +// Please see https://github.com/containers/common/pull/1460 +func Program(name string) (string, error) { + return program(name, false) +} + +func ProgramDnsname(name string) (string, error) { + return program(name, true) +} + +func program(program string, dnsname bool) (string, error) { + cmd := exec.Command(program, "--version") + var stdout bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + err := cmd.Run() + if err != nil { + return "", fmt.Errorf("`%v --version` failed: %v %v (%v)", program, stderr.String(), stdout.String(), err) + } + + output := strings.TrimSuffix(stdout.String(), "\n") + // dnsname --version returns the information to stderr + if dnsname { + output = strings.TrimSuffix(stderr.String(), "\n") + } + + return output, nil +} diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 382c140d187..19ba92c0f01 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.55.4" +const Version = "0.57.4" diff --git a/vendor/github.com/containers/image/v5/copy/compression.go b/vendor/github.com/containers/image/v5/copy/compression.go index eb4da5092fd..a42e3b67abe 100644 --- a/vendor/github.com/containers/image/v5/copy/compression.go +++ b/vendor/github.com/containers/image/v5/copy/compression.go @@ -284,10 +284,24 @@ func (d *bpCompressionStepData) recordValidatedDigestData(c *copier, uploadedInf } } if d.uploadedCompressorName != "" && d.uploadedCompressorName != internalblobinfocache.UnknownCompression { - c.blobInfoCache.RecordDigestCompressorName(uploadedInfo.Digest, d.uploadedCompressorName) + if d.uploadedCompressorName != compressiontypes.ZstdChunkedAlgorithmName { + // HACK: Don’t record zstd:chunked algorithms. + // There is already a similar hack in internal/imagedestination/impl/helpers.BlobMatchesRequiredCompression, + // and that one prevents reusing zstd:chunked blobs, so recording the algorithm here would be mostly harmless. + // + // We skip that here anyway to work around the inability of blobPipelineDetectCompressionStep to differentiate + // between zstd and zstd:chunked; so we could, in varying situations over time, call RecordDigestCompressorName + // with the same digest and both ZstdAlgorithmName and ZstdChunkedAlgorithmName , which causes warnings about + // inconsistent data to be logged. + c.blobInfoCache.RecordDigestCompressorName(uploadedInfo.Digest, d.uploadedCompressorName) + } } - if srcInfo.Digest != "" && d.srcCompressorName != "" && d.srcCompressorName != internalblobinfocache.UnknownCompression { - c.blobInfoCache.RecordDigestCompressorName(srcInfo.Digest, d.srcCompressorName) + if srcInfo.Digest != "" && srcInfo.Digest != uploadedInfo.Digest && + d.srcCompressorName != "" && d.srcCompressorName != internalblobinfocache.UnknownCompression { + if d.srcCompressorName != compressiontypes.ZstdChunkedAlgorithmName { + // HACK: Don’t record zstd:chunked algorithms, see above. + c.blobInfoCache.RecordDigestCompressorName(srcInfo.Digest, d.srcCompressorName) + } } return nil } diff --git a/vendor/github.com/containers/image/v5/copy/copy.go b/vendor/github.com/containers/image/v5/copy/copy.go index ac0e6f2fa22..ad1453fcbcc 100644 --- a/vendor/github.com/containers/image/v5/copy/copy.go +++ b/vendor/github.com/containers/image/v5/copy/copy.go @@ -133,6 +133,10 @@ type Options struct { // Invalid when copying a non-multi-architecture image. That will probably // change in the future. EnsureCompressionVariantsExist []OptionCompressionVariant + // ForceCompressionFormat ensures that the compression algorithm set in + // DestinationCtx.CompressionFormat is used exclusively, and blobs of other + // compression algorithms are not reused. + ForceCompressionFormat bool } // OptionCompressionVariant allows to supply information about @@ -163,6 +167,14 @@ type copier struct { signersToClose []*signer.Signer // Signers that should be closed when this copier is destroyed. } +// Internal function to validate `requireCompressionFormatMatch` for copySingleImageOptions +func shouldRequireCompressionFormatMatch(options *Options) (bool, error) { + if options.ForceCompressionFormat && (options.DestinationCtx == nil || options.DestinationCtx.CompressionFormat == nil) { + return false, fmt.Errorf("cannot use ForceCompressionFormat with undefined default compression format") + } + return options.ForceCompressionFormat, nil +} + // Image copies image from srcRef to destRef, using policyContext to validate // source image admissibility. It returns the manifest which was written to // the new copy of the image. @@ -230,11 +242,13 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, unparsedToplevel: image.UnparsedInstance(rawSource, nil), // FIXME? The cache is used for sources and destinations equally, but we only have a SourceCtx and DestinationCtx. - // For now, use DestinationCtx (because blob reuse changes the behavior of the destination side more); eventually - // we might want to add a separate CommonCtx — or would that be too confusing? + // For now, use DestinationCtx (because blob reuse changes the behavior of the destination side more). + // Conceptually the cache settings should be in copy.Options instead. blobInfoCache: internalblobinfocache.FromBlobInfoCache(blobinfocache.DefaultCache(options.DestinationCtx)), } defer c.close() + c.blobInfoCache.Open() + defer c.blobInfoCache.Close() // Set the concurrentBlobCopiesSemaphore if we can copy layers in parallel. if dest.HasThreadSafePutBlob() && rawSource.HasThreadSafeGetBlob() { @@ -269,8 +283,12 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, if len(options.EnsureCompressionVariantsExist) > 0 { return nil, fmt.Errorf("EnsureCompressionVariantsExist is not implemented when not creating a multi-architecture image") } + requireCompressionFormatMatch, err := shouldRequireCompressionFormatMatch(options) + if err != nil { + return nil, err + } // The simple case: just copy a single image. - single, err := c.copySingleImage(ctx, c.unparsedToplevel, nil, copySingleImageOptions{requireCompressionFormatMatch: false}) + single, err := c.copySingleImage(ctx, c.unparsedToplevel, nil, copySingleImageOptions{requireCompressionFormatMatch: requireCompressionFormatMatch}) if err != nil { return nil, err } @@ -279,6 +297,10 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, if len(options.EnsureCompressionVariantsExist) > 0 { return nil, fmt.Errorf("EnsureCompressionVariantsExist is not implemented when not creating a multi-architecture image") } + requireCompressionFormatMatch, err := shouldRequireCompressionFormatMatch(options) + if err != nil { + return nil, err + } // This is a manifest list, and we weren't asked to copy multiple images. Choose a single image that // matches the current system to copy, and copy it. mfest, manifestType, err := c.unparsedToplevel.Manifest(ctx) @@ -295,7 +317,7 @@ func Image(ctx context.Context, policyContext *signature.PolicyContext, destRef, } logrus.Debugf("Source is a manifest list; copying (only) instance %s for current system", instanceDigest) unparsedInstance := image.UnparsedInstance(rawSource, &instanceDigest) - single, err := c.copySingleImage(ctx, unparsedInstance, nil, copySingleImageOptions{requireCompressionFormatMatch: false}) + single, err := c.copySingleImage(ctx, unparsedInstance, nil, copySingleImageOptions{requireCompressionFormatMatch: requireCompressionFormatMatch}) if err != nil { return nil, fmt.Errorf("copying system image from manifest list: %w", err) } diff --git a/vendor/github.com/containers/image/v5/copy/encryption.go b/vendor/github.com/containers/image/v5/copy/encryption.go index b406b0c316c..1305676d7ad 100644 --- a/vendor/github.com/containers/image/v5/copy/encryption.go +++ b/vendor/github.com/containers/image/v5/copy/encryption.go @@ -70,7 +70,7 @@ func (d *bpDecryptionStepData) updateCryptoOperation(operation *types.LayerCrypt } } -// bpdData contains data that the copy pipeline needs about the encryption step. +// bpEncryptionStepData contains data that the copy pipeline needs about the encryption step. type bpEncryptionStepData struct { encrypting bool // We are actually encrypting the stream finalizer ocicrypt.EncryptLayerFinalizer diff --git a/vendor/github.com/containers/image/v5/copy/multiple.go b/vendor/github.com/containers/image/v5/copy/multiple.go index 34f2129d69c..f252e3476f4 100644 --- a/vendor/github.com/containers/image/v5/copy/multiple.go +++ b/vendor/github.com/containers/image/v5/copy/multiple.go @@ -32,6 +32,10 @@ type instanceCopy struct { op instanceCopyKind sourceDigest digest.Digest + // Fields which can be used by callers when operation + // is `instanceCopyCopy` + copyForceCompressionFormat bool + // Fields which can be used by callers when operation // is `instanceCopyClone` cloneCompressionVariant OptionCompressionVariant @@ -122,9 +126,14 @@ func prepareInstanceCopies(list internalManifest.List, instanceDigests []digest. if err != nil { return res, fmt.Errorf("getting details for instance %s: %w", instanceDigest, err) } + forceCompressionFormat, err := shouldRequireCompressionFormatMatch(options) + if err != nil { + return nil, err + } res = append(res, instanceCopy{ - op: instanceCopyCopy, - sourceDigest: instanceDigest, + op: instanceCopyCopy, + sourceDigest: instanceDigest, + copyForceCompressionFormat: forceCompressionFormat, }) platform := platformV1ToPlatformComparable(instanceDetails.ReadOnly.Platform) compressionList := compressionsByPlatform[platform] @@ -230,7 +239,7 @@ func (c *copier) copyMultipleImages(ctx context.Context) (copiedManifest []byte, logrus.Debugf("Copying instance %s (%d/%d)", instance.sourceDigest, i+1, len(instanceCopyList)) c.Printf("Copying image %s (%d/%d)\n", instance.sourceDigest, i+1, len(instanceCopyList)) unparsedInstance := image.UnparsedInstance(c.rawSource, &instanceCopyList[i].sourceDigest) - updated, err := c.copySingleImage(ctx, unparsedInstance, &instanceCopyList[i].sourceDigest, copySingleImageOptions{requireCompressionFormatMatch: false}) + updated, err := c.copySingleImage(ctx, unparsedInstance, &instanceCopyList[i].sourceDigest, copySingleImageOptions{requireCompressionFormatMatch: instance.copyForceCompressionFormat}) if err != nil { return nil, fmt.Errorf("copying image %d/%d from manifest list: %w", i+1, len(instanceCopyList), err) } @@ -331,7 +340,7 @@ func (c *copier) copyMultipleImages(ctx context.Context) (copiedManifest []byte, if err != nil { return nil, err } - sigs = append(sigs, newSigs...) + sigs = append(slices.Clone(sigs), newSigs...) c.Printf("Storing list signatures\n") if err := c.dest.PutSignaturesWithFormat(ctx, sigs, nil); err != nil { diff --git a/vendor/github.com/containers/image/v5/copy/progress_bars.go b/vendor/github.com/containers/image/v5/copy/progress_bars.go index 25f2463630e..ce078234cb6 100644 --- a/vendor/github.com/containers/image/v5/copy/progress_bars.go +++ b/vendor/github.com/containers/image/v5/copy/progress_bars.go @@ -84,6 +84,8 @@ func (c *copier) createProgressBar(pool *mpb.Progress, partial bool, info types. ), mpb.AppendDecorators( decor.OnComplete(decor.CountersKibiByte("%.1f / %.1f"), ""), + decor.Name(" | "), + decor.OnComplete(decor.EwmaSpeed(decor.SizeB1024(0), "% .1f", 30), ""), ), ) } @@ -94,6 +96,9 @@ func (c *copier) createProgressBar(pool *mpb.Progress, partial bool, info types. mpb.PrependDecorators( decor.OnComplete(decor.Name(prefix), onComplete), ), + mpb.AppendDecorators( + decor.OnComplete(decor.EwmaSpeed(decor.SizeB1024(0), "% .1f", 30), ""), + ), ) } return &progressBar{ diff --git a/vendor/github.com/containers/image/v5/copy/single.go b/vendor/github.com/containers/image/v5/copy/single.go index f40b5f2f722..67ca43f7bcf 100644 --- a/vendor/github.com/containers/image/v5/copy/single.go +++ b/vendor/github.com/containers/image/v5/copy/single.go @@ -161,7 +161,7 @@ func (c *copier) copySingleImage(ctx context.Context, unparsedImage *image.Unpar return copySingleImageResult{}, err } - destRequiresOciEncryption := (isEncrypted(src) && ic.c.options.OciDecryptConfig != nil) || c.options.OciEncryptLayers != nil + destRequiresOciEncryption := (isEncrypted(src) && ic.c.options.OciDecryptConfig == nil) || c.options.OciEncryptLayers != nil manifestConversionPlan, err := determineManifestConversion(determineManifestConversionInputs{ srcMIMEType: ic.src.ManifestMIMEType, @@ -277,7 +277,7 @@ func (c *copier) copySingleImage(ctx context.Context, unparsedImage *image.Unpar if err != nil { return copySingleImageResult{}, err } - sigs = append(sigs, newSigs...) + sigs = append(slices.Clone(sigs), newSigs...) if len(sigs) > 0 { c.Printf("Storing signatures\n") @@ -305,18 +305,18 @@ func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.Syst options := newOrderedSet() match := false for _, wantedPlatform := range wantedPlatforms { - // Waiting for https://github.com/opencontainers/image-spec/pull/777 : - // This currently can’t use image.MatchesPlatform because we don’t know what to use - // for image.Variant. - if wantedPlatform.OS == c.OS && wantedPlatform.Architecture == c.Architecture { + // For a transitional period, this might trigger warnings because the Variant + // field was added to OCI config only recently. If this turns out to be too noisy, + // revert this check to only look for (OS, Architecture). + if platform.MatchesPlatform(c.Platform, wantedPlatform) { match = true break } - options.append(fmt.Sprintf("%s+%s", wantedPlatform.OS, wantedPlatform.Architecture)) + options.append(fmt.Sprintf("%s+%s+%q", wantedPlatform.OS, wantedPlatform.Architecture, wantedPlatform.Variant)) } if !match { - logrus.Infof("Image operating system mismatch: image uses OS %q+architecture %q, expecting one of %q", - c.OS, c.Architecture, strings.Join(options.list, ", ")) + logrus.Infof("Image operating system mismatch: image uses OS %q+architecture %q+%q, expecting one of %q", + c.OS, c.Architecture, c.Variant, strings.Join(options.list, ", ")) } } return nil @@ -360,6 +360,7 @@ func (ic *imageCopier) compareImageDestinationManifestEqual(ctx context.Context, logrus.Debugf("Unable to create destination image %s source: %v", ic.c.dest.Reference(), err) return nil, nil } + defer destImageSource.Close() destManifest, destManifestType, err := destImageSource.GetManifest(ctx, targetInstance) if err != nil { @@ -379,8 +380,9 @@ func (ic *imageCopier) compareImageDestinationManifestEqual(ctx context.Context, compressionAlgos := set.New[string]() for _, srcInfo := range ic.src.LayerInfos() { - compression := compressionAlgorithmFromMIMEType(srcInfo) - compressionAlgos.Add(compression.Name()) + if c := compressionAlgorithmFromMIMEType(srcInfo); c != nil { + compressionAlgos.Add(c.Name()) + } } algos, err := algorithmsByNames(compressionAlgos.Values()) @@ -459,8 +461,14 @@ func (ic *imageCopier) copyLayers(ctx context.Context) ([]compressiontypes.Algor encryptAll = len(*ic.c.options.OciEncryptLayers) == 0 totalLayers := len(srcInfos) for _, l := range *ic.c.options.OciEncryptLayers { - // if layer is negative, it is reverse indexed. - layersToEncrypt.Add((totalLayers + l) % totalLayers) + switch { + case l >= 0 && l < totalLayers: + layersToEncrypt.Add(l) + case l < 0 && l+totalLayers >= 0: // Implies (l + totalLayers) < totalLayers + layersToEncrypt.Add(l + totalLayers) // If l is negative, it is reverse indexed. + default: + return nil, fmt.Errorf("when choosing layers to encrypt, layer index %d out of range (%d layers exist)", l, totalLayers) + } } if encryptAll { @@ -655,8 +663,12 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to ic.c.printCopyInfo("blob", srcInfo) - cachedDiffID := ic.c.blobInfoCache.UncompressedDigest(srcInfo.Digest) // May be "" - diffIDIsNeeded := ic.diffIDsAreNeeded && cachedDiffID == "" + diffIDIsNeeded := false + var cachedDiffID digest.Digest = "" + if ic.diffIDsAreNeeded { + cachedDiffID = ic.c.blobInfoCache.UncompressedDigest(srcInfo.Digest) // May be "" + diffIDIsNeeded = cachedDiffID == "" + } // When encrypting to decrypting, only use the simple code path. We might be able to optimize more // (e.g. if we know the DiffID of an encrypted compressed layer, it might not be necessary to pull, decrypt and decompress again), // but it’s not trivially safe to do such things, so until someone takes the effort to make a comprehensive argument, let’s not. @@ -732,7 +744,9 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to uploadedBlob, err := ic.c.dest.PutBlobPartial(ctx, &proxy, srcInfo, ic.c.blobInfoCache) if err == nil { if srcInfo.Size != -1 { - bar.SetRefill(srcInfo.Size - bar.Current()) + refill := srcInfo.Size - bar.Current() + bar.SetCurrent(srcInfo.Size) + bar.SetRefill(refill) } bar.mark100PercentComplete() hideProgressBar = false diff --git a/vendor/github.com/containers/image/v5/docker/daemon/client.go b/vendor/github.com/containers/image/v5/docker/daemon/client.go index 2c245f54f98..354af2140ff 100644 --- a/vendor/github.com/containers/image/v5/docker/daemon/client.go +++ b/vendor/github.com/containers/image/v5/docker/daemon/client.go @@ -9,11 +9,6 @@ import ( "github.com/docker/go-connections/tlsconfig" ) -const ( - // The default API version to be used in case none is explicitly specified - defaultAPIVersion = "1.22" -) - // NewDockerClient initializes a new API client based on the passed SystemContext. func newDockerClient(sys *types.SystemContext) (*dockerclient.Client, error) { host := dockerclient.DefaultDockerHost @@ -23,7 +18,7 @@ func newDockerClient(sys *types.SystemContext) (*dockerclient.Client, error) { opts := []dockerclient.Opt{ dockerclient.WithHost(host), - dockerclient.WithVersion(defaultAPIVersion), + dockerclient.WithAPIVersionNegotiation(), } // We conditionalize building the TLS configuration only to TLS sockets: diff --git a/vendor/github.com/containers/image/v5/docker/daemon/daemon_dest.go b/vendor/github.com/containers/image/v5/docker/daemon/daemon_dest.go index 59e02462f0c..55431db13aa 100644 --- a/vendor/github.com/containers/image/v5/docker/daemon/daemon_dest.go +++ b/vendor/github.com/containers/image/v5/docker/daemon/daemon_dest.go @@ -2,6 +2,7 @@ package daemon import ( "context" + "encoding/json" "errors" "fmt" "io" @@ -85,12 +86,40 @@ func imageLoadGoroutine(ctx context.Context, c *client.Client, reader *io.PipeRe } }() + err = imageLoad(ctx, c, reader) +} + +// imageLoad accepts tar stream on reader and sends it to c +func imageLoad(ctx context.Context, c *client.Client, reader *io.PipeReader) error { resp, err := c.ImageLoad(ctx, reader, true) if err != nil { - err = fmt.Errorf("saving image to docker engine: %w", err) - return + return fmt.Errorf("starting a load operation in docker engine: %w", err) } defer resp.Body.Close() + + // jsonError and jsonMessage are small subsets of docker/docker/pkg/jsonmessage.JSONError and JSONMessage, + // copied here to minimize dependencies. + type jsonError struct { + Message string `json:"message,omitempty"` + } + type jsonMessage struct { + Error *jsonError `json:"errorDetail,omitempty"` + } + + dec := json.NewDecoder(resp.Body) + for { + var msg jsonMessage + if err := dec.Decode(&msg); err != nil { + if err == io.EOF { + break + } + return fmt.Errorf("parsing docker load progress: %w", err) + } + if msg.Error != nil { + return fmt.Errorf("docker engine reported: %s", msg.Error.Message) + } + } + return nil // No error reported = success } // DesiredLayerCompression indicates if layers must be compressed, decompressed or preserved diff --git a/vendor/github.com/containers/image/v5/docker/distribution_error.go b/vendor/github.com/containers/image/v5/docker/distribution_error.go index 0fe915249b7..11b42c6e003 100644 --- a/vendor/github.com/containers/image/v5/docker/distribution_error.go +++ b/vendor/github.com/containers/image/v5/docker/distribution_error.go @@ -24,6 +24,7 @@ import ( "github.com/docker/distribution/registry/api/errcode" dockerChallenge "github.com/docker/distribution/registry/client/auth/challenge" + "golang.org/x/exp/slices" ) // errNoErrorsInBody is returned when an HTTP response body parses to an empty @@ -105,7 +106,7 @@ func makeErrorList(err error) []error { } func mergeErrors(err1, err2 error) error { - return errcode.Errors(append(makeErrorList(err1), makeErrorList(err2)...)) + return errcode.Errors(append(slices.Clone(makeErrorList(err1)), makeErrorList(err2)...)) } // handleErrorResponse returns error parsed from HTTP response for an diff --git a/vendor/github.com/containers/image/v5/docker/docker_client.go b/vendor/github.com/containers/image/v5/docker/docker_client.go index dd9127c5ac8..6ce8f700838 100644 --- a/vendor/github.com/containers/image/v5/docker/docker_client.go +++ b/vendor/github.com/containers/image/v5/docker/docker_client.go @@ -1,7 +1,6 @@ package docker import ( - "bytes" "context" "crypto/tls" "encoding/json" @@ -19,6 +18,7 @@ import ( "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/internal/iolimits" + "github.com/containers/image/v5/internal/set" "github.com/containers/image/v5/internal/useragent" "github.com/containers/image/v5/manifest" "github.com/containers/image/v5/pkg/docker/config" @@ -121,6 +121,9 @@ type dockerClient struct { // Private state for detectProperties: detectPropertiesOnce sync.Once // detectPropertiesOnce is used to execute detectProperties() at most once. detectPropertiesError error // detectPropertiesError caches the initial error. + // Private state for logResponseWarnings + reportedWarningsLock sync.Mutex + reportedWarnings *set.Set[string] } type authScope struct { @@ -281,10 +284,11 @@ func newDockerClient(sys *types.SystemContext, registry, reference string) (*doc } return &dockerClient{ - sys: sys, - registry: registry, - userAgent: userAgent, - tlsClientConfig: tlsClientConfig, + sys: sys, + registry: registry, + userAgent: userAgent, + tlsClientConfig: tlsClientConfig, + reportedWarnings: set.New[string](), }, nil } @@ -359,6 +363,11 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima hostname := registry if registry == dockerHostname { hostname = dockerV1Hostname + // A search term of library/foo does not find the library/foo image on the docker.io servers, + // which is surprising - and that Docker is modifying the search term client-side this same way, + // and it seems convenient to do the same thing. + // Read more here: https://github.com/containers/image/pull/2133#issue-1928524334 + image = strings.TrimPrefix(image, "library/") } client, err := newDockerClient(sys, hostname, registry) @@ -624,9 +633,76 @@ func (c *dockerClient) makeRequestToResolvedURLOnce(ctx context.Context, method if err != nil { return nil, err } + if warnings := res.Header.Values("Warning"); len(warnings) != 0 { + c.logResponseWarnings(res, warnings) + } return res, nil } +// logResponseWarnings logs warningHeaders from res, if any. +func (c *dockerClient) logResponseWarnings(res *http.Response, warningHeaders []string) { + c.reportedWarningsLock.Lock() + defer c.reportedWarningsLock.Unlock() + + for _, header := range warningHeaders { + warningString := parseRegistryWarningHeader(header) + if warningString == "" { + logrus.Debugf("Ignored Warning: header from registry: %q", header) + } else { + if !c.reportedWarnings.Contains(warningString) { + c.reportedWarnings.Add(warningString) + // Note that reportedWarnings is based only on warningString, so that we don’t + // repeat the same warning for every request - but the warning includes the URL; + // so it may not be specific to that URL. + logrus.Warnf("Warning from registry (first encountered at %q): %q", res.Request.URL.Redacted(), warningString) + } else { + logrus.Debugf("Repeated warning from registry at %q: %q", res.Request.URL.Redacted(), warningString) + } + } + } +} + +// parseRegistryWarningHeader parses a Warning: header per RFC 7234, limited to the warning +// values allowed by opencontainers/distribution-spec. +// It returns the warning string if the header has the expected format, or "" otherwise. +func parseRegistryWarningHeader(header string) string { + const expectedPrefix = `299 - "` + const expectedSuffix = `"` + + // warning-value = warn-code SP warn-agent SP warn-text [ SP warn-date ] + // distribution-spec requires warn-code=299, warn-agent="-", warn-date missing + if !strings.HasPrefix(header, expectedPrefix) || !strings.HasSuffix(header, expectedSuffix) { + return "" + } + header = header[len(expectedPrefix) : len(header)-len(expectedSuffix)] + + // ”Recipients that process the value of a quoted-string MUST handle a quoted-pair + // as if it were replaced by the octet following the backslash.”, so let’s do that… + res := strings.Builder{} + afterBackslash := false + for _, c := range []byte(header) { // []byte because escaping is defined in terms of bytes, not Unicode code points + switch { + case c == 0x7F || (c < ' ' && c != '\t'): + return "" // Control characters are forbidden + case afterBackslash: + res.WriteByte(c) + afterBackslash = false + case c == '"': + // This terminates the warn-text and warn-date, forbidden by distribution-spec, follows, + // or completely invalid input. + return "" + case c == '\\': + afterBackslash = true + default: + res.WriteByte(c) + } + } + if afterBackslash { + return "" + } + return res.String() +} + // we're using the challenges from the /v2/ ping response and not the one from the destination // URL in this request because: // @@ -1008,9 +1084,10 @@ func isManifestUnknownError(err error) bool { if errors.As(err, &e) && e.ErrorCode() == errcode.ErrorCodeUnknown && e.Message == "Not Found" { return true } - // ALSO registry.redhat.io as of October 2022 + // opencontainers/distribution-spec does not require the errcode.Error payloads to be used, + // but specifies that the HTTP status must be 404. var unexpected *unexpectedHTTPResponseError - if errors.As(err, &unexpected) && unexpected.StatusCode == http.StatusNotFound && bytes.Contains(unexpected.Response, []byte("Not found")) { + if errors.As(err, &unexpected) && unexpected.StatusCode == http.StatusNotFound { return true } return false diff --git a/vendor/github.com/containers/image/v5/docker/docker_image.go b/vendor/github.com/containers/image/v5/docker/docker_image.go index 42bbfd95ee2..93160480ea2 100644 --- a/vendor/github.com/containers/image/v5/docker/docker_image.go +++ b/vendor/github.com/containers/image/v5/docker/docker_image.go @@ -123,6 +123,9 @@ func GetDigest(ctx context.Context, sys *types.SystemContext, ref types.ImageRef if !ok { return "", errors.New("ref must be a dockerReference") } + if dr.isUnknownDigest { + return "", fmt.Errorf("docker: reference %q is for unknown digest case; cannot get digest", dr.StringWithinTransport()) + } tagOrDigest, err := dr.tagOrDigest() if err != nil { diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go index 63e372d6776..a9a36f0a34a 100644 --- a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go +++ b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go @@ -137,7 +137,7 @@ func (d *dockerImageDestination) PutBlobWithOptions(ctx context.Context, stream // If requested, precompute the blob digest to prevent uploading layers that already exist on the registry. // This functionality is particularly useful when BlobInfoCache has not been populated with compressed digests, // the source blob is uncompressed, and the destination blob is being compressed "on the fly". - if inputInfo.Digest == "" && d.c.sys.DockerRegistryPushPrecomputeDigests { + if inputInfo.Digest == "" && d.c.sys != nil && d.c.sys.DockerRegistryPushPrecomputeDigests { logrus.Debugf("Precomputing digest layer for %s", reference.Path(d.ref.ref)) streamCopy, cleanup, err := streamdigest.ComputeBlobInfo(d.c.sys, stream, &inputInfo) if err != nil { @@ -341,34 +341,58 @@ func (d *dockerImageDestination) TryReusingBlobWithOptions(ctx context.Context, // Then try reusing blobs from other locations. candidates := options.Cache.CandidateLocations2(d.ref.Transport(), bicTransportScope(d.ref), info.Digest, options.CanSubstitute) for _, candidate := range candidates { - candidateRepo, err := parseBICLocationReference(candidate.Location) - if err != nil { - logrus.Debugf("Error parsing BlobInfoCache location reference: %s", err) - continue - } + var err error compressionOperation, compressionAlgorithm, err := blobinfocache.OperationAndAlgorithmForCompressor(candidate.CompressorName) if err != nil { logrus.Debugf("OperationAndAlgorithmForCompressor Failed: %v", err) continue } + var candidateRepo reference.Named + if !candidate.UnknownLocation { + candidateRepo, err = parseBICLocationReference(candidate.Location) + if err != nil { + logrus.Debugf("Error parsing BlobInfoCache location reference: %s", err) + continue + } + } if !impl.BlobMatchesRequiredCompression(options, compressionAlgorithm) { requiredCompression := "nil" if compressionAlgorithm != nil { requiredCompression = compressionAlgorithm.Name() } - logrus.Debugf("Ignoring candidate blob %s as reuse candidate due to compression mismatch ( %s vs %s ) in %s", candidate.Digest.String(), options.RequiredCompression.Name(), requiredCompression, candidateRepo.Name()) + if !candidate.UnknownLocation { + logrus.Debugf("Ignoring candidate blob %s as reuse candidate due to compression mismatch ( %s vs %s ) in %s", candidate.Digest.String(), options.RequiredCompression.Name(), requiredCompression, candidateRepo.Name()) + } else { + logrus.Debugf("Ignoring candidate blob %s as reuse candidate due to compression mismatch ( %s vs %s ) with no location match, checking current repo", candidate.Digest.String(), options.RequiredCompression.Name(), requiredCompression) + } continue } - if candidate.CompressorName != blobinfocache.Uncompressed { - logrus.Debugf("Trying to reuse cached location %s compressed with %s in %s", candidate.Digest.String(), candidate.CompressorName, candidateRepo.Name()) + if !candidate.UnknownLocation { + if candidate.CompressorName != blobinfocache.Uncompressed { + logrus.Debugf("Trying to reuse blob with cached digest %s compressed with %s in destination repo %s", candidate.Digest.String(), candidate.CompressorName, candidateRepo.Name()) + } else { + logrus.Debugf("Trying to reuse blob with cached digest %s in destination repo %s", candidate.Digest.String(), candidateRepo.Name()) + } + // Sanity checks: + if reference.Domain(candidateRepo) != reference.Domain(d.ref.ref) { + // OCI distribution spec 1.1 allows mounting blobs without specifying the source repo + // (the "from" parameter); in that case we might try to use these candidates as well. + // + // OTOH that would mean we can’t do the “blobExists” check, and if there is no match + // we could get an upload request that we would have to cancel. + logrus.Debugf("... Internal error: domain %s does not match destination %s", reference.Domain(candidateRepo), reference.Domain(d.ref.ref)) + continue + } } else { - logrus.Debugf("Trying to reuse cached location %s with no compression in %s", candidate.Digest.String(), candidateRepo.Name()) - } - - // Sanity checks: - if reference.Domain(candidateRepo) != reference.Domain(d.ref.ref) { - logrus.Debugf("... Internal error: domain %s does not match destination %s", reference.Domain(candidateRepo), reference.Domain(d.ref.ref)) - continue + if candidate.CompressorName != blobinfocache.Uncompressed { + logrus.Debugf("Trying to reuse blob with cached digest %s compressed with %s with no location match, checking current repo", candidate.Digest.String(), candidate.CompressorName) + } else { + logrus.Debugf("Trying to reuse blob with cached digest %s in destination repo with no location match, checking current repo", candidate.Digest.String()) + } + // This digest is a known variant of this blob but we don’t + // have a recorded location in this registry, let’s try looking + // for it in the current repo. + candidateRepo = reference.TrimNamed(d.ref.ref) } if candidateRepo.Name() == d.ref.ref.Name() && candidate.Digest == info.Digest { logrus.Debug("... Already tried the primary destination") @@ -428,7 +452,15 @@ func (d *dockerImageDestination) TryReusingBlobWithOptions(ctx context.Context, // but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError. func (d *dockerImageDestination) PutManifest(ctx context.Context, m []byte, instanceDigest *digest.Digest) error { var refTail string - if instanceDigest != nil { + // If d.ref.isUnknownDigest=true, then we push without a tag, so get the + // digest that will be used + if d.ref.isUnknownDigest { + digest, err := manifest.Digest(m) + if err != nil { + return err + } + refTail = digest.String() + } else if instanceDigest != nil { // If the instanceDigest is provided, then use it as the refTail, because the reference, // whether it includes a tag or a digest, refers to the list as a whole, and not this // particular instance. @@ -683,6 +715,10 @@ func (d *dockerImageDestination) putSignaturesToSigstoreAttachments(ctx context. } } + // To make sure we can safely append to the slices of ociManifest, without adding a remote dependency on the code that creates it. + ociManifest.Layers = slices.Clone(ociManifest.Layers) + // We don’t need to ^^^ for ociConfig.RootFS.DiffIDs because we have created it empty ourselves, and json.Unmarshal is documented to append() to + // the slice in the original object (or in a newly allocated object). for _, sig := range signatures { mimeType := sig.UntrustedMIMEType() payloadBlob := sig.UntrustedPayload() diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_src.go b/vendor/github.com/containers/image/v5/docker/docker_image_src.go index 231d5d21240..f9d4d6030f0 100644 --- a/vendor/github.com/containers/image/v5/docker/docker_image_src.go +++ b/vendor/github.com/containers/image/v5/docker/docker_image_src.go @@ -38,8 +38,8 @@ type dockerImageSource struct { impl.DoesNotAffectLayerInfosForCopy stubs.ImplementsGetBlobAt - logicalRef dockerReference // The reference the user requested. - physicalRef dockerReference // The actual reference we are accessing (possibly a mirror) + logicalRef dockerReference // The reference the user requested. This must satisfy !isUnknownDigest + physicalRef dockerReference // The actual reference we are accessing (possibly a mirror). This must satisfy !isUnknownDigest c *dockerClient // State cachedManifest []byte // nil if not loaded yet @@ -48,7 +48,12 @@ type dockerImageSource struct { // newImageSource creates a new ImageSource for the specified image reference. // The caller must call .Close() on the returned ImageSource. +// The caller must ensure !ref.isUnknownDigest. func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerReference) (*dockerImageSource, error) { + if ref.isUnknownDigest { + return nil, fmt.Errorf("reading images from docker: reference %q without a tag or digest is not supported", ref.StringWithinTransport()) + } + registryConfig, err := loadRegistryConfiguration(sys) if err != nil { return nil, err @@ -121,7 +126,7 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef // The caller must call .Close() on the returned ImageSource. func newImageSourceAttempt(ctx context.Context, sys *types.SystemContext, logicalRef dockerReference, pullSource sysregistriesv2.PullSource, registryConfig *registryConfiguration) (*dockerImageSource, error) { - physicalRef, err := newReference(pullSource.Reference) + physicalRef, err := newReference(pullSource.Reference, false) if err != nil { return nil, err } @@ -591,6 +596,10 @@ func (s *dockerImageSource) getSignaturesFromSigstoreAttachments(ctx context.Con // deleteImage deletes the named image from the registry, if supported. func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerReference) error { + if ref.isUnknownDigest { + return fmt.Errorf("Docker reference without a tag or digest cannot be deleted") + } + registryConfig, err := loadRegistryConfiguration(sys) if err != nil { return err diff --git a/vendor/github.com/containers/image/v5/docker/docker_transport.go b/vendor/github.com/containers/image/v5/docker/docker_transport.go index 6ae8491594a..1c89302f46b 100644 --- a/vendor/github.com/containers/image/v5/docker/docker_transport.go +++ b/vendor/github.com/containers/image/v5/docker/docker_transport.go @@ -12,6 +12,11 @@ import ( "github.com/containers/image/v5/types" ) +// UnknownDigestSuffix can be appended to a reference when the caller +// wants to push an image without a tag or digest. +// NewReferenceUnknownDigest() is called when this const is detected. +const UnknownDigestSuffix = "@@unknown-digest@@" + func init() { transports.Register(Transport) } @@ -43,7 +48,8 @@ func (t dockerTransport) ValidatePolicyConfigurationScope(scope string) error { // dockerReference is an ImageReference for Docker images. type dockerReference struct { - ref reference.Named // By construction we know that !reference.IsNameOnly(ref) + ref reference.Named // By construction we know that !reference.IsNameOnly(ref) unless isUnknownDigest=true + isUnknownDigest bool } // ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an Docker ImageReference. @@ -51,23 +57,46 @@ func ParseReference(refString string) (types.ImageReference, error) { if !strings.HasPrefix(refString, "//") { return nil, fmt.Errorf("docker: image reference %s does not start with //", refString) } + // Check if ref has UnknownDigestSuffix suffixed to it + unknownDigest := false + if strings.HasSuffix(refString, UnknownDigestSuffix) { + unknownDigest = true + refString = strings.TrimSuffix(refString, UnknownDigestSuffix) + } ref, err := reference.ParseNormalizedNamed(strings.TrimPrefix(refString, "//")) if err != nil { return nil, err } + + if unknownDigest { + if !reference.IsNameOnly(ref) { + return nil, fmt.Errorf("docker: image reference %q has unknown digest set but it contains either a tag or digest", ref.String()+UnknownDigestSuffix) + } + return NewReferenceUnknownDigest(ref) + } + ref = reference.TagNameOnly(ref) return NewReference(ref) } // NewReference returns a Docker reference for a named reference. The reference must satisfy !reference.IsNameOnly(). func NewReference(ref reference.Named) (types.ImageReference, error) { - return newReference(ref) + return newReference(ref, false) +} + +// NewReferenceUnknownDigest returns a Docker reference for a named reference, which can be used to write images without setting +// a tag on the registry. The reference must satisfy reference.IsNameOnly() +func NewReferenceUnknownDigest(ref reference.Named) (types.ImageReference, error) { + return newReference(ref, true) } // newReference returns a dockerReference for a named reference. -func newReference(ref reference.Named) (dockerReference, error) { - if reference.IsNameOnly(ref) { - return dockerReference{}, fmt.Errorf("Docker reference %s has neither a tag nor a digest", reference.FamiliarString(ref)) +func newReference(ref reference.Named, unknownDigest bool) (dockerReference, error) { + if reference.IsNameOnly(ref) && !unknownDigest { + return dockerReference{}, fmt.Errorf("Docker reference %s is not for an unknown digest case; tag or digest is needed", reference.FamiliarString(ref)) + } + if !reference.IsNameOnly(ref) && unknownDigest { + return dockerReference{}, fmt.Errorf("Docker reference %s is for an unknown digest case but reference has a tag or digest", reference.FamiliarString(ref)) } // A github.com/distribution/reference value can have a tag and a digest at the same time! // The docker/distribution API does not really support that (we can’t ask for an image with a specific @@ -81,7 +110,8 @@ func newReference(ref reference.Named) (dockerReference, error) { } return dockerReference{ - ref: ref, + ref: ref, + isUnknownDigest: unknownDigest, }, nil } @@ -95,7 +125,11 @@ func (ref dockerReference) Transport() types.ImageTransport { // e.g. default attribute values omitted by the user may be filled in the return value, or vice versa. // WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix. func (ref dockerReference) StringWithinTransport() string { - return "//" + reference.FamiliarString(ref.ref) + famString := "//" + reference.FamiliarString(ref.ref) + if ref.isUnknownDigest { + return famString + UnknownDigestSuffix + } + return famString } // DockerReference returns a Docker reference associated with this reference @@ -113,6 +147,9 @@ func (ref dockerReference) DockerReference() reference.Named { // not required/guaranteed that it will be a valid input to Transport().ParseReference(). // Returns "" if configuration identities for these references are not supported. func (ref dockerReference) PolicyConfigurationIdentity() string { + if ref.isUnknownDigest { + return ref.ref.Name() + } res, err := policyconfiguration.DockerReferenceIdentity(ref.ref) if res == "" || err != nil { // Coverage: Should never happen, NewReference above should refuse values which could cause a failure. panic(fmt.Sprintf("Internal inconsistency: policyconfiguration.DockerReferenceIdentity returned %#v, %v", res, err)) @@ -126,7 +163,13 @@ func (ref dockerReference) PolicyConfigurationIdentity() string { // It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(), // and each following element to be a prefix of the element preceding it. func (ref dockerReference) PolicyConfigurationNamespaces() []string { - return policyconfiguration.DockerReferenceNamespaces(ref.ref) + namespaces := policyconfiguration.DockerReferenceNamespaces(ref.ref) + if ref.isUnknownDigest { + if len(namespaces) != 0 && namespaces[0] == ref.ref.Name() { + namespaces = namespaces[1:] + } + } + return namespaces } // NewImage returns a types.ImageCloser for this reference, possibly specialized for this ImageTransport. @@ -163,6 +206,10 @@ func (ref dockerReference) tagOrDigest() (string, error) { if ref, ok := ref.ref.(reference.NamedTagged); ok { return ref.Tag(), nil } + + if ref.isUnknownDigest { + return "", fmt.Errorf("Docker reference %q is for an unknown digest case, has neither a digest nor a tag", reference.FamiliarString(ref.ref)) + } // This should not happen, NewReference above refuses reference.IsNameOnly values. return "", fmt.Errorf("Internal inconsistency: Reference %s unexpectedly has neither a digest nor a tag", reference.FamiliarString(ref.ref)) } diff --git a/vendor/github.com/containers/image/v5/docker/errors.go b/vendor/github.com/containers/image/v5/docker/errors.go index 2caa10d7d3b..4392f9d1829 100644 --- a/vendor/github.com/containers/image/v5/docker/errors.go +++ b/vendor/github.com/containers/image/v5/docker/errors.go @@ -47,7 +47,12 @@ func httpResponseToError(res *http.Response, context string) error { } // registryHTTPResponseToError creates a Go error from an HTTP error response of a docker/distribution -// registry +// registry. +// +// WARNING: The OCI distribution spec says +// “A `4XX` response code from the registry MAY return a body in any format.”; but if it is +// JSON, it MUST use the errcode.Error structure. +// So, callers should primarily decide based on HTTP StatusCode, not based on error type here. func registryHTTPResponseToError(res *http.Response) error { err := handleErrorResponse(res) // len(errs) == 0 should never be returned by handleErrorResponse; if it does, we don't modify it and let the caller report it as is. @@ -83,7 +88,7 @@ func registryHTTPResponseToError(res *http.Response) error { response = response[:50] + "..." } // %.0w makes e visible to error.Unwrap() without including any text - err = fmt.Errorf("StatusCode: %d, %s%.0w", e.StatusCode, response, e) + err = fmt.Errorf("StatusCode: %d, %q%.0w", e.StatusCode, response, e) case errcode.Error: // e.Error() is fmt.Sprintf("%s: %s", e.Code.Error(), e.Message, which is usually // rather redundant. So reword it without using e.Code.Error() if e.Message is the default. diff --git a/vendor/github.com/containers/image/v5/docker/internal/tarfile/reader.go b/vendor/github.com/containers/image/v5/docker/internal/tarfile/reader.go index 3b986f503d9..6845893bfb1 100644 --- a/vendor/github.com/containers/image/v5/docker/internal/tarfile/reader.go +++ b/vendor/github.com/containers/image/v5/docker/internal/tarfile/reader.go @@ -57,7 +57,7 @@ func NewReaderFromFile(sys *types.SystemContext, path string) (*Reader, error) { // The caller should call .Close() on the returned archive when done. func NewReaderFromStream(sys *types.SystemContext, inputStream io.Reader) (*Reader, error) { // Save inputStream to a temporary file - tarCopyFile, err := os.CreateTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "docker-tar") + tarCopyFile, err := tmpdir.CreateBigFileTemp(sys, "docker-tar") if err != nil { return nil, fmt.Errorf("creating temporary file: %w", err) } diff --git a/vendor/github.com/containers/image/v5/docker/policyconfiguration/naming.go b/vendor/github.com/containers/image/v5/docker/policyconfiguration/naming.go index 5d42c38706f..e1f1f1f2b75 100644 --- a/vendor/github.com/containers/image/v5/docker/policyconfiguration/naming.go +++ b/vendor/github.com/containers/image/v5/docker/policyconfiguration/naming.go @@ -40,7 +40,7 @@ func DockerReferenceNamespaces(ref reference.Named) []string { // then in its parent "docker.io/library"; in none of "busybox", // un-namespaced "library" nor in "" supposedly implicitly representing "library/". // - // ref.FullName() == ref.Hostname() + "/" + ref.RemoteName(), so the last + // ref.Name() == ref.Domain() + "/" + ref.Path(), so the last // iteration matches the host name (for any namespace). res := []string{} name := ref.Name() diff --git a/vendor/github.com/containers/image/v5/image/unparsed.go b/vendor/github.com/containers/image/v5/image/unparsed.go index 123f6ce6f1c..f2ebb929a2f 100644 --- a/vendor/github.com/containers/image/v5/image/unparsed.go +++ b/vendor/github.com/containers/image/v5/image/unparsed.go @@ -2,6 +2,8 @@ package image import ( "github.com/containers/image/v5/internal/image" + "github.com/containers/image/v5/internal/private" + "github.com/containers/image/v5/internal/unparsedimage" "github.com/containers/image/v5/types" "github.com/opencontainers/go-digest" ) @@ -17,3 +19,23 @@ type UnparsedImage = image.UnparsedImage func UnparsedInstance(src types.ImageSource, instanceDigest *digest.Digest) *UnparsedImage { return image.UnparsedInstance(src, instanceDigest) } + +// unparsedWithRef wraps a private.UnparsedImage, claiming another replacementRef +type unparsedWithRef struct { + private.UnparsedImage + ref types.ImageReference +} + +func (uwr *unparsedWithRef) Reference() types.ImageReference { + return uwr.ref +} + +// UnparsedInstanceWithReference returns a types.UnparsedImage for wrappedInstance which claims to be a replacementRef. +// This is useful for combining image data with other reference values, e.g. to check signatures on a locally-pulled image +// based on a remote-registry policy. +func UnparsedInstanceWithReference(wrappedInstance types.UnparsedImage, replacementRef types.ImageReference) types.UnparsedImage { + return &unparsedWithRef{ + UnparsedImage: unparsedimage.FromPublic(wrappedInstance), + ref: replacementRef, + } +} diff --git a/vendor/github.com/containers/image/v5/internal/blobinfocache/blobinfocache.go b/vendor/github.com/containers/image/v5/internal/blobinfocache/blobinfocache.go index b86e8b1ac3a..2767c395070 100644 --- a/vendor/github.com/containers/image/v5/internal/blobinfocache/blobinfocache.go +++ b/vendor/github.com/containers/image/v5/internal/blobinfocache/blobinfocache.go @@ -23,6 +23,12 @@ type v1OnlyBlobInfoCache struct { types.BlobInfoCache } +func (bic *v1OnlyBlobInfoCache) Open() { +} + +func (bic *v1OnlyBlobInfoCache) Close() { +} + func (bic *v1OnlyBlobInfoCache) RecordDigestCompressorName(anyDigest digest.Digest, compressorName string) { } diff --git a/vendor/github.com/containers/image/v5/internal/blobinfocache/types.go b/vendor/github.com/containers/image/v5/internal/blobinfocache/types.go index 3c2be57f32a..429d6826355 100644 --- a/vendor/github.com/containers/image/v5/internal/blobinfocache/types.go +++ b/vendor/github.com/containers/image/v5/internal/blobinfocache/types.go @@ -18,6 +18,13 @@ const ( // of compression was applied to the blobs it keeps information about. type BlobInfoCache2 interface { types.BlobInfoCache + + // Open() sets up the cache for future accesses, potentially acquiring costly state. Each Open() must be paired with a Close(). + // Note that public callers may call the types.BlobInfoCache operations without Open()/Close(). + Open() + // Close destroys state created by Open(). + Close() + // RecordDigestCompressorName records a compressor for the blob with the specified digest, // or Uncompressed or UnknownCompression. // WARNING: Only call this with LOCALLY VERIFIED data; don’t record a compressor for a @@ -25,7 +32,7 @@ type BlobInfoCache2 interface { // otherwise the cache could be poisoned and cause us to make incorrect edits to type // information in a manifest. RecordDigestCompressorName(anyDigest digest.Digest, compressorName string) - // CandidateLocations2 returns a prioritized, limited, number of blobs and their locations + // CandidateLocations2 returns a prioritized, limited, number of blobs and their locations (if known) // that could possibly be reused within the specified (transport scope) (if they still // exist, which is not guaranteed). // @@ -39,7 +46,8 @@ type BlobInfoCache2 interface { // BICReplacementCandidate2 is an item returned by BlobInfoCache2.CandidateLocations2. type BICReplacementCandidate2 struct { - Digest digest.Digest - CompressorName string // either the Name() of a known pkg/compression.Algorithm, or Uncompressed or UnknownCompression - Location types.BICLocationReference + Digest digest.Digest + CompressorName string // either the Name() of a known pkg/compression.Algorithm, or Uncompressed or UnknownCompression + UnknownLocation bool // is true when `Location` for this blob is not set + Location types.BICLocationReference // not set if UnknownLocation is set to `true` } diff --git a/vendor/github.com/containers/image/v5/internal/image/oci.go b/vendor/github.com/containers/image/v5/internal/image/oci.go index 166daa0e874..df0e8e41716 100644 --- a/vendor/github.com/containers/image/v5/internal/image/oci.go +++ b/vendor/github.com/containers/image/v5/internal/image/oci.go @@ -12,8 +12,10 @@ import ( "github.com/containers/image/v5/manifest" "github.com/containers/image/v5/pkg/blobinfocache/none" "github.com/containers/image/v5/types" + ociencspec "github.com/containers/ocicrypt/spec" "github.com/opencontainers/go-digest" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" + "golang.org/x/exp/slices" ) type manifestOCI1 struct { @@ -86,7 +88,7 @@ func (m *manifestOCI1) ConfigBlob(ctx context.Context) ([]byte, error) { // old image manifests work (docker v2s1 especially). func (m *manifestOCI1) OCIConfig(ctx context.Context) (*imgspecv1.Image, error) { if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig { - return nil, internalManifest.NewNonImageArtifactError(m.m.Config.MediaType) + return nil, internalManifest.NewNonImageArtifactError(&m.m.Manifest) } cb, err := m.ConfigBlob(ctx) @@ -194,26 +196,86 @@ func (m *manifestOCI1) convertToManifestSchema2Generic(ctx context.Context, opti return m.convertToManifestSchema2(ctx, options) } +// layerEditsOfOCIOnlyFeatures checks if options requires some layer edits to be done before converting to a Docker format. +// If not, it returns (nil, nil). +// If decryption is required, it returns a set of edits to provide to OCI1.UpdateLayerInfos, +// and edits *options to not try decryption again. +func (m *manifestOCI1) layerEditsOfOCIOnlyFeatures(options *types.ManifestUpdateOptions) ([]types.BlobInfo, error) { + if options == nil || options.LayerInfos == nil { + return nil, nil + } + + originalInfos := m.LayerInfos() + if len(originalInfos) != len(options.LayerInfos) { + return nil, fmt.Errorf("preparing to decrypt before conversion: %d layers vs. %d layer edits", len(originalInfos), len(options.LayerInfos)) + } + + ociOnlyEdits := slices.Clone(originalInfos) // Start with a full copy so that we don't forget to copy anything: use the current data in full unless we intentionally deviate. + laterEdits := slices.Clone(options.LayerInfos) + needsOCIOnlyEdits := false + for i, edit := range options.LayerInfos { + // Unless determined otherwise, don't do any compression-related MIME type conversions. m.LayerInfos() should not set these edit instructions, but be explicit. + ociOnlyEdits[i].CompressionOperation = types.PreserveOriginal + ociOnlyEdits[i].CompressionAlgorithm = nil + + if edit.CryptoOperation == types.Decrypt { + needsOCIOnlyEdits = true // Encrypted types must be removed before conversion because they can’t be represented in Docker schemas + ociOnlyEdits[i].CryptoOperation = types.Decrypt + laterEdits[i].CryptoOperation = types.PreserveOriginalCrypto // Don't try to decrypt in a schema[12] manifest later, that would fail. + } + + if originalInfos[i].MediaType == imgspecv1.MediaTypeImageLayerZstd || + originalInfos[i].MediaType == imgspecv1.MediaTypeImageLayerNonDistributableZstd { //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images. + needsOCIOnlyEdits = true // Zstd MIME types must be removed before conversion because they can’t be represented in Docker schemas. + ociOnlyEdits[i].CompressionOperation = edit.CompressionOperation + ociOnlyEdits[i].CompressionAlgorithm = edit.CompressionAlgorithm + laterEdits[i].CompressionOperation = types.PreserveOriginal + laterEdits[i].CompressionAlgorithm = nil + } + } + if !needsOCIOnlyEdits { + return nil, nil + } + + options.LayerInfos = laterEdits + return ociOnlyEdits, nil +} + // convertToManifestSchema2 returns a genericManifest implementation converted to manifest.DockerV2Schema2MediaType. // It may use options.InformationOnly and also adjust *options to be appropriate for editing the returned // value. // This does not change the state of the original manifestOCI1 object. -func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, _ *types.ManifestUpdateOptions) (*manifestSchema2, error) { +func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, options *types.ManifestUpdateOptions) (*manifestSchema2, error) { if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig { - return nil, internalManifest.NewNonImageArtifactError(m.m.Config.MediaType) + return nil, internalManifest.NewNonImageArtifactError(&m.m.Manifest) + } + + // Mostly we first make a format conversion, and _afterwards_ do layer edits. But first we need to do the layer edits + // which remove OCI-specific features, because trying to convert those layers would fail. + // So, do the layer updates for decryption, and for conversions from Zstd. + ociManifest := m.m + ociOnlyEdits, err := m.layerEditsOfOCIOnlyFeatures(options) + if err != nil { + return nil, err + } + if ociOnlyEdits != nil { + ociManifest = manifest.OCI1Clone(ociManifest) + if err := ociManifest.UpdateLayerInfos(ociOnlyEdits); err != nil { + return nil, err + } } // Create a copy of the descriptor. - config := schema2DescriptorFromOCI1Descriptor(m.m.Config) + config := schema2DescriptorFromOCI1Descriptor(ociManifest.Config) // Above, we have already checked that this manifest refers to an image, not an OCI artifact, // so the only difference between OCI and DockerSchema2 is the mediatypes. The // media type of the manifest is handled by manifestSchema2FromComponents. config.MediaType = manifest.DockerV2Schema2ConfigMediaType - layers := make([]manifest.Schema2Descriptor, len(m.m.Layers)) + layers := make([]manifest.Schema2Descriptor, len(ociManifest.Layers)) for idx := range layers { - layers[idx] = schema2DescriptorFromOCI1Descriptor(m.m.Layers[idx]) + layers[idx] = schema2DescriptorFromOCI1Descriptor(ociManifest.Layers[idx]) switch layers[idx].MediaType { case imgspecv1.MediaTypeImageLayerNonDistributable: //nolint:staticcheck // NonDistributable layers are deprecated, but we want to continue to support manipulating pre-existing images. layers[idx].MediaType = manifest.DockerV2Schema2ForeignLayerMediaType @@ -227,6 +289,9 @@ func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, _ *types.Mani layers[idx].MediaType = manifest.DockerV2Schema2LayerMediaType case imgspecv1.MediaTypeImageLayerZstd: return nil, fmt.Errorf("Error during manifest conversion: %q: zstd compression is not supported for docker images", layers[idx].MediaType) + case ociencspec.MediaTypeLayerEnc, ociencspec.MediaTypeLayerGzipEnc, ociencspec.MediaTypeLayerZstdEnc, + ociencspec.MediaTypeLayerNonDistributableEnc, ociencspec.MediaTypeLayerNonDistributableGzipEnc, ociencspec.MediaTypeLayerNonDistributableZstdEnc: + return nil, fmt.Errorf("during manifest conversion: encrypted layers (%q) are not supported in docker images", layers[idx].MediaType) default: return nil, fmt.Errorf("Unknown media type during manifest conversion: %q", layers[idx].MediaType) } @@ -244,7 +309,7 @@ func (m *manifestOCI1) convertToManifestSchema2(_ context.Context, _ *types.Mani // This does not change the state of the original manifestOCI1 object. func (m *manifestOCI1) convertToManifestSchema1(ctx context.Context, options *types.ManifestUpdateOptions) (genericManifest, error) { if m.m.Config.MediaType != imgspecv1.MediaTypeImageConfig { - return nil, internalManifest.NewNonImageArtifactError(m.m.Config.MediaType) + return nil, internalManifest.NewNonImageArtifactError(&m.m.Manifest) } // We can't directly convert images to V1, but we can transitively convert via a V2 image diff --git a/vendor/github.com/containers/image/v5/internal/imagedestination/impl/helpers.go b/vendor/github.com/containers/image/v5/internal/imagedestination/impl/helpers.go index d5de81a613b..5d28b3e73a4 100644 --- a/vendor/github.com/containers/image/v5/internal/imagedestination/impl/helpers.go +++ b/vendor/github.com/containers/image/v5/internal/imagedestination/impl/helpers.go @@ -12,6 +12,11 @@ func BlobMatchesRequiredCompression(options private.TryReusingBlobOptions, candi if options.RequiredCompression == nil { return true // no requirement imposed } + if options.RequiredCompression.Name() == compression.ZstdChunkedAlgorithmName { + // HACK: Never match when the caller asks for zstd:chunked, because we don’t record the annotations required to use the chunked blobs. + // The caller must re-compress to build those annotations. + return false + } return candidateCompression != nil && (options.RequiredCompression.Name() == candidateCompression.Name()) } diff --git a/vendor/github.com/containers/image/v5/internal/manifest/docker_schema2_list.go b/vendor/github.com/containers/image/v5/internal/manifest/docker_schema2_list.go index 14a476642e0..7ce5bb0696e 100644 --- a/vendor/github.com/containers/image/v5/internal/manifest/docker_schema2_list.go +++ b/vendor/github.com/containers/image/v5/internal/manifest/docker_schema2_list.go @@ -64,13 +64,8 @@ func (list *Schema2ListPublic) Instance(instanceDigest digest.Digest) (ListUpdat MediaType: manifest.MediaType, } ret.ReadOnly.CompressionAlgorithmNames = []string{compression.GzipAlgorithmName} - ret.ReadOnly.Platform = &imgspecv1.Platform{ - OS: manifest.Platform.OS, - Architecture: manifest.Platform.Architecture, - OSVersion: manifest.Platform.OSVersion, - OSFeatures: manifest.Platform.OSFeatures, - Variant: manifest.Platform.Variant, - } + platform := ociPlatformFromSchema2PlatformSpec(manifest.Platform) + ret.ReadOnly.Platform = &platform return ret, nil } } @@ -119,23 +114,28 @@ func (index *Schema2ListPublic) editInstances(editInstances []ListEdit) error { } index.Manifests[targetIndex].MediaType = editInstance.UpdateMediaType case ListOpAdd: - addInstance := Schema2ManifestDescriptor{ - Schema2Descriptor{Digest: editInstance.AddDigest, Size: editInstance.AddSize, MediaType: editInstance.AddMediaType}, - Schema2PlatformSpec{ - OS: editInstance.AddPlatform.OS, - Architecture: editInstance.AddPlatform.Architecture, - OSVersion: editInstance.AddPlatform.OSVersion, - OSFeatures: editInstance.AddPlatform.OSFeatures, - Variant: editInstance.AddPlatform.Variant, - }, + if editInstance.AddPlatform == nil { + // Should we create a struct with empty fields instead? + // Right now ListOpAdd is only called when an instance with the same platform value + // already exists in the manifest, so this should not be reached in practice. + return fmt.Errorf("adding a schema2 list instance with no platform specified is not supported") } - addedEntries = append(addedEntries, addInstance) + addedEntries = append(addedEntries, Schema2ManifestDescriptor{ + Schema2Descriptor{ + Digest: editInstance.AddDigest, + Size: editInstance.AddSize, + MediaType: editInstance.AddMediaType, + }, + schema2PlatformSpecFromOCIPlatform(*editInstance.AddPlatform), + }) default: return fmt.Errorf("internal error: invalid operation: %d", editInstance.ListOperation) } } if len(addedEntries) != 0 { - index.Manifests = append(index.Manifests, addedEntries...) + // slices.Clone() here to ensure a private backing array; + // an external caller could have manually created Schema2ListPublic with a slice with extra capacity. + index.Manifests = append(slices.Clone(index.Manifests), addedEntries...) } return nil } @@ -158,13 +158,7 @@ func (list *Schema2ListPublic) ChooseInstance(ctx *types.SystemContext) (digest. } for _, wantedPlatform := range wantedPlatforms { for _, d := range list.Manifests { - imagePlatform := imgspecv1.Platform{ - Architecture: d.Platform.Architecture, - OS: d.Platform.OS, - OSVersion: d.Platform.OSVersion, - OSFeatures: slices.Clone(d.Platform.OSFeatures), - Variant: d.Platform.Variant, - } + imagePlatform := ociPlatformFromSchema2PlatformSpec(d.Platform) if platform.MatchesPlatform(imagePlatform, wantedPlatform) { return d.Digest, nil } @@ -224,20 +218,14 @@ func Schema2ListPublicClone(list *Schema2ListPublic) *Schema2ListPublic { func (list *Schema2ListPublic) ToOCI1Index() (*OCI1IndexPublic, error) { components := make([]imgspecv1.Descriptor, 0, len(list.Manifests)) for _, manifest := range list.Manifests { - converted := imgspecv1.Descriptor{ + platform := ociPlatformFromSchema2PlatformSpec(manifest.Platform) + components = append(components, imgspecv1.Descriptor{ MediaType: manifest.MediaType, Size: manifest.Size, Digest: manifest.Digest, URLs: slices.Clone(manifest.URLs), - Platform: &imgspecv1.Platform{ - OS: manifest.Platform.OS, - Architecture: manifest.Platform.Architecture, - OSFeatures: slices.Clone(manifest.Platform.OSFeatures), - OSVersion: manifest.Platform.OSVersion, - Variant: manifest.Platform.Variant, - }, - } - components = append(components, converted) + Platform: &platform, + }) } oci := OCI1IndexPublicFromComponents(components, nil) return oci, nil @@ -312,3 +300,15 @@ func Schema2ListFromManifest(manifest []byte) (*Schema2List, error) { } return schema2ListFromPublic(public), nil } + +// ociPlatformFromSchema2PlatformSpec converts a schema2 platform p to the OCI struccture. +func ociPlatformFromSchema2PlatformSpec(p Schema2PlatformSpec) imgspecv1.Platform { + return imgspecv1.Platform{ + Architecture: p.Architecture, + OS: p.OS, + OSVersion: p.OSVersion, + OSFeatures: slices.Clone(p.OSFeatures), + Variant: p.Variant, + // Features is not supported in OCI, and discarded. + } +} diff --git a/vendor/github.com/containers/image/v5/internal/manifest/errors.go b/vendor/github.com/containers/image/v5/internal/manifest/errors.go index 6ebe4b24cf3..6c8e233d976 100644 --- a/vendor/github.com/containers/image/v5/internal/manifest/errors.go +++ b/vendor/github.com/containers/image/v5/internal/manifest/errors.go @@ -1,6 +1,10 @@ package manifest -import "fmt" +import ( + "fmt" + + imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" +) // FIXME: This is a duplicate of c/image/manifestDockerV2Schema2ConfigMediaType. // Deduplicate that, depending on outcome of https://github.com/containers/image/pull/1791 . @@ -26,8 +30,20 @@ type NonImageArtifactError struct { mimeType string } -// NewNonImageArtifactError returns a NonImageArtifactError about an artifact with mimeType. -func NewNonImageArtifactError(mimeType string) error { +// NewNonImageArtifactError returns a NonImageArtifactError about an artifact manifest. +// +// This is typically called if manifest.Config.MediaType != imgspecv1.MediaTypeImageConfig . +func NewNonImageArtifactError(manifest *imgspecv1.Manifest) error { + // Callers decide based on manifest.Config.MediaType that this is not an image; + // in that case manifest.ArtifactType can be optionally defined, and if it is, it is typically + // more relevant because config may be ~absent with imgspecv1.MediaTypeEmptyJSON. + // + // If ArtifactType and Config.MediaType are both defined and non-trivial, presumably + // ArtifactType is the “top-level” one, although that’s not defined by the spec. + mimeType := manifest.ArtifactType + if mimeType == "" { + mimeType = manifest.Config.MediaType + } return NonImageArtifactError{mimeType: mimeType} } diff --git a/vendor/github.com/containers/image/v5/internal/manifest/oci_index.go b/vendor/github.com/containers/image/v5/internal/manifest/oci_index.go index 3038d81243e..d8d06513b5f 100644 --- a/vendor/github.com/containers/image/v5/internal/manifest/oci_index.go +++ b/vendor/github.com/containers/image/v5/internal/manifest/oci_index.go @@ -167,11 +167,24 @@ func (index *OCI1IndexPublic) editInstances(editInstances []ListEdit) error { } } if len(addedEntries) != 0 { - index.Manifests = append(index.Manifests, addedEntries...) + // slices.Clone() here to ensure the slice uses a private backing array; + // an external caller could have manually created OCI1IndexPublic with a slice with extra capacity. + index.Manifests = append(slices.Clone(index.Manifests), addedEntries...) } if len(addedEntries) != 0 || updatedAnnotations { - slices.SortStableFunc(index.Manifests, func(a, b imgspecv1.Descriptor) bool { - return !instanceIsZstd(a) && instanceIsZstd(b) + slices.SortStableFunc(index.Manifests, func(a, b imgspecv1.Descriptor) int { + // FIXME? With Go 1.21 and cmp.Compare available, turn instanceIsZstd into an integer score that can be compared, and generalizes + // into more algorithms? + aZstd := instanceIsZstd(a) + bZstd := instanceIsZstd(b) + switch { + case aZstd == bZstd: + return 0 + case !aZstd: // Implies bZstd + return -1 + default: // aZstd && !bZstd + return 1 + } }) } return nil @@ -209,7 +222,7 @@ func (ic instanceCandidate) isPreferredOver(other *instanceCandidate, preferGzip case ic.manifestPosition != other.manifestPosition: return ic.manifestPosition < other.manifestPosition } - panic("internal error: invalid comparision between two candidates") // This should not be reachable because in all calls we make, the two candidates differ at least in manifestPosition. + panic("internal error: invalid comparison between two candidates") // This should not be reachable because in all calls we make, the two candidates differ at least in manifestPosition. } // chooseInstance is a private equivalent to ChooseInstanceByCompression, @@ -228,13 +241,7 @@ func (index *OCI1IndexPublic) chooseInstance(ctx *types.SystemContext, preferGzi for manifestIndex, d := range index.Manifests { candidate := instanceCandidate{platformIndex: math.MaxInt, manifestPosition: manifestIndex, isZstd: instanceIsZstd(d), digest: d.Digest} if d.Platform != nil { - imagePlatform := imgspecv1.Platform{ - Architecture: d.Platform.Architecture, - OS: d.Platform.OS, - OSVersion: d.Platform.OSVersion, - OSFeatures: slices.Clone(d.Platform.OSFeatures), - Variant: d.Platform.Variant, - } + imagePlatform := ociPlatformClone(*d.Platform) platformIndex := slices.IndexFunc(wantedPlatforms, func(wantedPlatform imgspecv1.Platform) bool { return platform.MatchesPlatform(imagePlatform, wantedPlatform) }) @@ -288,13 +295,8 @@ func OCI1IndexPublicFromComponents(components []imgspecv1.Descriptor, annotation for i, component := range components { var platform *imgspecv1.Platform if component.Platform != nil { - platform = &imgspecv1.Platform{ - Architecture: component.Platform.Architecture, - OS: component.Platform.OS, - OSVersion: component.Platform.OSVersion, - OSFeatures: slices.Clone(component.Platform.OSFeatures), - Variant: component.Platform.Variant, - } + platformCopy := ociPlatformClone(*component.Platform) + platform = &platformCopy } m := imgspecv1.Descriptor{ MediaType: component.MediaType, @@ -331,22 +333,15 @@ func (index *OCI1IndexPublic) ToSchema2List() (*Schema2ListPublic, error) { Architecture: runtime.GOARCH, } } - converted := Schema2ManifestDescriptor{ + components = append(components, Schema2ManifestDescriptor{ Schema2Descriptor{ MediaType: manifest.MediaType, Size: manifest.Size, Digest: manifest.Digest, URLs: slices.Clone(manifest.URLs), }, - Schema2PlatformSpec{ - OS: platform.OS, - Architecture: platform.Architecture, - OSFeatures: slices.Clone(platform.OSFeatures), - OSVersion: platform.OSVersion, - Variant: platform.Variant, - }, - } - components = append(components, converted) + schema2PlatformSpecFromOCIPlatform(*platform), + }) } s2 := Schema2ListPublicFromComponents(components) return s2, nil @@ -420,3 +415,32 @@ func OCI1IndexFromManifest(manifest []byte) (*OCI1Index, error) { } return oci1IndexFromPublic(public), nil } + +// ociPlatformClone returns an independent copy of p. +func ociPlatformClone(p imgspecv1.Platform) imgspecv1.Platform { + // The only practical way in Go to give read-only access to an array is to copy it. + // The only practical way in Go to copy a deep structure is to either do it manually field by field, + // or to use reflection (incl. a round-trip through JSON, which uses reflection). + // + // The combination of the two is just sad, and leads to code like this, which will + // need to be updated with every new Platform field. + return imgspecv1.Platform{ + Architecture: p.Architecture, + OS: p.OS, + OSVersion: p.OSVersion, + OSFeatures: slices.Clone(p.OSFeatures), + Variant: p.Variant, + } +} + +// schema2PlatformSpecFromOCIPlatform converts an OCI platform p to the schema2 structure. +func schema2PlatformSpecFromOCIPlatform(p imgspecv1.Platform) Schema2PlatformSpec { + return Schema2PlatformSpec{ + Architecture: p.Architecture, + OS: p.OS, + OSVersion: p.OSVersion, + OSFeatures: slices.Clone(p.OSFeatures), + Variant: p.Variant, + Features: nil, + } +} diff --git a/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go b/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go index 59b1d4b9e2b..3ba0e4084f5 100644 --- a/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go +++ b/vendor/github.com/containers/image/v5/internal/pkg/platform/platform_matcher.go @@ -128,6 +128,10 @@ var compatibility = map[string][]string{ // the most compatible platform is first. // If some option (arch, os, variant) is not present, a value from current platform is detected. func WantedPlatforms(ctx *types.SystemContext) ([]imgspecv1.Platform, error) { + // Note that this does not use Platform.OSFeatures and Platform.OSVersion at all. + // The fields are not specified by the OCI specification, as of version 1.1, usefully enough + // to be interoperable, anyway. + wantedArch := runtime.GOARCH wantedVariant := "" if ctx != nil && ctx.ArchitectureChoice != "" { diff --git a/vendor/github.com/containers/image/v5/internal/streamdigest/stream_digest.go b/vendor/github.com/containers/image/v5/internal/streamdigest/stream_digest.go index 84bb656ac71..d5a5436a4d9 100644 --- a/vendor/github.com/containers/image/v5/internal/streamdigest/stream_digest.go +++ b/vendor/github.com/containers/image/v5/internal/streamdigest/stream_digest.go @@ -15,7 +15,7 @@ import ( // It is the caller's responsibility to call the cleanup function, which closes and removes the temporary file. // If an error occurs, inputInfo is not modified. func ComputeBlobInfo(sys *types.SystemContext, stream io.Reader, inputInfo *types.BlobInfo) (io.Reader, func(), error) { - diskBlob, err := os.CreateTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "stream-blob") + diskBlob, err := tmpdir.CreateBigFileTemp(sys, "stream-blob") if err != nil { return nil, nil, fmt.Errorf("creating temporary on-disk layer: %w", err) } diff --git a/vendor/github.com/containers/image/v5/internal/tmpdir/tmpdir.go b/vendor/github.com/containers/image/v5/internal/tmpdir/tmpdir.go index 809446e1897..bab73ee3340 100644 --- a/vendor/github.com/containers/image/v5/internal/tmpdir/tmpdir.go +++ b/vendor/github.com/containers/image/v5/internal/tmpdir/tmpdir.go @@ -17,10 +17,12 @@ var unixTempDirForBigFiles = builtinUnixTempDirForBigFiles // DO NOT change this, instead see unixTempDirForBigFiles above. const builtinUnixTempDirForBigFiles = "/var/tmp" +const prefix = "container_images_" + // TemporaryDirectoryForBigFiles returns a directory for temporary (big) files. // On non Windows systems it avoids the use of os.TempDir(), because the default temporary directory usually falls under /tmp // which on systemd based systems could be the unsuitable tmpfs filesystem. -func TemporaryDirectoryForBigFiles(sys *types.SystemContext) string { +func temporaryDirectoryForBigFiles(sys *types.SystemContext) string { if sys != nil && sys.BigFilesTemporaryDir != "" { return sys.BigFilesTemporaryDir } @@ -32,3 +34,11 @@ func TemporaryDirectoryForBigFiles(sys *types.SystemContext) string { } return temporaryDirectoryForBigFiles } + +func CreateBigFileTemp(sys *types.SystemContext, name string) (*os.File, error) { + return os.CreateTemp(temporaryDirectoryForBigFiles(sys), prefix+name) +} + +func MkDirBigFileTemp(sys *types.SystemContext, name string) (string, error) { + return os.MkdirTemp(temporaryDirectoryForBigFiles(sys), prefix+name) +} diff --git a/vendor/github.com/containers/image/v5/manifest/docker_schema1.go b/vendor/github.com/containers/image/v5/manifest/docker_schema1.go index 7b9c4b58fbe..a80af701afd 100644 --- a/vendor/github.com/containers/image/v5/manifest/docker_schema1.go +++ b/vendor/github.com/containers/image/v5/manifest/docker_schema1.go @@ -154,6 +154,9 @@ func (m *Schema1) UpdateLayerInfos(layerInfos []types.BlobInfo) error { // but (docker pull) ignores them in favor of computing DiffIDs from uncompressed data, except verifying the child->parent links and uniqueness. // So, we don't bother recomputing the IDs in m.History.V1Compatibility. m.FSLayers[(len(layerInfos)-1)-i].BlobSum = info.Digest + if info.CryptoOperation != types.PreserveOriginalCrypto { + return fmt.Errorf("encryption change (for layer %q) is not supported in schema1 manifests", info.Digest) + } } return nil } diff --git a/vendor/github.com/containers/image/v5/manifest/docker_schema2.go b/vendor/github.com/containers/image/v5/manifest/docker_schema2.go index 3c9745dde5d..20b721f4cad 100644 --- a/vendor/github.com/containers/image/v5/manifest/docker_schema2.go +++ b/vendor/github.com/containers/image/v5/manifest/docker_schema2.go @@ -247,6 +247,9 @@ func (m *Schema2) UpdateLayerInfos(layerInfos []types.BlobInfo) error { m.LayersDescriptors[i].Digest = info.Digest m.LayersDescriptors[i].Size = info.Size m.LayersDescriptors[i].URLs = info.URLs + if info.CryptoOperation != types.PreserveOriginalCrypto { + return fmt.Errorf("encryption change (for layer %q) is not supported in schema2 manifests", info.Digest) + } } return nil } diff --git a/vendor/github.com/containers/image/v5/manifest/oci.go b/vendor/github.com/containers/image/v5/manifest/oci.go index a70470d99a3..a85641c36ad 100644 --- a/vendor/github.com/containers/image/v5/manifest/oci.go +++ b/vendor/github.com/containers/image/v5/manifest/oci.go @@ -202,7 +202,7 @@ func (m *OCI1) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*type // Most software calling this without human intervention is going to expect the values to be realistic and relevant, // and is probably better served by failing; we can always re-visit that later if we fail now, but // if we started returning some data for OCI artifacts now, we couldn’t start failing in this function later. - return nil, manifest.NewNonImageArtifactError(m.Config.MediaType) + return nil, manifest.NewNonImageArtifactError(&m.Manifest) } config, err := configGetter(m.ConfigInfo()) @@ -253,7 +253,7 @@ func (m *OCI1) ImageID([]digest.Digest) (string, error) { // (The only known caller of ImageID is storage/storageImageDestination.computeID, // which can’t work with non-image artifacts.) if m.Config.MediaType != imgspecv1.MediaTypeImageConfig { - return "", manifest.NewNonImageArtifactError(m.Config.MediaType) + return "", manifest.NewNonImageArtifactError(&m.Manifest) } if err := m.Config.Digest.Validate(); err != nil { diff --git a/vendor/github.com/containers/image/v5/oci/archive/oci_src.go b/vendor/github.com/containers/image/v5/oci/archive/oci_src.go index 6c9ee334027..ee8409896cb 100644 --- a/vendor/github.com/containers/image/v5/oci/archive/oci_src.go +++ b/vendor/github.com/containers/image/v5/oci/archive/oci_src.go @@ -28,6 +28,18 @@ func (e ImageNotFoundError) Error() string { return fmt.Sprintf("no descriptor found for reference %q", e.ref.image) } +// ArchiveFileNotFoundError occurs when the archive file does not exist. +type ArchiveFileNotFoundError struct { + // ref is the image reference + ref ociArchiveReference + // path is the file path that was not present + path string +} + +func (e ArchiveFileNotFoundError) Error() string { + return fmt.Sprintf("archive file not found: %q", e.path) +} + type ociArchiveImageSource struct { impl.Compat diff --git a/vendor/github.com/containers/image/v5/oci/archive/oci_transport.go b/vendor/github.com/containers/image/v5/oci/archive/oci_transport.go index 53371796fbf..d5fee36310f 100644 --- a/vendor/github.com/containers/image/v5/oci/archive/oci_transport.go +++ b/vendor/github.com/containers/image/v5/oci/archive/oci_transport.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "io/fs" "os" "strings" @@ -156,7 +157,7 @@ func (t *tempDirOCIRef) deleteTempDir() error { // createOCIRef creates the oci reference of the image // If SystemContext.BigFilesTemporaryDir not "", overrides the temporary directory to use for storing big files func createOCIRef(sys *types.SystemContext, image string) (tempDirOCIRef, error) { - dir, err := os.MkdirTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "oci") + dir, err := tmpdir.MkDirBigFileTemp(sys, "oci") if err != nil { return tempDirOCIRef{}, fmt.Errorf("creating temp directory: %w", err) } @@ -171,18 +172,24 @@ func createOCIRef(sys *types.SystemContext, image string) (tempDirOCIRef, error) // creates the temporary directory and copies the tarred content to it func createUntarTempDir(sys *types.SystemContext, ref ociArchiveReference) (tempDirOCIRef, error) { + src := ref.resolvedFile + arch, err := os.Open(src) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return tempDirOCIRef{}, ArchiveFileNotFoundError{ref: ref, path: src} + } else { + return tempDirOCIRef{}, err + } + } + defer arch.Close() + tempDirRef, err := createOCIRef(sys, ref.image) if err != nil { return tempDirOCIRef{}, fmt.Errorf("creating oci reference: %w", err) } - src := ref.resolvedFile dst := tempDirRef.tempDirectory + // TODO: This can take quite some time, and should ideally be cancellable using a context.Context. - arch, err := os.Open(src) - if err != nil { - return tempDirOCIRef{}, err - } - defer arch.Close() if err := archive.NewDefaultArchiver().Untar(arch, dst, &archive.TarOptions{NoLchown: true}); err != nil { if err := tempDirRef.deleteTempDir(); err != nil { return tempDirOCIRef{}, fmt.Errorf("deleting temp directory %q: %w", tempDirRef.tempDirectory, err) diff --git a/vendor/github.com/containers/image/v5/oci/layout/oci_delete.go b/vendor/github.com/containers/image/v5/oci/layout/oci_delete.go new file mode 100644 index 00000000000..8dd54f255ae --- /dev/null +++ b/vendor/github.com/containers/image/v5/oci/layout/oci_delete.go @@ -0,0 +1,240 @@ +package layout + +import ( + "context" + "encoding/json" + "fmt" + "io/fs" + "os" + + "github.com/containers/image/v5/internal/set" + "github.com/containers/image/v5/types" + digest "github.com/opencontainers/go-digest" + imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/sirupsen/logrus" + "golang.org/x/exp/slices" +) + +// DeleteImage deletes the named image from the directory, if supported. +func (ref ociReference) DeleteImage(ctx context.Context, sys *types.SystemContext) error { + sharedBlobsDir := "" + if sys != nil && sys.OCISharedBlobDirPath != "" { + sharedBlobsDir = sys.OCISharedBlobDirPath + } + + descriptor, descriptorIndex, err := ref.getManifestDescriptor() + if err != nil { + return err + } + + var blobsUsedByImage map[digest.Digest]int + + switch descriptor.MediaType { + case imgspecv1.MediaTypeImageManifest: + blobsUsedByImage, err = ref.getBlobsUsedInSingleImage(&descriptor, sharedBlobsDir) + case imgspecv1.MediaTypeImageIndex: + blobsUsedByImage, err = ref.getBlobsUsedInImageIndex(&descriptor, sharedBlobsDir) + default: + return fmt.Errorf("unsupported mediaType in index: %q", descriptor.MediaType) + } + if err != nil { + return err + } + + blobsToDelete, err := ref.getBlobsToDelete(blobsUsedByImage, sharedBlobsDir) + if err != nil { + return err + } + + err = ref.deleteBlobs(blobsToDelete) + if err != nil { + return err + } + + return ref.deleteReferenceFromIndex(descriptorIndex) +} + +func (ref ociReference) getBlobsUsedInSingleImage(descriptor *imgspecv1.Descriptor, sharedBlobsDir string) (map[digest.Digest]int, error) { + manifest, err := ref.getManifest(descriptor, sharedBlobsDir) + if err != nil { + return nil, err + } + blobsUsedInManifest := ref.getBlobsUsedInManifest(manifest) + blobsUsedInManifest[descriptor.Digest]++ // Add the current manifest to the list of blobs used by this reference + + return blobsUsedInManifest, nil +} + +func (ref ociReference) getBlobsUsedInImageIndex(descriptor *imgspecv1.Descriptor, sharedBlobsDir string) (map[digest.Digest]int, error) { + blobPath, err := ref.blobPath(descriptor.Digest, sharedBlobsDir) + if err != nil { + return nil, err + } + index, err := parseIndex(blobPath) + if err != nil { + return nil, err + } + + blobsUsedInImageRefIndex := make(map[digest.Digest]int) + err = ref.addBlobsUsedInIndex(blobsUsedInImageRefIndex, index, sharedBlobsDir) + if err != nil { + return nil, err + } + blobsUsedInImageRefIndex[descriptor.Digest]++ // Add the nested index in the list of blobs used by this reference + + return blobsUsedInImageRefIndex, nil +} + +// Updates a map of digest with the usage count, so a blob that is referenced three times will have 3 in the map +func (ref ociReference) addBlobsUsedInIndex(destination map[digest.Digest]int, index *imgspecv1.Index, sharedBlobsDir string) error { + for _, descriptor := range index.Manifests { + destination[descriptor.Digest]++ + switch descriptor.MediaType { + case imgspecv1.MediaTypeImageManifest: + manifest, err := ref.getManifest(&descriptor, sharedBlobsDir) + if err != nil { + return err + } + for digest, count := range ref.getBlobsUsedInManifest(manifest) { + destination[digest] += count + } + case imgspecv1.MediaTypeImageIndex: + blobPath, err := ref.blobPath(descriptor.Digest, sharedBlobsDir) + if err != nil { + return err + } + index, err := parseIndex(blobPath) + if err != nil { + return err + } + err = ref.addBlobsUsedInIndex(destination, index, sharedBlobsDir) + if err != nil { + return err + } + default: + return fmt.Errorf("unsupported mediaType in index: %q", descriptor.MediaType) + } + } + + return nil +} + +func (ref ociReference) getBlobsUsedInManifest(manifest *imgspecv1.Manifest) map[digest.Digest]int { + blobsUsedInManifest := make(map[digest.Digest]int, 0) + + blobsUsedInManifest[manifest.Config.Digest]++ + for _, layer := range manifest.Layers { + blobsUsedInManifest[layer.Digest]++ + } + + return blobsUsedInManifest +} + +// This takes in a map of the digest and their usage count in the manifest to be deleted +// It will compare it to the digest usage in the root index, and return a set of the blobs that can be safely deleted +func (ref ociReference) getBlobsToDelete(blobsUsedByDescriptorToDelete map[digest.Digest]int, sharedBlobsDir string) (*set.Set[digest.Digest], error) { + rootIndex, err := ref.getIndex() + if err != nil { + return nil, err + } + blobsUsedInRootIndex := make(map[digest.Digest]int) + err = ref.addBlobsUsedInIndex(blobsUsedInRootIndex, rootIndex, sharedBlobsDir) + if err != nil { + return nil, err + } + + blobsToDelete := set.New[digest.Digest]() + + for digest, count := range blobsUsedInRootIndex { + if count-blobsUsedByDescriptorToDelete[digest] == 0 { + blobsToDelete.Add(digest) + } + } + + return blobsToDelete, nil +} + +// This transport never generates layouts where blobs for an image are both in the local blobs directory +// and the shared one; it’s either one or the other, depending on how OCISharedBlobDirPath is set. +// +// But we can’t correctly compute use counts for OCISharedBlobDirPath (because we don't know what +// the other layouts sharing that directory are, and we might not even have permission to read them), +// so we can’t really delete any blobs in that case. +// Checking the _local_ blobs directory, and deleting blobs from there, doesn't really hurt, +// in case the layout was created using some other tool or without OCISharedBlobDirPath set, so let's silently +// check for local blobs (but we should make no noise if the blobs are actually in the shared directory). +// +// So, NOTE: the blobPath() call below hard-codes "" even in calls where OCISharedBlobDirPath is set +func (ref ociReference) deleteBlobs(blobsToDelete *set.Set[digest.Digest]) error { + for _, digest := range blobsToDelete.Values() { + blobPath, err := ref.blobPath(digest, "") //Only delete in the local directory, see comment above + if err != nil { + return err + } + err = deleteBlob(blobPath) + if err != nil { + return err + } + } + + return nil +} + +func deleteBlob(blobPath string) error { + logrus.Debug(fmt.Sprintf("Deleting blob at %q", blobPath)) + + err := os.Remove(blobPath) + if err != nil && !os.IsNotExist(err) { + return err + } else { + return nil + } +} + +func (ref ociReference) deleteReferenceFromIndex(referenceIndex int) error { + index, err := ref.getIndex() + if err != nil { + return err + } + + index.Manifests = slices.Delete(index.Manifests, referenceIndex, referenceIndex+1) + + return saveJSON(ref.indexPath(), index) +} + +func saveJSON(path string, content any) error { + // If the file already exists, get its mode to preserve it + var mode fs.FileMode + existingfi, err := os.Stat(path) + if err != nil { + if !os.IsNotExist(err) { + return err + } else { // File does not exist, use default mode + mode = 0644 + } + } else { + mode = existingfi.Mode() + } + + file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode) + if err != nil { + return err + } + defer file.Close() + + return json.NewEncoder(file).Encode(content) +} + +func (ref ociReference) getManifest(descriptor *imgspecv1.Descriptor, sharedBlobsDir string) (*imgspecv1.Manifest, error) { + manifestPath, err := ref.blobPath(descriptor.Digest, sharedBlobsDir) + if err != nil { + return nil, err + } + + manifest, err := parseJSON[imgspecv1.Manifest](manifestPath) + if err != nil { + return nil, err + } + + return manifest, nil +} diff --git a/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go b/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go index 8ff43d4480f..100d16763f4 100644 --- a/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go +++ b/vendor/github.com/containers/image/v5/oci/layout/oci_dest.go @@ -19,6 +19,7 @@ import ( digest "github.com/opencontainers/go-digest" imgspec "github.com/opencontainers/image-spec/specs-go" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" + "golang.org/x/exp/slices" ) type ociImageDestination struct { @@ -84,7 +85,7 @@ func newImageDestination(sys *types.SystemContext, ref ociReference) (private.Im // Per the OCI image specification, layouts MUST have a "blobs" subdirectory, // but it MAY be empty (e.g. if we never end up calling PutBlob) // https://github.com/opencontainers/image-spec/blame/7c889fafd04a893f5c5f50b7ab9963d5d64e5242/image-layout.md#L19 - if err := ensureDirectoryExists(filepath.Join(d.ref.dir, "blobs")); err != nil { + if err := ensureDirectoryExists(filepath.Join(d.ref.dir, imgspecv1.ImageBlobsDir)); err != nil { return nil, err } return d, nil @@ -271,8 +272,8 @@ func (d *ociImageDestination) addManifest(desc *imgspecv1.Descriptor) { return } } - // It's a new entry to be added to the index. - d.index.Manifests = append(d.index.Manifests, *desc) + // It's a new entry to be added to the index. Use slices.Clone() to avoid a remote dependency on how d.index was created. + d.index.Manifests = append(slices.Clone(d.index.Manifests), *desc) } // Commit marks the process of storing the image as successful and asks for the image to be persisted. @@ -283,7 +284,13 @@ func (d *ociImageDestination) addManifest(desc *imgspecv1.Descriptor) { // - Uploaded data MAY be visible to others before Commit() is called // - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed) func (d *ociImageDestination) Commit(context.Context, types.UnparsedImage) error { - if err := os.WriteFile(d.ref.ociLayoutPath(), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0644); err != nil { + layoutBytes, err := json.Marshal(imgspecv1.ImageLayout{ + Version: imgspecv1.ImageLayoutVersion, + }) + if err != nil { + return err + } + if err := os.WriteFile(d.ref.ociLayoutPath(), layoutBytes, 0644); err != nil { return err } indexJSON, err := json.Marshal(d.index) diff --git a/vendor/github.com/containers/image/v5/oci/layout/oci_src.go b/vendor/github.com/containers/image/v5/oci/layout/oci_src.go index 6b423f3b05d..f5f1debc9fe 100644 --- a/vendor/github.com/containers/image/v5/oci/layout/oci_src.go +++ b/vendor/github.com/containers/image/v5/oci/layout/oci_src.go @@ -60,7 +60,7 @@ func newImageSource(sys *types.SystemContext, ref ociReference) (private.ImageSo client := &http.Client{} client.Transport = tr - descriptor, err := ref.getManifestDescriptor() + descriptor, _, err := ref.getManifestDescriptor() if err != nil { return nil, err } diff --git a/vendor/github.com/containers/image/v5/oci/layout/oci_transport.go b/vendor/github.com/containers/image/v5/oci/layout/oci_transport.go index 6586b84402e..1e26dc52443 100644 --- a/vendor/github.com/containers/image/v5/oci/layout/oci_transport.go +++ b/vendor/github.com/containers/image/v5/oci/layout/oci_transport.go @@ -160,48 +160,56 @@ func (ref ociReference) NewImage(ctx context.Context, sys *types.SystemContext) // getIndex returns a pointer to the index references by this ociReference. If an error occurs opening an index nil is returned together // with an error. func (ref ociReference) getIndex() (*imgspecv1.Index, error) { - indexJSON, err := os.Open(ref.indexPath()) + return parseIndex(ref.indexPath()) +} + +func parseIndex(path string) (*imgspecv1.Index, error) { + return parseJSON[imgspecv1.Index](path) +} + +func parseJSON[T any](path string) (*T, error) { + content, err := os.Open(path) if err != nil { return nil, err } - defer indexJSON.Close() + defer content.Close() - index := &imgspecv1.Index{} - if err := json.NewDecoder(indexJSON).Decode(index); err != nil { + obj := new(T) + if err := json.NewDecoder(content).Decode(obj); err != nil { return nil, err } - return index, nil + return obj, nil } -func (ref ociReference) getManifestDescriptor() (imgspecv1.Descriptor, error) { +func (ref ociReference) getManifestDescriptor() (imgspecv1.Descriptor, int, error) { index, err := ref.getIndex() if err != nil { - return imgspecv1.Descriptor{}, err + return imgspecv1.Descriptor{}, -1, err } if ref.image == "" { // return manifest if only one image is in the oci directory if len(index.Manifests) != 1 { // ask user to choose image when more than one image in the oci directory - return imgspecv1.Descriptor{}, ErrMoreThanOneImage + return imgspecv1.Descriptor{}, -1, ErrMoreThanOneImage } - return index.Manifests[0], nil + return index.Manifests[0], 0, nil } else { // if image specified, look through all manifests for a match var unsupportedMIMETypes []string - for _, md := range index.Manifests { + for i, md := range index.Manifests { if refName, ok := md.Annotations[imgspecv1.AnnotationRefName]; ok && refName == ref.image { if md.MediaType == imgspecv1.MediaTypeImageManifest || md.MediaType == imgspecv1.MediaTypeImageIndex { - return md, nil + return md, i, nil } unsupportedMIMETypes = append(unsupportedMIMETypes, md.MediaType) } } if len(unsupportedMIMETypes) != 0 { - return imgspecv1.Descriptor{}, fmt.Errorf("reference %q matches unsupported manifest MIME types %q", ref.image, unsupportedMIMETypes) + return imgspecv1.Descriptor{}, -1, fmt.Errorf("reference %q matches unsupported manifest MIME types %q", ref.image, unsupportedMIMETypes) } } - return imgspecv1.Descriptor{}, ImageNotFoundError{ref} + return imgspecv1.Descriptor{}, -1, ImageNotFoundError{ref} } // LoadManifestDescriptor loads the manifest descriptor to be used to retrieve the image name @@ -211,7 +219,8 @@ func LoadManifestDescriptor(imgRef types.ImageReference) (imgspecv1.Descriptor, if !ok { return imgspecv1.Descriptor{}, errors.New("error typecasting, need type ociRef") } - return ociRef.getManifestDescriptor() + md, _, err := ociRef.getManifestDescriptor() + return md, err } // NewImageSource returns a types.ImageSource for this reference. @@ -226,19 +235,14 @@ func (ref ociReference) NewImageDestination(ctx context.Context, sys *types.Syst return newImageDestination(sys, ref) } -// DeleteImage deletes the named image from the registry, if supported. -func (ref ociReference) DeleteImage(ctx context.Context, sys *types.SystemContext) error { - return errors.New("Deleting images not implemented for oci: images") -} - // ociLayoutPath returns a path for the oci-layout within a directory using OCI conventions. func (ref ociReference) ociLayoutPath() string { - return filepath.Join(ref.dir, "oci-layout") + return filepath.Join(ref.dir, imgspecv1.ImageLayoutFile) } // indexPath returns a path for the index.json within a directory using OCI conventions. func (ref ociReference) indexPath() string { - return filepath.Join(ref.dir, "index.json") + return filepath.Join(ref.dir, imgspecv1.ImageIndexFile) } // blobPath returns a path for a blob within a directory using OCI image-layout conventions. @@ -246,9 +250,11 @@ func (ref ociReference) blobPath(digest digest.Digest, sharedBlobDir string) (st if err := digest.Validate(); err != nil { return "", fmt.Errorf("unexpected digest reference %s: %w", digest, err) } - blobDir := filepath.Join(ref.dir, "blobs") + var blobDir string if sharedBlobDir != "" { blobDir = sharedBlobDir + } else { + blobDir = filepath.Join(ref.dir, imgspecv1.ImageBlobsDir) } return filepath.Join(blobDir, digest.Algorithm().String(), digest.Hex()), nil } diff --git a/vendor/github.com/containers/image/v5/openshift/openshift.go b/vendor/github.com/containers/image/v5/openshift/openshift.go index f3d5662e669..2c69afbe94f 100644 --- a/vendor/github.com/containers/image/v5/openshift/openshift.go +++ b/vendor/github.com/containers/image/v5/openshift/openshift.go @@ -65,6 +65,10 @@ func newOpenshiftClient(ref openshiftReference) (*openshiftClient, error) { }, nil } +func (c *openshiftClient) close() { + c.httpClient.CloseIdleConnections() +} + // doRequest performs a correctly authenticated request to a specified path, and returns response body or an error object. func (c *openshiftClient) doRequest(ctx context.Context, method, path string, requestBody []byte) ([]byte, error) { requestURL := *c.baseURL diff --git a/vendor/github.com/containers/image/v5/openshift/openshift_dest.go b/vendor/github.com/containers/image/v5/openshift/openshift_dest.go index 7b1b5dfcded..50a5339e1b8 100644 --- a/vendor/github.com/containers/image/v5/openshift/openshift_dest.go +++ b/vendor/github.com/containers/image/v5/openshift/openshift_dest.go @@ -71,7 +71,9 @@ func (d *openshiftImageDestination) Reference() types.ImageReference { // Close removes resources associated with an initialized ImageDestination, if any. func (d *openshiftImageDestination) Close() error { - return d.docker.Close() + err := d.docker.Close() + d.client.close() + return err } func (d *openshiftImageDestination) SupportedManifestMIMETypes() []string { diff --git a/vendor/github.com/containers/image/v5/openshift/openshift_src.go b/vendor/github.com/containers/image/v5/openshift/openshift_src.go index 93ba8d10e30..0ac0127ee77 100644 --- a/vendor/github.com/containers/image/v5/openshift/openshift_src.go +++ b/vendor/github.com/containers/image/v5/openshift/openshift_src.go @@ -60,14 +60,15 @@ func (s *openshiftImageSource) Reference() types.ImageReference { // Close removes resources associated with an initialized ImageSource, if any. func (s *openshiftImageSource) Close() error { + var err error if s.docker != nil { - err := s.docker.Close() + err = s.docker.Close() s.docker = nil - - return err } - return nil + s.client.close() + + return err } // GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available). diff --git a/vendor/github.com/containers/image/v5/pkg/blobinfocache/boltdb/boltdb.go b/vendor/github.com/containers/image/v5/pkg/blobinfocache/boltdb/boltdb.go deleted file mode 100644 index a472efd95bf..00000000000 --- a/vendor/github.com/containers/image/v5/pkg/blobinfocache/boltdb/boltdb.go +++ /dev/null @@ -1,393 +0,0 @@ -// Package boltdb implements a BlobInfoCache backed by BoltDB. -package boltdb - -import ( - "fmt" - "os" - "sync" - "time" - - "github.com/containers/image/v5/internal/blobinfocache" - "github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize" - "github.com/containers/image/v5/types" - "github.com/opencontainers/go-digest" - "github.com/sirupsen/logrus" - bolt "go.etcd.io/bbolt" -) - -var ( - // NOTE: There is no versioning data inside the file; this is a “cache”, so on an incompatible format upgrade - // we can simply start over with a different filename; update blobInfoCacheFilename. - - // FIXME: For CRI-O, does this need to hide information between different users? - - // uncompressedDigestBucket stores a mapping from any digest to an uncompressed digest. - uncompressedDigestBucket = []byte("uncompressedDigest") - // digestCompressorBucket stores a mapping from any digest to a compressor, or blobinfocache.Uncompressed - // It may not exist in caches created by older versions, even if uncompressedDigestBucket is present. - digestCompressorBucket = []byte("digestCompressor") - // digestByUncompressedBucket stores a bucket per uncompressed digest, with the bucket containing a set of digests for that uncompressed digest - // (as a set of key=digest, value="" pairs) - digestByUncompressedBucket = []byte("digestByUncompressed") - // knownLocationsBucket stores a nested structure of buckets, keyed by (transport name, scope string, blob digest), ultimately containing - // a bucket of (opaque location reference, BinaryMarshaller-encoded time.Time value). - knownLocationsBucket = []byte("knownLocations") -) - -// Concurrency: -// See https://www.sqlite.org/src/artifact/c230a7a24?ln=994-1081 for all the issues with locks, which make it extremely -// difficult to use a single BoltDB file from multiple threads/goroutines inside a process. So, we punt and only allow one at a time. - -// pathLock contains a lock for a specific BoltDB database path. -type pathLock struct { - refCount int64 // Number of threads/goroutines owning or waiting on this lock. Protected by global pathLocksMutex, NOT by the mutex field below! - mutex sync.Mutex // Owned by the thread/goroutine allowed to access the BoltDB database. -} - -var ( - // pathLocks contains a lock for each currently open file. - // This must be global so that independently created instances of boltDBCache exclude each other. - // The map is protected by pathLocksMutex. - // FIXME? Should this be based on device:inode numbers instead of paths instead? - pathLocks = map[string]*pathLock{} - pathLocksMutex = sync.Mutex{} -) - -// lockPath obtains the pathLock for path. -// The caller must call unlockPath eventually. -func lockPath(path string) { - pl := func() *pathLock { // A scope for defer - pathLocksMutex.Lock() - defer pathLocksMutex.Unlock() - pl, ok := pathLocks[path] - if ok { - pl.refCount++ - } else { - pl = &pathLock{refCount: 1, mutex: sync.Mutex{}} - pathLocks[path] = pl - } - return pl - }() - pl.mutex.Lock() -} - -// unlockPath releases the pathLock for path. -func unlockPath(path string) { - pathLocksMutex.Lock() - defer pathLocksMutex.Unlock() - pl, ok := pathLocks[path] - if !ok { - // Should this return an error instead? BlobInfoCache ultimately ignores errors… - panic(fmt.Sprintf("Internal error: unlocking nonexistent lock for path %s", path)) - } - pl.mutex.Unlock() - pl.refCount-- - if pl.refCount == 0 { - delete(pathLocks, path) - } -} - -// cache is a BlobInfoCache implementation which uses a BoltDB file at the specified path. -// -// Note that we don’t keep the database open across operations, because that would lock the file and block any other -// users; instead, we need to open/close it for every single write or lookup. -type cache struct { - path string -} - -// New returns a BlobInfoCache implementation which uses a BoltDB file at path. -// -// Most users should call blobinfocache.DefaultCache instead. -func New(path string) types.BlobInfoCache { - return new2(path) -} -func new2(path string) *cache { - return &cache{path: path} -} - -// view returns runs the specified fn within a read-only transaction on the database. -func (bdc *cache) view(fn func(tx *bolt.Tx) error) (retErr error) { - // bolt.Open(bdc.path, 0600, &bolt.Options{ReadOnly: true}) will, if the file does not exist, - // nevertheless create it, but with an O_RDONLY file descriptor, try to initialize it, and fail — while holding - // a read lock, blocking any future writes. - // Hence this preliminary check, which is RACY: Another process could remove the file - // between the Lstat call and opening the database. - if _, err := os.Lstat(bdc.path); err != nil && os.IsNotExist(err) { - return err - } - - lockPath(bdc.path) - defer unlockPath(bdc.path) - db, err := bolt.Open(bdc.path, 0600, &bolt.Options{ReadOnly: true}) - if err != nil { - return err - } - defer func() { - if err := db.Close(); retErr == nil && err != nil { - retErr = err - } - }() - - return db.View(fn) -} - -// update returns runs the specified fn within a read-write transaction on the database. -func (bdc *cache) update(fn func(tx *bolt.Tx) error) (retErr error) { - lockPath(bdc.path) - defer unlockPath(bdc.path) - db, err := bolt.Open(bdc.path, 0600, nil) - if err != nil { - return err - } - defer func() { - if err := db.Close(); retErr == nil && err != nil { - retErr = err - } - }() - - return db.Update(fn) -} - -// uncompressedDigest implements BlobInfoCache.UncompressedDigest within the provided read-only transaction. -func (bdc *cache) uncompressedDigest(tx *bolt.Tx, anyDigest digest.Digest) digest.Digest { - if b := tx.Bucket(uncompressedDigestBucket); b != nil { - if uncompressedBytes := b.Get([]byte(anyDigest.String())); uncompressedBytes != nil { - d, err := digest.Parse(string(uncompressedBytes)) - if err == nil { - return d - } - // FIXME? Log err (but throttle the log volume on repeated accesses)? - } - } - // Presence in digestsByUncompressedBucket implies that anyDigest must already refer to an uncompressed digest. - // This way we don't have to waste storage space with trivial (uncompressed, uncompressed) mappings - // when we already record a (compressed, uncompressed) pair. - if b := tx.Bucket(digestByUncompressedBucket); b != nil { - if b = b.Bucket([]byte(anyDigest.String())); b != nil { - c := b.Cursor() - if k, _ := c.First(); k != nil { // The bucket is non-empty - return anyDigest - } - } - } - return "" -} - -// UncompressedDigest returns an uncompressed digest corresponding to anyDigest. -// May return anyDigest if it is known to be uncompressed. -// Returns "" if nothing is known about the digest (it may be compressed or uncompressed). -func (bdc *cache) UncompressedDigest(anyDigest digest.Digest) digest.Digest { - var res digest.Digest - if err := bdc.view(func(tx *bolt.Tx) error { - res = bdc.uncompressedDigest(tx, anyDigest) - return nil - }); err != nil { // Including os.IsNotExist(err) - return "" // FIXME? Log err (but throttle the log volume on repeated accesses)? - } - return res -} - -// RecordDigestUncompressedPair records that the uncompressed version of anyDigest is uncompressed. -// It’s allowed for anyDigest == uncompressed. -// WARNING: Only call this for LOCALLY VERIFIED data; don’t record a digest pair just because some remote author claims so (e.g. -// because a manifest/config pair exists); otherwise the cache could be poisoned and allow substituting unexpected blobs. -// (Eventually, the DiffIDs in image config could detect the substitution, but that may be too late, and not all image formats contain that data.) -func (bdc *cache) RecordDigestUncompressedPair(anyDigest digest.Digest, uncompressed digest.Digest) { - _ = bdc.update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists(uncompressedDigestBucket) - if err != nil { - return err - } - key := []byte(anyDigest.String()) - if previousBytes := b.Get(key); previousBytes != nil { - previous, err := digest.Parse(string(previousBytes)) - if err != nil { - return err - } - if previous != uncompressed { - logrus.Warnf("Uncompressed digest for blob %s previously recorded as %s, now %s", anyDigest, previous, uncompressed) - } - } - if err := b.Put(key, []byte(uncompressed.String())); err != nil { - return err - } - - b, err = tx.CreateBucketIfNotExists(digestByUncompressedBucket) - if err != nil { - return err - } - b, err = b.CreateBucketIfNotExists([]byte(uncompressed.String())) - if err != nil { - return err - } - if err := b.Put([]byte(anyDigest.String()), []byte{}); err != nil { // Possibly writing the same []byte{} presence marker again. - return err - } - return nil - }) // FIXME? Log error (but throttle the log volume on repeated accesses)? -} - -// RecordDigestCompressorName records that the blob with digest anyDigest was compressed with the specified -// compressor, or is blobinfocache.Uncompressed. -// WARNING: Only call this for LOCALLY VERIFIED data; don’t record a digest pair just because some remote author claims so (e.g. -// because a manifest/config pair exists); otherwise the cache could be poisoned and allow substituting unexpected blobs. -// (Eventually, the DiffIDs in image config could detect the substitution, but that may be too late, and not all image formats contain that data.) -func (bdc *cache) RecordDigestCompressorName(anyDigest digest.Digest, compressorName string) { - _ = bdc.update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists(digestCompressorBucket) - if err != nil { - return err - } - key := []byte(anyDigest.String()) - if previousBytes := b.Get(key); previousBytes != nil { - if string(previousBytes) != compressorName { - logrus.Warnf("Compressor for blob with digest %s previously recorded as %s, now %s", anyDigest, string(previousBytes), compressorName) - } - } - if compressorName == blobinfocache.UnknownCompression { - return b.Delete(key) - } - return b.Put(key, []byte(compressorName)) - }) // FIXME? Log error (but throttle the log volume on repeated accesses)? -} - -// RecordKnownLocation records that a blob with the specified digest exists within the specified (transport, scope) scope, -// and can be reused given the opaque location data. -func (bdc *cache) RecordKnownLocation(transport types.ImageTransport, scope types.BICTransportScope, blobDigest digest.Digest, location types.BICLocationReference) { - _ = bdc.update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists(knownLocationsBucket) - if err != nil { - return err - } - b, err = b.CreateBucketIfNotExists([]byte(transport.Name())) - if err != nil { - return err - } - b, err = b.CreateBucketIfNotExists([]byte(scope.Opaque)) - if err != nil { - return err - } - b, err = b.CreateBucketIfNotExists([]byte(blobDigest.String())) - if err != nil { - return err - } - value, err := time.Now().MarshalBinary() - if err != nil { - return err - } - if err := b.Put([]byte(location.Opaque), value); err != nil { // Possibly overwriting an older entry. - return err - } - return nil - }) // FIXME? Log error (but throttle the log volume on repeated accesses)? -} - -// appendReplacementCandidates creates prioritize.CandidateWithTime values for digest in scopeBucket with corresponding compression info from compressionBucket (if compressionBucket is not nil), and returns the result of appending them to candidates. -func (bdc *cache) appendReplacementCandidates(candidates []prioritize.CandidateWithTime, scopeBucket, compressionBucket *bolt.Bucket, digest digest.Digest, requireCompressionInfo bool) []prioritize.CandidateWithTime { - digestKey := []byte(digest.String()) - b := scopeBucket.Bucket(digestKey) - if b == nil { - return candidates - } - compressorName := blobinfocache.UnknownCompression - if compressionBucket != nil { - // the bucket won't exist if the cache was created by a v1 implementation and - // hasn't yet been updated by a v2 implementation - if compressorNameValue := compressionBucket.Get(digestKey); len(compressorNameValue) > 0 { - compressorName = string(compressorNameValue) - } - } - if compressorName == blobinfocache.UnknownCompression && requireCompressionInfo { - return candidates - } - _ = b.ForEach(func(k, v []byte) error { - t := time.Time{} - if err := t.UnmarshalBinary(v); err != nil { - return err - } - candidates = append(candidates, prioritize.CandidateWithTime{ - Candidate: blobinfocache.BICReplacementCandidate2{ - Digest: digest, - CompressorName: compressorName, - Location: types.BICLocationReference{Opaque: string(k)}, - }, - LastSeen: t, - }) - return nil - }) // FIXME? Log error (but throttle the log volume on repeated accesses)? - return candidates -} - -// CandidateLocations2 returns a prioritized, limited, number of blobs and their locations that could possibly be reused -// within the specified (transport scope) (if they still exist, which is not guaranteed). -// -// If !canSubstitute, the returned candidates will match the submitted digest exactly; if canSubstitute, -// data from previous RecordDigestUncompressedPair calls is used to also look up variants of the blob which have the same -// uncompressed digest. -func (bdc *cache) CandidateLocations2(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute bool) []blobinfocache.BICReplacementCandidate2 { - return bdc.candidateLocations(transport, scope, primaryDigest, canSubstitute, true) -} - -func (bdc *cache) candidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute, requireCompressionInfo bool) []blobinfocache.BICReplacementCandidate2 { - res := []prioritize.CandidateWithTime{} - var uncompressedDigestValue digest.Digest // = "" - if err := bdc.view(func(tx *bolt.Tx) error { - scopeBucket := tx.Bucket(knownLocationsBucket) - if scopeBucket == nil { - return nil - } - scopeBucket = scopeBucket.Bucket([]byte(transport.Name())) - if scopeBucket == nil { - return nil - } - scopeBucket = scopeBucket.Bucket([]byte(scope.Opaque)) - if scopeBucket == nil { - return nil - } - // compressionBucket won't have been created if previous writers never recorded info about compression, - // and we don't want to fail just because of that - compressionBucket := tx.Bucket(digestCompressorBucket) - - res = bdc.appendReplacementCandidates(res, scopeBucket, compressionBucket, primaryDigest, requireCompressionInfo) - if canSubstitute { - if uncompressedDigestValue = bdc.uncompressedDigest(tx, primaryDigest); uncompressedDigestValue != "" { - b := tx.Bucket(digestByUncompressedBucket) - if b != nil { - b = b.Bucket([]byte(uncompressedDigestValue.String())) - if b != nil { - if err := b.ForEach(func(k, _ []byte) error { - d, err := digest.Parse(string(k)) - if err != nil { - return err - } - if d != primaryDigest && d != uncompressedDigestValue { - res = bdc.appendReplacementCandidates(res, scopeBucket, compressionBucket, d, requireCompressionInfo) - } - return nil - }); err != nil { - return err - } - } - } - if uncompressedDigestValue != primaryDigest { - res = bdc.appendReplacementCandidates(res, scopeBucket, compressionBucket, uncompressedDigestValue, requireCompressionInfo) - } - } - } - return nil - }); err != nil { // Including os.IsNotExist(err) - return []blobinfocache.BICReplacementCandidate2{} // FIXME? Log err (but throttle the log volume on repeated accesses)? - } - - return prioritize.DestructivelyPrioritizeReplacementCandidates(res, primaryDigest, uncompressedDigestValue) -} - -// CandidateLocations returns a prioritized, limited, number of blobs and their locations that could possibly be reused -// within the specified (transport scope) (if they still exist, which is not guaranteed). -// -// If !canSubstitute, the returned cadidates will match the submitted digest exactly; if canSubstitute, -// data from previous RecordDigestUncompressedPair calls is used to also look up variants of the blob which have the same -// uncompressed digest. -func (bdc *cache) CandidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute bool) []types.BICReplacementCandidate { - return blobinfocache.CandidateLocationsFromV2(bdc.candidateLocations(transport, scope, primaryDigest, canSubstitute, false)) -} diff --git a/vendor/github.com/containers/image/v5/pkg/blobinfocache/default.go b/vendor/github.com/containers/image/v5/pkg/blobinfocache/default.go index 83034b618d9..037572b0eec 100644 --- a/vendor/github.com/containers/image/v5/pkg/blobinfocache/default.go +++ b/vendor/github.com/containers/image/v5/pkg/blobinfocache/default.go @@ -6,8 +6,8 @@ import ( "path/filepath" "github.com/containers/image/v5/internal/rootless" - "github.com/containers/image/v5/pkg/blobinfocache/boltdb" "github.com/containers/image/v5/pkg/blobinfocache/memory" + "github.com/containers/image/v5/pkg/blobinfocache/sqlite" "github.com/containers/image/v5/types" "github.com/sirupsen/logrus" ) @@ -15,7 +15,7 @@ import ( const ( // blobInfoCacheFilename is the file name used for blob info caches. // If the format changes in an incompatible way, increase the version number. - blobInfoCacheFilename = "blob-info-cache-v1.boltdb" + blobInfoCacheFilename = "blob-info-cache-v1.sqlite" // systemBlobInfoCacheDir is the directory containing the blob info cache (in blobInfocacheFilename) for root-running processes. systemBlobInfoCacheDir = "/var/lib/containers/cache" ) @@ -57,10 +57,20 @@ func DefaultCache(sys *types.SystemContext) types.BlobInfoCache { } path := filepath.Join(dir, blobInfoCacheFilename) if err := os.MkdirAll(dir, 0700); err != nil { - logrus.Debugf("Error creating parent directories for %s, using a memory-only cache: %v", blobInfoCacheFilename, err) + logrus.Debugf("Error creating parent directories for %s, using a memory-only cache: %v", path, err) return memory.New() } - logrus.Debugf("Using blob info cache at %s", path) - return boltdb.New(path) + // It might make sense to keep a single sqlite cache object, and a single initialized sqlite connection, open + // as global singleton, for the vast majority of callers who don’t override thde cache location. + // OTOH that would keep a file descriptor open forever, even for long-term callers who copy images rarely, + // and the performance benefit to this over using an Open()/Close() pair for a single image copy is < 10%. + + cache, err := sqlite.New(path) + if err != nil { + logrus.Debugf("Error creating a SQLite blob info cache at %s, using a memory-only cache: %v", path, err) + return memory.New() + } + logrus.Debugf("Using SQLite blob info cache at %s", path) + return cache } diff --git a/vendor/github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize/prioritize.go b/vendor/github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize/prioritize.go index 6f5506d94c1..97562687c86 100644 --- a/vendor/github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize/prioritize.go +++ b/vendor/github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize/prioritize.go @@ -10,15 +10,20 @@ import ( "github.com/opencontainers/go-digest" ) -// replacementAttempts is the number of blob replacement candidates returned by destructivelyPrioritizeReplacementCandidates, +// replacementAttempts is the number of blob replacement candidates with known location returned by destructivelyPrioritizeReplacementCandidates, // and therefore ultimately by types.BlobInfoCache.CandidateLocations. // This is a heuristic/guess, and could well use a different value. const replacementAttempts = 5 +// replacementUnknownLocationAttempts is the number of blob replacement candidates with unknown Location returned by destructivelyPrioritizeReplacementCandidates, +// and therefore ultimately by blobinfocache.BlobInfoCache2.CandidateLocations2. +// This is a heuristic/guess, and could well use a different value. +const replacementUnknownLocationAttempts = 2 + // CandidateWithTime is the input to types.BICReplacementCandidate prioritization. type CandidateWithTime struct { Candidate blobinfocache.BICReplacementCandidate2 // The replacement candidate - LastSeen time.Time // Time the candidate was last known to exist (either read or written) + LastSeen time.Time // Time the candidate was last known to exist (either read or written) (not set for Candidate.UnknownLocation) } // candidateSortState is a local state implementing sort.Interface on candidates to prioritize, @@ -77,34 +82,58 @@ func (css *candidateSortState) Swap(i, j int) { css.cs[i], css.cs[j] = css.cs[j], css.cs[i] } -// destructivelyPrioritizeReplacementCandidatesWithMax is destructivelyPrioritizeReplacementCandidates with a parameter for the -// number of entries to limit, only to make testing simpler. -func destructivelyPrioritizeReplacementCandidatesWithMax(cs []CandidateWithTime, primaryDigest, uncompressedDigest digest.Digest, maxCandidates int) []blobinfocache.BICReplacementCandidate2 { +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// destructivelyPrioritizeReplacementCandidatesWithMax is destructivelyPrioritizeReplacementCandidates with parameters for the +// number of entries to limit for known and unknown location separately, only to make testing simpler. +// TODO: following function is not destructive any more in the nature instead priortized result is actually copies of the original +// candidate set, so In future we might wanna re-name this public API and remove the destructive prefix. +func destructivelyPrioritizeReplacementCandidatesWithMax(cs []CandidateWithTime, primaryDigest, uncompressedDigest digest.Digest, totalLimit int, noLocationLimit int) []blobinfocache.BICReplacementCandidate2 { + // split unknown candidates and known candidates + // and limit them seperately. + var knownLocationCandidates []CandidateWithTime + var unknownLocationCandidates []CandidateWithTime // We don't need to use sort.Stable() because nanosecond timestamps are (presumably?) unique, so no two elements should // compare equal. + // FIXME: Use slices.SortFunc after we update to Go 1.20 (Go 1.21?) and Time.Compare and cmp.Compare are available. sort.Sort(&candidateSortState{ cs: cs, primaryDigest: primaryDigest, uncompressedDigest: uncompressedDigest, }) + for _, candidate := range cs { + if candidate.Candidate.UnknownLocation { + unknownLocationCandidates = append(unknownLocationCandidates, candidate) + } else { + knownLocationCandidates = append(knownLocationCandidates, candidate) + } + } - resLength := len(cs) - if resLength > maxCandidates { - resLength = maxCandidates + knownLocationCandidatesUsed := min(len(knownLocationCandidates), totalLimit) + remainingCapacity := totalLimit - knownLocationCandidatesUsed + unknownLocationCandidatesUsed := min(noLocationLimit, min(remainingCapacity, len(unknownLocationCandidates))) + res := make([]blobinfocache.BICReplacementCandidate2, knownLocationCandidatesUsed) + for i := 0; i < knownLocationCandidatesUsed; i++ { + res[i] = knownLocationCandidates[i].Candidate } - res := make([]blobinfocache.BICReplacementCandidate2, resLength) - for i := range res { - res[i] = cs[i].Candidate + // If candidates with unknown location are found, lets add them to final list + for i := 0; i < unknownLocationCandidatesUsed; i++ { + res = append(res, unknownLocationCandidates[i].Candidate) } return res } // DestructivelyPrioritizeReplacementCandidates consumes AND DESTROYS an array of possible replacement candidates with their last known existence times, -// the primary digest the user actually asked for, and the corresponding uncompressed digest (if known, possibly equal to the primary digest), -// and returns an appropriately prioritized and/or trimmed result suitable for a return value from types.BlobInfoCache.CandidateLocations. +// the primary digest the user actually asked for, the corresponding uncompressed digest (if known, possibly equal to the primary digest) returns an +// appropriately prioritized and/or trimmed result suitable for a return value from types.BlobInfoCache.CandidateLocations. // // WARNING: The array of candidates is destructively modified. (The implementation of this function could of course // make a copy, but all CandidateLocations implementations build the slice of candidates only for the single purpose of calling this function anyway.) func DestructivelyPrioritizeReplacementCandidates(cs []CandidateWithTime, primaryDigest, uncompressedDigest digest.Digest) []blobinfocache.BICReplacementCandidate2 { - return destructivelyPrioritizeReplacementCandidatesWithMax(cs, primaryDigest, uncompressedDigest, replacementAttempts) + return destructivelyPrioritizeReplacementCandidatesWithMax(cs, primaryDigest, uncompressedDigest, replacementAttempts, replacementUnknownLocationAttempts) } diff --git a/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go b/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go index 427610fab05..cfad16b2ec4 100644 --- a/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go +++ b/vendor/github.com/containers/image/v5/pkg/blobinfocache/memory/memory.go @@ -27,7 +27,7 @@ type cache struct { uncompressedDigests map[digest.Digest]digest.Digest digestsByUncompressed map[digest.Digest]*set.Set[digest.Digest] // stores a set of digests for each uncompressed digest knownLocations map[locationKey]map[types.BICLocationReference]time.Time // stores last known existence time for each location reference - compressors map[digest.Digest]string // stores a compressor name, or blobinfocache.Unknown, for each digest + compressors map[digest.Digest]string // stores a compressor name, or blobinfocache.Unknown (not blobinfocache.UnknownCompression), for each digest } // New returns a BlobInfoCache implementation which is in-memory only. @@ -51,6 +51,15 @@ func new2() *cache { } } +// Open() sets up the cache for future accesses, potentially acquiring costly state. Each Open() must be paired with a Close(). +// Note that public callers may call the types.BlobInfoCache operations without Open()/Close(). +func (mem *cache) Open() { +} + +// Close destroys state created by Open(). +func (mem *cache) Close() { +} + // UncompressedDigest returns an uncompressed digest corresponding to anyDigest. // May return anyDigest if it is known to be uncompressed. // Returns "" if nothing is known about the digest (it may be compressed or uncompressed). @@ -114,6 +123,9 @@ func (mem *cache) RecordKnownLocation(transport types.ImageTransport, scope type func (mem *cache) RecordDigestCompressorName(blobDigest digest.Digest, compressorName string) { mem.mutex.Lock() defer mem.mutex.Unlock() + if previous, ok := mem.compressors[blobDigest]; ok && previous != compressorName { + logrus.Warnf("Compressor for blob with digest %s previously recorded as %s, now %s", blobDigest, previous, compressorName) + } if compressorName == blobinfocache.UnknownCompression { delete(mem.compressors, blobDigest) return @@ -121,24 +133,39 @@ func (mem *cache) RecordDigestCompressorName(blobDigest digest.Digest, compresso mem.compressors[blobDigest] = compressorName } -// appendReplacementCandidates creates prioritize.CandidateWithTime values for (transport, scope, digest), and returns the result of appending them to candidates. -func (mem *cache) appendReplacementCandidates(candidates []prioritize.CandidateWithTime, transport types.ImageTransport, scope types.BICTransportScope, digest digest.Digest, requireCompressionInfo bool) []prioritize.CandidateWithTime { +// appendReplacementCandidates creates prioritize.CandidateWithTime values for digest in memory +// with corresponding compression info from mem.compressors, and returns the result of appending +// them to candidates. v2Output allows including candidates with unknown location, and filters out +// candidates with unknown compression. +func (mem *cache) appendReplacementCandidates(candidates []prioritize.CandidateWithTime, transport types.ImageTransport, scope types.BICTransportScope, digest digest.Digest, v2Output bool) []prioritize.CandidateWithTime { + compressorName := blobinfocache.UnknownCompression + if v, ok := mem.compressors[digest]; ok { + compressorName = v + } + if compressorName == blobinfocache.UnknownCompression && v2Output { + return candidates + } locations := mem.knownLocations[locationKey{transport: transport.Name(), scope: scope, blobDigest: digest}] // nil if not present - for l, t := range locations { - compressorName, compressorKnown := mem.compressors[digest] - if !compressorKnown { - if requireCompressionInfo { - continue - } - compressorName = blobinfocache.UnknownCompression + if len(locations) > 0 { + for l, t := range locations { + candidates = append(candidates, prioritize.CandidateWithTime{ + Candidate: blobinfocache.BICReplacementCandidate2{ + Digest: digest, + CompressorName: compressorName, + Location: l, + }, + LastSeen: t, + }) } + } else if v2Output { candidates = append(candidates, prioritize.CandidateWithTime{ Candidate: blobinfocache.BICReplacementCandidate2{ - Digest: digest, - CompressorName: compressorName, - Location: l, + Digest: digest, + CompressorName: compressorName, + UnknownLocation: true, + Location: types.BICLocationReference{Opaque: ""}, }, - LastSeen: t, + LastSeen: time.Time{}, }) } return candidates @@ -154,7 +181,7 @@ func (mem *cache) CandidateLocations(transport types.ImageTransport, scope types return blobinfocache.CandidateLocationsFromV2(mem.candidateLocations(transport, scope, primaryDigest, canSubstitute, false)) } -// CandidateLocations2 returns a prioritized, limited, number of blobs and their locations that could possibly be reused +// CandidateLocations2 returns a prioritized, limited, number of blobs and their locations (if known) that could possibly be reused // within the specified (transport scope) (if they still exist, which is not guaranteed). // // If !canSubstitute, the returned cadidates will match the submitted digest exactly; if canSubstitute, @@ -164,23 +191,24 @@ func (mem *cache) CandidateLocations2(transport types.ImageTransport, scope type return mem.candidateLocations(transport, scope, primaryDigest, canSubstitute, true) } -func (mem *cache) candidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute, requireCompressionInfo bool) []blobinfocache.BICReplacementCandidate2 { +func (mem *cache) candidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute, v2Output bool) []blobinfocache.BICReplacementCandidate2 { mem.mutex.Lock() defer mem.mutex.Unlock() res := []prioritize.CandidateWithTime{} - res = mem.appendReplacementCandidates(res, transport, scope, primaryDigest, requireCompressionInfo) + res = mem.appendReplacementCandidates(res, transport, scope, primaryDigest, v2Output) var uncompressedDigest digest.Digest // = "" if canSubstitute { if uncompressedDigest = mem.uncompressedDigestLocked(primaryDigest); uncompressedDigest != "" { - if otherDigests, ok := mem.digestsByUncompressed[uncompressedDigest]; ok { + otherDigests := mem.digestsByUncompressed[uncompressedDigest] // nil if not present in the map + if otherDigests != nil { for _, d := range otherDigests.Values() { if d != primaryDigest && d != uncompressedDigest { - res = mem.appendReplacementCandidates(res, transport, scope, d, requireCompressionInfo) + res = mem.appendReplacementCandidates(res, transport, scope, d, v2Output) } } } if uncompressedDigest != primaryDigest { - res = mem.appendReplacementCandidates(res, transport, scope, uncompressedDigest, requireCompressionInfo) + res = mem.appendReplacementCandidates(res, transport, scope, uncompressedDigest, v2Output) } } } diff --git a/vendor/github.com/containers/image/v5/pkg/blobinfocache/sqlite/sqlite.go b/vendor/github.com/containers/image/v5/pkg/blobinfocache/sqlite/sqlite.go new file mode 100644 index 00000000000..2b446a61c48 --- /dev/null +++ b/vendor/github.com/containers/image/v5/pkg/blobinfocache/sqlite/sqlite.go @@ -0,0 +1,575 @@ +// Package boltdb implements a BlobInfoCache backed by SQLite. +package sqlite + +import ( + "database/sql" + "errors" + "fmt" + "sync" + "time" + + "github.com/containers/image/v5/internal/blobinfocache" + "github.com/containers/image/v5/pkg/blobinfocache/internal/prioritize" + "github.com/containers/image/v5/types" + _ "github.com/mattn/go-sqlite3" // Registers the "sqlite3" backend backend for database/sql + "github.com/opencontainers/go-digest" + "github.com/sirupsen/logrus" +) + +const ( + // NOTE: There is no versioning data inside the file; this is a “cache”, so on an incompatible format upgrade + // we can simply start over with a different filename; update blobInfoCacheFilename. + // That also means we don’t have to worry about co-existing readers/writers which know different versions of the schema + // (which would require compatibility in both directions). + + // Assembled sqlite options used when opening the database. + sqliteOptions = "?" + + // Deal with timezone automatically. + // go-sqlite3 always _records_ timestamps as a text: time in local time + a time zone offset. + // _loc affects how the values are _parsed_: (which timezone is assumed for numeric timestamps or for text which does not specify an offset, or) + // if the time zone offset matches the specified time zone, the timestamp is assumed to be in that time zone / location; + // (otherwise an unnamed time zone carrying just a hard-coded offset, but no location / DST rules is used). + "_loc=auto" + + // Force an fsync after each transaction (https://www.sqlite.org/pragma.html#pragma_synchronous). + "&_sync=FULL" + + // Allow foreign keys (https://www.sqlite.org/pragma.html#pragma_foreign_keys). + // We don’t currently use any foreign keys, but this is a good choice long-term (not default in SQLite only for historical reasons). + "&_foreign_keys=1" + + // Use BEGIN EXCLUSIVE (https://www.sqlite.org/lang_transaction.html); + // i.e. obtain a write lock for _all_ transactions at the transaction start (never use a read lock, + // never upgrade from a read to a write lock - that can fail if multiple read lock owners try to do that simultaneously). + // + // This, together with go-sqlite3’s default for _busy_timeout=5000, means that we should never see a “database is locked” error, + // the database should block on the exclusive lock when starting a transaction, and the problematic case of two simultaneous + // holders of a read lock trying to upgrade to a write lock (and one necessarily failing) is prevented. + // Compare https://github.com/mattn/go-sqlite3/issues/274 . + // + // Ideally the BEGIN / BEGIN EXCLUSIVE decision could be made per-transaction, compare https://github.com/mattn/go-sqlite3/pull/1167 + // or https://github.com/mattn/go-sqlite3/issues/400 . + // The currently-proposed workaround is to create two different SQL “databases” (= connection pools) with different _txlock settings, + // which seems rather wasteful. + "&_txlock=exclusive" +) + +// cache is a BlobInfoCache implementation which uses a SQLite file at the specified path. +type cache struct { + path string + + // The database/sql package says “It is rarely necessary to close a DB.”, and steers towards a long-term *sql.DB connection pool. + // That’s probably very applicable for database-backed services, where the database is the primary data store. That’s not necessarily + // the case for callers of c/image, where image operations might be a small proportion of the total runtime, and the cache is fairly + // incidental even to the image operations. It’s also hard for us to use that model, because the public BlobInfoCache object doesn’t have + // a Close method, so creating a lot of single-use caches could leak data. + // + // Instead, the private BlobInfoCache2 interface provides Open/Close methods, and they are called by c/image/copy.Image. + // This amortizes the cost of opening/closing the SQLite state over a single image copy, while keeping no long-term resources open. + // Some rough benchmarks in https://github.com/containers/image/pull/2092 suggest relative costs on the order of "25" for a single + // *sql.DB left open long-term, "27" for a *sql.DB open for a single image copy, and "40" for opening/closing a *sql.DB for every + // single transaction; so the Open/Close per image copy seems a reasonable compromise (especially compared to the previous implementation, + // somewhere around "700"). + + lock sync.Mutex + // The following fields can only be accessed with lock held. + refCount int // number of outstanding Open() calls + db *sql.DB // nil if not set (may happen even if refCount > 0 on errors) +} + +// New returns BlobInfoCache implementation which uses a SQLite file at path. +// +// Most users should call blobinfocache.DefaultCache instead. +func New(path string) (types.BlobInfoCache, error) { + return new2(path) +} + +func new2(path string) (*cache, error) { + db, err := rawOpen(path) + if err != nil { + return nil, fmt.Errorf("initializing blob info cache at %q: %w", path, err) + } + defer db.Close() + + // We don’t check the schema before every operation, because that would be costly + // and because we assume schema changes will be handled by using a different path. + if err := ensureDBHasCurrentSchema(db); err != nil { + return nil, err + } + + return &cache{ + path: path, + refCount: 0, + db: nil, + }, nil +} + +// rawOpen returns a new *sql.DB for path. +// The caller should arrange for it to be .Close()d. +func rawOpen(path string) (*sql.DB, error) { + // This exists to centralize the use of sqliteOptions. + return sql.Open("sqlite3", path+sqliteOptions) +} + +// Open() sets up the cache for future accesses, potentially acquiring costly state. Each Open() must be paired with a Close(). +// Note that public callers may call the types.BlobInfoCache operations without Open()/Close(). +func (sqc *cache) Open() { + sqc.lock.Lock() + defer sqc.lock.Unlock() + + if sqc.refCount == 0 { + db, err := rawOpen(sqc.path) + if err != nil { + logrus.Warnf("Error opening (previously-successfully-opened) blob info cache at %q: %v", sqc.path, err) + db = nil // But still increase sqc.refCount, because a .Close() will happen + } + sqc.db = db + } + sqc.refCount++ +} + +// Close destroys state created by Open(). +func (sqc *cache) Close() { + sqc.lock.Lock() + defer sqc.lock.Unlock() + + switch sqc.refCount { + case 0: + logrus.Errorf("internal error using pkg/blobinfocache/sqlite.cache: Close() without a matching Open()") + return + case 1: + if sqc.db != nil { + sqc.db.Close() + sqc.db = nil + } + } + sqc.refCount-- +} + +type void struct{} // So that we don’t have to write struct{}{} all over the place + +// transaction calls fn within a read-write transaction in sqc. +func transaction[T any](sqc *cache, fn func(tx *sql.Tx) (T, error)) (T, error) { + db, closeDB, err := func() (*sql.DB, func(), error) { // A scope for defer + sqc.lock.Lock() + defer sqc.lock.Unlock() + + if sqc.db != nil { + return sqc.db, func() {}, nil + } + db, err := rawOpen(sqc.path) + if err != nil { + return nil, nil, fmt.Errorf("opening blob info cache at %q: %w", sqc.path, err) + } + return db, func() { db.Close() }, nil + }() + if err != nil { + var zeroRes T // A zero value of T + return zeroRes, err + } + defer closeDB() + + return dbTransaction(db, fn) +} + +// dbTransaction calls fn within a read-write transaction in db. +func dbTransaction[T any](db *sql.DB, fn func(tx *sql.Tx) (T, error)) (T, error) { + // Ideally we should be able to distinguish between read-only and read-write transactions, see the _txlock=exclusive dicussion. + + var zeroRes T // A zero value of T + + tx, err := db.Begin() + if err != nil { + return zeroRes, fmt.Errorf("beginning transaction: %w", err) + } + succeeded := false + defer func() { + if !succeeded { + if err := tx.Rollback(); err != nil { + logrus.Errorf("Rolling back transaction: %v", err) + } + } + }() + + res, err := fn(tx) + if err != nil { + return zeroRes, err + } + if err := tx.Commit(); err != nil { + return zeroRes, fmt.Errorf("committing transaction: %w", err) + } + + succeeded = true + return res, nil +} + +// querySingleValue executes a SELECT which is expected to return at most one row with a single column. +// It returns (value, true, nil) on success, or (value, false, nil) if no row was returned. +func querySingleValue[T any](tx *sql.Tx, query string, params ...any) (T, bool, error) { + var value T + if err := tx.QueryRow(query, params...).Scan(&value); err != nil { + var zeroValue T // A zero value of T + if errors.Is(err, sql.ErrNoRows) { + return zeroValue, false, nil + } + return zeroValue, false, err + } + return value, true, nil +} + +// ensureDBHasCurrentSchema adds the necessary tables and indices to a database. +// This is typically used when creating a previously-nonexistent database. +// We don’t really anticipate schema migrations; with c/image usually vendored, not using +// shared libraries, migrating a schema on an existing database would affect old-version users. +// Instead, schema changes are likely to be implemented by using a different cache file name, +// and leaving existing caches around for old users. +func ensureDBHasCurrentSchema(db *sql.DB) error { + // Considered schema design alternatives: + // + // (Overall, considering the overall network latency and disk I/O costs of many-megabyte layer pulls which are happening while referring + // to the blob info cache, it seems reasonable to prioritize readability over microoptimization of this database.) + // + // * This schema uses the text representation of digests. + // + // We use the fairly wasteful text with hexadecimal digits because digest.Digest does not define a binary representation; + // and the way digest.Digest.Hex() is deprecated in favor of digest.Digest.Encoded(), and the way digest.Algorithm + // is documented to “define the string encoding” suggests that assuming a hexadecimal representation and turning that + // into binary ourselves is not a good idea in general; we would have to special-case the currently-known algorithm + // — and that would require us to implement two code paths, one of them basically never exercised / never tested. + // + // * There are two separate items for recording the uncompressed digest and digest compressors. + // Alternatively, we could have a single "digest facts" table with NULLable columns. + // + // The way the BlobInfoCache API works, we are only going to write one value at a time, so + // sharing a table would not be any more efficient for writes (same number of lookups, larger row tuples). + // Reads in candidateLocations would not be more efficient either, the searches in DigestCompressors and DigestUncompressedPairs + // do not coincide (we want a compressor for every candidate, but the uncompressed digest only for the primary digest; and then + // we search in DigestUncompressedPairs by uncompressed digest, not by the primary key). + // + // Also, using separate items allows the single-item writes to be done using a simple INSERT OR REPLACE, instead of having to + // do a more verbose ON CONFLICT(…) DO UPDATE SET … = …. + // + // * Joins (the two that exist in appendReplacementCandidates) are based on the text representation of digests. + // + // Using integer primary keys might make the joins themselves a bit more efficient, but then we would need to involve an extra + // join to translate from/to the user-provided digests anyway. If anything, that extra join (potentially more btree lookups) + // is probably costlier than comparing a few more bytes of data. + // + // Perhaps more importantly, storing digest texts directly makes the database dumps much easier to read for humans without + // having to do extra steps to decode the integers into digest values (either by running sqlite commands with joins, or mentally). + // + items := []struct{ itemName, command string }{ + { + "DigestUncompressedPairs", + `CREATE TABLE IF NOT EXISTS DigestUncompressedPairs(` + + // index implied by PRIMARY KEY + `anyDigest TEXT PRIMARY KEY NOT NULL,` + + // DigestUncompressedPairs_index_uncompressedDigest + `uncompressedDigest TEXT NOT NULL + )`, + }, + { + "DigestUncompressedPairs_index_uncompressedDigest", + `CREATE INDEX IF NOT EXISTS DigestUncompressedPairs_index_uncompressedDigest ON DigestUncompressedPairs(uncompressedDigest)`, + }, + { + "DigestCompressors", + `CREATE TABLE IF NOT EXISTS DigestCompressors(` + + // index implied by PRIMARY KEY + `digest TEXT PRIMARY KEY NOT NULL,` + + // May include blobinfocache.Uncompressed (not blobinfocache.UnknownCompression). + `compressor TEXT NOT NULL + )`, + }, + { + "KnownLocations", + `CREATE TABLE IF NOT EXISTS KnownLocations( + transport TEXT NOT NULL, + scope TEXT NOT NULL, + digest TEXT NOT NULL, + location TEXT NOT NULL,` + + // TIMESTAMP is parsed by SQLITE as a NUMERIC affinity, but go-sqlite3 stores text in the (Go formatting semantics) + // format "2006-01-02 15:04:05.999999999-07:00". + // See also the _loc option in the sql.Open data source name. + `time TIMESTAMP NOT NULL,` + + // Implies an index. + // We also search by (transport, scope, digest), that doesn’t need an extra index + // because it is a prefix of the implied primary-key index. + `PRIMARY KEY (transport, scope, digest, location) + )`, + }, + } + + _, err := dbTransaction(db, func(tx *sql.Tx) (void, error) { + // If the the last-created item exists, assume nothing needs to be done. + lastItemName := items[len(items)-1].itemName + _, found, err := querySingleValue[int](tx, "SELECT 1 FROM sqlite_schema WHERE name=?", lastItemName) + if err != nil { + return void{}, fmt.Errorf("checking if SQLite schema item %q exists: %w", lastItemName, err) + } + if !found { + // Item does not exist, assuming a fresh database. + for _, i := range items { + if _, err := tx.Exec(i.command); err != nil { + return void{}, fmt.Errorf("creating item %s: %w", i.itemName, err) + } + } + } + return void{}, nil + }) + return err +} + +// uncompressedDigest implements types.BlobInfoCache.UncompressedDigest within a transaction. +func (sqc *cache) uncompressedDigest(tx *sql.Tx, anyDigest digest.Digest) (digest.Digest, error) { + uncompressedString, found, err := querySingleValue[string](tx, "SELECT uncompressedDigest FROM DigestUncompressedPairs WHERE anyDigest = ?", anyDigest.String()) + if err != nil { + return "", err + } + if found { + d, err := digest.Parse(uncompressedString) + if err != nil { + return "", err + } + return d, nil + + } + // A record as uncompressedDigest implies that anyDigest must already refer to an uncompressed digest. + // This way we don't have to waste storage space with trivial (uncompressed, uncompressed) mappings + // when we already record a (compressed, uncompressed) pair. + _, found, err = querySingleValue[int](tx, "SELECT 1 FROM DigestUncompressedPairs WHERE uncompressedDigest = ?", anyDigest.String()) + if err != nil { + return "", err + } + if found { + return anyDigest, nil + } + return "", nil +} + +// UncompressedDigest returns an uncompressed digest corresponding to anyDigest. +// May return anyDigest if it is known to be uncompressed. +// Returns "" if nothing is known about the digest (it may be compressed or uncompressed). +func (sqc *cache) UncompressedDigest(anyDigest digest.Digest) digest.Digest { + res, err := transaction(sqc, func(tx *sql.Tx) (digest.Digest, error) { + return sqc.uncompressedDigest(tx, anyDigest) + }) + if err != nil { + return "" // FIXME? Log err (but throttle the log volume on repeated accesses)? + } + return res +} + +// RecordDigestUncompressedPair records that the uncompressed version of anyDigest is uncompressed. +// It’s allowed for anyDigest == uncompressed. +// WARNING: Only call this for LOCALLY VERIFIED data; don’t record a digest pair just because some remote author claims so (e.g. +// because a manifest/config pair exists); otherwise the cache could be poisoned and allow substituting unexpected blobs. +// (Eventually, the DiffIDs in image config could detect the substitution, but that may be too late, and not all image formats contain that data.) +func (sqc *cache) RecordDigestUncompressedPair(anyDigest digest.Digest, uncompressed digest.Digest) { + _, _ = transaction(sqc, func(tx *sql.Tx) (void, error) { + previousString, gotPrevious, err := querySingleValue[string](tx, "SELECT uncompressedDigest FROM DigestUncompressedPairs WHERE anyDigest = ?", anyDigest.String()) + if err != nil { + return void{}, fmt.Errorf("looking for uncompressed digest for %q", anyDigest) + } + if gotPrevious { + previous, err := digest.Parse(previousString) + if err != nil { + return void{}, err + } + if previous != uncompressed { + logrus.Warnf("Uncompressed digest for blob %s previously recorded as %s, now %s", anyDigest, previous, uncompressed) + } + } + if _, err := tx.Exec("INSERT OR REPLACE INTO DigestUncompressedPairs(anyDigest, uncompressedDigest) VALUES (?, ?)", + anyDigest.String(), uncompressed.String()); err != nil { + return void{}, fmt.Errorf("recording uncompressed digest %q for %q: %w", uncompressed, anyDigest, err) + } + return void{}, nil + }) // FIXME? Log error (but throttle the log volume on repeated accesses)? +} + +// RecordKnownLocation records that a blob with the specified digest exists within the specified (transport, scope) scope, +// and can be reused given the opaque location data. +func (sqc *cache) RecordKnownLocation(transport types.ImageTransport, scope types.BICTransportScope, digest digest.Digest, location types.BICLocationReference) { + _, _ = transaction(sqc, func(tx *sql.Tx) (void, error) { + if _, err := tx.Exec("INSERT OR REPLACE INTO KnownLocations(transport, scope, digest, location, time) VALUES (?, ?, ?, ?, ?)", + transport.Name(), scope.Opaque, digest.String(), location.Opaque, time.Now()); err != nil { // Possibly overwriting an older entry. + return void{}, fmt.Errorf("recording known location %q for (%q, %q, %q): %w", + location.Opaque, transport.Name(), scope.Opaque, digest.String(), err) + } + return void{}, nil + }) // FIXME? Log error (but throttle the log volume on repeated accesses)? +} + +// RecordDigestCompressorName records a compressor for the blob with the specified digest, +// or Uncompressed or UnknownCompression. +// WARNING: Only call this with LOCALLY VERIFIED data; don’t record a compressor for a +// digest just because some remote author claims so (e.g. because a manifest says so); +// otherwise the cache could be poisoned and cause us to make incorrect edits to type +// information in a manifest. +func (sqc *cache) RecordDigestCompressorName(anyDigest digest.Digest, compressorName string) { + _, _ = transaction(sqc, func(tx *sql.Tx) (void, error) { + previous, gotPrevious, err := querySingleValue[string](tx, "SELECT compressor FROM DigestCompressors WHERE digest = ?", anyDigest.String()) + if err != nil { + return void{}, fmt.Errorf("looking for compressor of for %q", anyDigest) + } + if gotPrevious && previous != compressorName { + logrus.Warnf("Compressor for blob with digest %s previously recorded as %s, now %s", anyDigest, previous, compressorName) + } + if compressorName == blobinfocache.UnknownCompression { + if _, err := tx.Exec("DELETE FROM DigestCompressors WHERE digest = ?", anyDigest.String()); err != nil { + return void{}, fmt.Errorf("deleting compressor for digest %q: %w", anyDigest, err) + } + } else { + if _, err := tx.Exec("INSERT OR REPLACE INTO DigestCompressors(digest, compressor) VALUES (?, ?)", + anyDigest.String(), compressorName); err != nil { + return void{}, fmt.Errorf("recording compressor %q for %q: %w", compressorName, anyDigest, err) + } + } + return void{}, nil + }) // FIXME? Log error (but throttle the log volume on repeated accesses)? +} + +// appendReplacementCandidates creates prioritize.CandidateWithTime values for (transport, scope, digest), +// and returns the result of appending them to candidates. v2Output allows including candidates with unknown +// location, and filters out candidates with unknown compression. +func (sqc *cache) appendReplacementCandidates(candidates []prioritize.CandidateWithTime, tx *sql.Tx, transport types.ImageTransport, scope types.BICTransportScope, digest digest.Digest, v2Output bool) ([]prioritize.CandidateWithTime, error) { + var rows *sql.Rows + var err error + if v2Output { + rows, err = tx.Query("SELECT location, time, compressor FROM KnownLocations JOIN DigestCompressors "+ + "ON KnownLocations.digest = DigestCompressors.digest "+ + "WHERE transport = ? AND scope = ? AND KnownLocations.digest = ?", + transport.Name(), scope.Opaque, digest.String()) + } else { + rows, err = tx.Query("SELECT location, time, IFNULL(compressor, ?) FROM KnownLocations "+ + "LEFT JOIN DigestCompressors ON KnownLocations.digest = DigestCompressors.digest "+ + "WHERE transport = ? AND scope = ? AND KnownLocations.digest = ?", + blobinfocache.UnknownCompression, + transport.Name(), scope.Opaque, digest.String()) + } + if err != nil { + return nil, fmt.Errorf("looking up candidate locations: %w", err) + } + defer rows.Close() + + res := []prioritize.CandidateWithTime{} + for rows.Next() { + var location string + var time time.Time + var compressorName string + if err := rows.Scan(&location, &time, &compressorName); err != nil { + return nil, fmt.Errorf("scanning candidate: %w", err) + } + res = append(res, prioritize.CandidateWithTime{ + Candidate: blobinfocache.BICReplacementCandidate2{ + Digest: digest, + CompressorName: compressorName, + Location: types.BICLocationReference{Opaque: location}, + }, + LastSeen: time, + }) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("iterating through locations: %w", err) + } + + if len(res) == 0 && v2Output { + compressor, found, err := querySingleValue[string](tx, "SELECT compressor FROM DigestCompressors WHERE digest = ?", digest.String()) + if err != nil { + return nil, fmt.Errorf("scanning compressorName: %w", err) + } + if found { + res = append(res, prioritize.CandidateWithTime{ + Candidate: blobinfocache.BICReplacementCandidate2{ + Digest: digest, + CompressorName: compressor, + UnknownLocation: true, + Location: types.BICLocationReference{Opaque: ""}, + }, + LastSeen: time.Time{}, + }) + } + } + candidates = append(candidates, res...) + return candidates, nil +} + +// CandidateLocations2 returns a prioritized, limited, number of blobs and their locations (if known) +// that could possibly be reused within the specified (transport scope) (if they still +// exist, which is not guaranteed). +// +// If !canSubstitute, the returned cadidates will match the submitted digest exactly; if +// canSubstitute, data from previous RecordDigestUncompressedPair calls is used to also look +// up variants of the blob which have the same uncompressed digest. +// +// The CompressorName fields in returned data must never be UnknownCompression. +func (sqc *cache) CandidateLocations2(transport types.ImageTransport, scope types.BICTransportScope, digest digest.Digest, canSubstitute bool) []blobinfocache.BICReplacementCandidate2 { + return sqc.candidateLocations(transport, scope, digest, canSubstitute, true) +} + +func (sqc *cache) candidateLocations(transport types.ImageTransport, scope types.BICTransportScope, primaryDigest digest.Digest, canSubstitute, v2Output bool) []blobinfocache.BICReplacementCandidate2 { + var uncompressedDigest digest.Digest // = "" + res, err := transaction(sqc, func(tx *sql.Tx) ([]prioritize.CandidateWithTime, error) { + res := []prioritize.CandidateWithTime{} + res, err := sqc.appendReplacementCandidates(res, tx, transport, scope, primaryDigest, v2Output) + if err != nil { + return nil, err + } + if canSubstitute { + uncompressedDigest, err = sqc.uncompressedDigest(tx, primaryDigest) + if err != nil { + return nil, err + } + + // FIXME? We could integrate this with appendReplacementCandidates into a single join instead of N+1 queries. + // (In the extreme, we could turn _everything_ this function does into a single query. + // And going even further, even DestructivelyPrioritizeReplacementCandidates could be turned into SQL.) + // For now, we prioritize simplicity, and sharing both code and implementation structure with the other cache implementations. + rows, err := tx.Query("SELECT anyDigest FROM DigestUncompressedPairs WHERE uncompressedDigest = ?", uncompressedDigest.String()) + if err != nil { + return nil, fmt.Errorf("querying for other digests: %w", err) + } + defer rows.Close() + for rows.Next() { + var otherDigestString string + if err := rows.Scan(&otherDigestString); err != nil { + return nil, fmt.Errorf("scanning other digest: %w", err) + } + otherDigest, err := digest.Parse(otherDigestString) + if err != nil { + return nil, err + } + if otherDigest != primaryDigest && otherDigest != uncompressedDigest { + res, err = sqc.appendReplacementCandidates(res, tx, transport, scope, otherDigest, v2Output) + if err != nil { + return nil, err + } + } + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("iterating through other digests: %w", err) + } + + if uncompressedDigest != primaryDigest { + res, err = sqc.appendReplacementCandidates(res, tx, transport, scope, uncompressedDigest, v2Output) + if err != nil { + return nil, err + } + } + } + return res, nil + }) + if err != nil { + return []blobinfocache.BICReplacementCandidate2{} // FIXME? Log err (but throttle the log volume on repeated accesses)? + } + return prioritize.DestructivelyPrioritizeReplacementCandidates(res, primaryDigest, uncompressedDigest) + +} + +// CandidateLocations returns a prioritized, limited, number of blobs and their locations that could possibly be reused +// within the specified (transport scope) (if they still exist, which is not guaranteed). +// +// If !canSubstitute, the returned candidates will match the submitted digest exactly; if canSubstitute, +// data from previous RecordDigestUncompressedPair calls is used to also look up variants of the blob which have the same +// uncompressed digest. +func (sqc *cache) CandidateLocations(transport types.ImageTransport, scope types.BICTransportScope, digest digest.Digest, canSubstitute bool) []types.BICReplacementCandidate { + return blobinfocache.CandidateLocationsFromV2(sqc.candidateLocations(transport, scope, digest, canSubstitute, false)) +} diff --git a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go index 2e79d0ffbc3..c61065cb014 100644 --- a/vendor/github.com/containers/image/v5/pkg/docker/config/config.go +++ b/vendor/github.com/containers/image/v5/pkg/docker/config/config.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "io/fs" "os" "os/exec" "path/filepath" @@ -61,78 +62,6 @@ func newAuthPathDefault(path string) authPath { return authPath{path: path, legacyFormat: false} } -// SetCredentials stores the username and password in a location -// appropriate for sys and the users’ configuration. -// A valid key is a repository, a namespace within a registry, or a registry hostname; -// using forms other than just a registry may fail depending on configuration. -// Returns a human-readable description of the location that was updated. -// NOTE: The return value is only intended to be read by humans; its form is not an API, -// it may change (or new forms can be added) any time. -func SetCredentials(sys *types.SystemContext, key, username, password string) (string, error) { - isNamespaced, err := validateKey(key) - if err != nil { - return "", err - } - - helpers, err := sysregistriesv2.CredentialHelpers(sys) - if err != nil { - return "", err - } - - // Make sure to collect all errors. - var multiErr error - for _, helper := range helpers { - var desc string - var err error - switch helper { - // Special-case the built-in helpers for auth files. - case sysregistriesv2.AuthenticationFileHelper: - desc, err = modifyJSON(sys, func(fileContents *dockerConfigFile) (bool, string, error) { - if ch, exists := fileContents.CredHelpers[key]; exists { - if isNamespaced { - return false, "", unsupportedNamespaceErr(ch) - } - desc, err := setCredsInCredHelper(ch, key, username, password) - if err != nil { - return false, "", err - } - return false, desc, nil - } - creds := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) - newCreds := dockerAuthConfig{Auth: creds} - fileContents.AuthConfigs[key] = newCreds - return true, "", nil - }) - // External helpers. - default: - if isNamespaced { - err = unsupportedNamespaceErr(helper) - } else { - desc, err = setCredsInCredHelper(helper, key, username, password) - } - } - if err != nil { - multiErr = multierror.Append(multiErr, err) - logrus.Debugf("Error storing credentials for %s in credential helper %s: %v", key, helper, err) - continue - } - logrus.Debugf("Stored credentials for %s in credential helper %s", key, helper) - return desc, nil - } - return "", multiErr -} - -func unsupportedNamespaceErr(helper string) error { - return fmt.Errorf("namespaced key is not supported for credential helper %s", helper) -} - -// SetAuthentication stores the username and password in the credential helper or file -// See the documentation of SetCredentials for format of "key" -func SetAuthentication(sys *types.SystemContext, key, username, password string) error { - _, err := SetCredentials(sys, key, username, password) - return err -} - // GetAllCredentials returns the registry credentials for all registries stored // in any of the configured credential helpers. func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthConfig, error) { @@ -370,17 +299,79 @@ func getAuthenticationWithHomeDir(sys *types.SystemContext, key, homeDir string) return creds.Username, creds.Password, nil } -// RemoveAuthentication removes credentials for `key` from all possible -// sources such as credential helpers and auth files. +// SetCredentials stores the username and password in a location +// appropriate for sys and the users’ configuration. // A valid key is a repository, a namespace within a registry, or a registry hostname; // using forms other than just a registry may fail depending on configuration. -func RemoveAuthentication(sys *types.SystemContext, key string) error { - isNamespaced, err := validateKey(key) +// Returns a human-readable description of the location that was updated. +// NOTE: The return value is only intended to be read by humans; its form is not an API, +// it may change (or new forms can be added) any time. +func SetCredentials(sys *types.SystemContext, key, username, password string) (string, error) { + helpers, jsonEditor, key, isNamespaced, err := prepareForEdit(sys, key, true) if err != nil { - return err + return "", err } - helpers, err := sysregistriesv2.CredentialHelpers(sys) + // Make sure to collect all errors. + var multiErr error + for _, helper := range helpers { + var desc string + var err error + switch helper { + // Special-case the built-in helpers for auth files. + case sysregistriesv2.AuthenticationFileHelper: + desc, err = jsonEditor(sys, func(fileContents *dockerConfigFile) (bool, string, error) { + if ch, exists := fileContents.CredHelpers[key]; exists { + if isNamespaced { + return false, "", unsupportedNamespaceErr(ch) + } + desc, err := setCredsInCredHelper(ch, key, username, password) + if err != nil { + return false, "", err + } + return false, desc, nil + } + creds := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) + newCreds := dockerAuthConfig{Auth: creds} + fileContents.AuthConfigs[key] = newCreds + return true, "", nil + }) + // External helpers. + default: + if isNamespaced { + err = unsupportedNamespaceErr(helper) + } else { + desc, err = setCredsInCredHelper(helper, key, username, password) + } + } + if err != nil { + multiErr = multierror.Append(multiErr, err) + logrus.Debugf("Error storing credentials for %s in credential helper %s: %v", key, helper, err) + continue + } + logrus.Debugf("Stored credentials for %s in credential helper %s", key, helper) + return desc, nil + } + return "", multiErr +} + +func unsupportedNamespaceErr(helper string) error { + return fmt.Errorf("namespaced key is not supported for credential helper %s", helper) +} + +// SetAuthentication stores the username and password in the credential helper or file +// See the documentation of SetCredentials for format of "key" +func SetAuthentication(sys *types.SystemContext, key, username, password string) error { + _, err := SetCredentials(sys, key, username, password) + return err +} + +// RemoveAuthentication removes credentials for `key` from all possible +// sources such as credential helpers and auth files. +// A valid key is a repository, a namespace within a registry, or a registry hostname; +// using forms other than just a registry may fail depending on configuration. +func RemoveAuthentication(sys *types.SystemContext, key string) error { + helpers, jsonEditor, key, isNamespaced, err := prepareForEdit(sys, key, true) if err != nil { return err } @@ -411,7 +402,7 @@ func RemoveAuthentication(sys *types.SystemContext, key string) error { switch helper { // Special-case the built-in helper for auth files. case sysregistriesv2.AuthenticationFileHelper: - _, err = modifyJSON(sys, func(fileContents *dockerConfigFile) (bool, string, error) { + _, err = jsonEditor(sys, func(fileContents *dockerConfigFile) (bool, string, error) { if innerHelper, exists := fileContents.CredHelpers[key]; exists { removeFromCredHelper(innerHelper) } @@ -443,7 +434,7 @@ func RemoveAuthentication(sys *types.SystemContext, key string) error { // RemoveAllAuthentication deletes all the credentials stored in credential // helpers and auth files. func RemoveAllAuthentication(sys *types.SystemContext) error { - helpers, err := sysregistriesv2.CredentialHelpers(sys) + helpers, jsonEditor, _, _, err := prepareForEdit(sys, "", false) if err != nil { return err } @@ -454,7 +445,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error { switch helper { // Special-case the built-in helper for auth files. case sysregistriesv2.AuthenticationFileHelper: - _, err = modifyJSON(sys, func(fileContents *dockerConfigFile) (bool, string, error) { + _, err = jsonEditor(sys, func(fileContents *dockerConfigFile) (bool, string, error) { for registry, helper := range fileContents.CredHelpers { // Helpers in auth files are expected // to exist, so no special treatment @@ -497,6 +488,46 @@ func RemoveAllAuthentication(sys *types.SystemContext) error { return multiErr } +// prepareForEdit processes sys and key (if keyRelevant) to return: +// - a list of credential helpers +// - a function which can be used to edit the JSON file +// - the key value to actually use in credential helpers / JSON +// - a boolean which is true if key is namespaced (and should not be used with credential helpers). +func prepareForEdit(sys *types.SystemContext, key string, keyRelevant bool) ([]string, func(*types.SystemContext, func(*dockerConfigFile) (bool, string, error)) (string, error), string, bool, error) { + var isNamespaced bool + if keyRelevant { + ns, err := validateKey(key) + if err != nil { + return nil, nil, "", false, err + } + isNamespaced = ns + } + + if sys != nil && sys.DockerCompatAuthFilePath != "" { + if sys.AuthFilePath != "" { + return nil, nil, "", false, errors.New("AuthFilePath and DockerCompatAuthFilePath can not be set simultaneously") + } + if keyRelevant { + if isNamespaced { + return nil, nil, "", false, fmt.Errorf("Credentials cannot be recorded in Docker-compatible format with namespaced key %q", key) + } + if key == "docker.io" { + key = "https://index.docker.io/v1/" + } + } + + // Do not use helpers defined in sysregistriesv2 because Docker isn’t aware of them. + return []string{sysregistriesv2.AuthenticationFileHelper}, modifyDockerConfigJSON, key, false, nil + } + + helpers, err := sysregistriesv2.CredentialHelpers(sys) + if err != nil { + return nil, nil, "", false, err + } + + return helpers, modifyJSON, key, isNamespaced, nil +} + func listCredsInCredHelper(credHelper string) (map[string]string, error) { helperName := fmt.Sprintf("docker-credential-%s", credHelper) p := helperclient.NewShellProgramFunc(helperName) @@ -513,17 +544,26 @@ func getPathToAuth(sys *types.SystemContext) (authPath, bool, error) { // it exists only to allow testing it with an artificial runtime.GOOS. func getPathToAuthWithOS(sys *types.SystemContext, goOS string) (authPath, bool, error) { if sys != nil { + if sys.AuthFilePath != "" && sys.DockerCompatAuthFilePath != "" { + return authPath{}, false, errors.New("AuthFilePath and DockerCompatAuthFilePath can not be set simultaneously") + } if sys.AuthFilePath != "" { return newAuthPathDefault(sys.AuthFilePath), true, nil } + // When reading, we can process auth.json and Docker’s config.json with the same code. + // When writing, prepareForEdit chooses an appropriate jsonEditor implementation. + if sys.DockerCompatAuthFilePath != "" { + return newAuthPathDefault(sys.DockerCompatAuthFilePath), true, nil + } if sys.LegacyFormatAuthFilePath != "" { return authPath{path: sys.LegacyFormatAuthFilePath, legacyFormat: true}, true, nil } - if sys.RootForImplicitAbsolutePaths != "" { + // Note: RootForImplicitAbsolutePaths should not affect paths starting with $HOME + if sys.RootForImplicitAbsolutePaths != "" && goOS == "linux" { return newAuthPathDefault(filepath.Join(sys.RootForImplicitAbsolutePaths, fmt.Sprintf(defaultPerUIDPathFormat, os.Getuid()))), false, nil } } - if goOS == "windows" || goOS == "darwin" { + if goOS != "linux" { return newAuthPathDefault(filepath.Join(homedir.Get(), nonLinuxAuthFilePath)), false, nil } @@ -625,6 +665,86 @@ func modifyJSON(sys *types.SystemContext, editor func(fileContents *dockerConfig return description, nil } +// modifyDockerConfigJSON finds a docker config.json file, calls editor on the contents, and +// writes it back if editor returns true. +// Returns a human-readable description of the file, to be returned by SetCredentials. +// +// The editor may also return a human-readable description of the updated location; if it is "", +// the file itself is used. +func modifyDockerConfigJSON(sys *types.SystemContext, editor func(fileContents *dockerConfigFile) (bool, string, error)) (string, error) { + if sys == nil || sys.DockerCompatAuthFilePath == "" { + return "", errors.New("internal error: modifyDockerConfigJSON called with DockerCompatAuthFilePath not set") + } + path := sys.DockerCompatAuthFilePath + + dir := filepath.Dir(path) + if err := os.MkdirAll(dir, 0700); err != nil { + return "", err + } + + // Try hard not to clobber fields we don’t understand, even fields which may be added in future Docker versions. + var rawContents map[string]json.RawMessage + originalBytes, err := os.ReadFile(path) + switch { + case err == nil: + if err := json.Unmarshal(originalBytes, &rawContents); err != nil { + return "", fmt.Errorf("unmarshaling JSON at %q: %w", path, err) + } + case errors.Is(err, fs.ErrNotExist): + rawContents = map[string]json.RawMessage{} + default: // err != nil + return "", err + } + + syntheticContents := dockerConfigFile{ + AuthConfigs: map[string]dockerAuthConfig{}, + CredHelpers: map[string]string{}, + } + // json.Unmarshal also falls back to case-insensitive field matching; this code does not do that. Presumably + // config.json is mostly maintained by machines doing `docker login`, so the files should, hopefully, not contain field names with + // unexpected case. + if rawAuths, ok := rawContents["auths"]; ok { + // This conversion will lose fields we don’t know about; when updating an entry, we can’t tell whether an unknown field + // should be preserved or discarded (because it is made obsolete/unwanted with the new credentials). + // It might make sense to track which entries of "auths" we actually modified, and to not touch any others. + if err := json.Unmarshal(rawAuths, &syntheticContents.AuthConfigs); err != nil { + return "", fmt.Errorf(`unmarshaling "auths" in JSON at %q: %w`, path, err) + } + } + if rawCH, ok := rawContents["credHelpers"]; ok { + if err := json.Unmarshal(rawCH, &syntheticContents.CredHelpers); err != nil { + return "", fmt.Errorf(`unmarshaling "credHelpers" in JSON at %q: %w`, path, err) + + } + } + + updated, description, err := editor(&syntheticContents) + if err != nil { + return "", fmt.Errorf("updating %q: %w", path, err) + } + if updated { + rawAuths, err := json.MarshalIndent(syntheticContents.AuthConfigs, "", "\t") + if err != nil { + return "", fmt.Errorf("marshaling JSON %q: %w", path, err) + } + rawContents["auths"] = rawAuths + // We never modify syntheticContents.CredHelpers, so we don’t need to update it. + newData, err := json.MarshalIndent(rawContents, "", "\t") + if err != nil { + return "", fmt.Errorf("marshaling JSON %q: %w", path, err) + } + + if err = ioutils.AtomicWriteFile(path, newData, 0600); err != nil { + return "", fmt.Errorf("writing to file %q: %w", path, err) + } + } + + if description == "" { + description = path + } + return description, nil +} + func getCredsFromCredHelper(credHelper, registry string) (types.DockerAuthConfig, error) { helperName := fmt.Sprintf("docker-credential-%s", credHelper) p := helperclient.NewShellProgramFunc(helperName) diff --git a/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go b/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go index eeb7c1effdb..a15b2b56e19 100644 --- a/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go +++ b/vendor/github.com/containers/image/v5/pkg/shortnames/shortnames.go @@ -11,6 +11,7 @@ import ( "github.com/containers/image/v5/types" "github.com/manifoldco/promptui" "github.com/opencontainers/go-digest" + "golang.org/x/exp/slices" "golang.org/x/term" ) @@ -169,7 +170,7 @@ func (r *Resolved) Description() string { // pull errors must equal the amount of pull candidates. func (r *Resolved) FormatPullErrors(pullErrors []error) error { if len(pullErrors) > 0 && len(pullErrors) != len(r.PullCandidates) { - pullErrors = append(pullErrors, + pullErrors = append(slices.Clone(pullErrors), fmt.Errorf("internal error: expected %d instead of %d errors for %d pull candidates", len(r.PullCandidates), len(pullErrors), len(r.PullCandidates))) } diff --git a/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go b/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go index 56b0d49390a..c6ec84bd5ae 100644 --- a/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go +++ b/vendor/github.com/containers/image/v5/pkg/tlsclientconfig/tlsclientconfig.go @@ -66,7 +66,7 @@ func SetupCertificates(dir string, tlsc *tls.Config) error { if err != nil { return err } - tlsc.Certificates = append(tlsc.Certificates, cert) + tlsc.Certificates = append(slices.Clone(tlsc.Certificates), cert) } if strings.HasSuffix(f.Name(), ".key") { keyName := f.Name() diff --git a/vendor/github.com/containers/image/v5/sif/src.go b/vendor/github.com/containers/image/v5/sif/src.go index 1f6ab7f3b9d..261cfbe7718 100644 --- a/vendor/github.com/containers/image/v5/sif/src.go +++ b/vendor/github.com/containers/image/v5/sif/src.go @@ -73,7 +73,7 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref sifRefere _ = sifImg.UnloadContainer() }() - workDir, err := os.MkdirTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "sif") + workDir, err := tmpdir.MkDirBigFileTemp(sys, "sif") if err != nil { return nil, fmt.Errorf("creating temp directory: %w", err) } diff --git a/vendor/github.com/containers/image/v5/signature/sigstore/copied.go b/vendor/github.com/containers/image/v5/signature/sigstore/copied.go index f9c7f6a5ed8..2e510f60e3b 100644 --- a/vendor/github.com/containers/image/v5/signature/sigstore/copied.go +++ b/vendor/github.com/containers/image/v5/signature/sigstore/copied.go @@ -10,9 +10,9 @@ import ( "errors" "fmt" + "github.com/secure-systems-lab/go-securesystemslib/encrypted" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" - "github.com/theupdateframework/go-tuf/encrypted" ) // The following code was copied from github.com/sigstore. diff --git a/vendor/github.com/containers/image/v5/storage/storage_dest.go b/vendor/github.com/containers/image/v5/storage/storage_dest.go index 7bbbf1752cd..07e1d5e1f9e 100644 --- a/vendor/github.com/containers/image/v5/storage/storage_dest.go +++ b/vendor/github.com/containers/image/v5/storage/storage_dest.go @@ -57,7 +57,7 @@ type storageImageDestination struct { imageRef storageReference directory string // Temporary directory where we store blobs until Commit() time - nextTempFileID int32 // A counter that we use for computing filenames to assign to blobs + nextTempFileID atomic.Int32 // A counter that we use for computing filenames to assign to blobs manifest []byte // Manifest contents, temporary manifestDigest digest.Digest // Valid if len(manifest) != 0 signatures []byte // Signature contents, temporary @@ -95,7 +95,7 @@ type addedLayerInfo struct { // newImageDestination sets us up to write a new image, caching blobs in a temporary directory until // it's time to Commit() the image func newImageDestination(sys *types.SystemContext, imageRef storageReference) (*storageImageDestination, error) { - directory, err := os.MkdirTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "storage") + directory, err := tmpdir.MkDirBigFileTemp(sys, "storage") if err != nil { return nil, fmt.Errorf("creating a temporary directory: %w", err) } @@ -154,7 +154,7 @@ func (s *storageImageDestination) Close() error { } func (s *storageImageDestination) computeNextBlobCacheFile() string { - return filepath.Join(s.directory, fmt.Sprintf("%d", atomic.AddInt32(&s.nextTempFileID, 1))) + return filepath.Join(s.directory, fmt.Sprintf("%d", s.nextTempFileID.Add(1))) } // PutBlobWithOptions writes contents of stream and returns data representing the result. @@ -763,7 +763,7 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t if len(layerBlobs) > 0 { // Can happen when using caches prev := s.indexToStorageID[len(layerBlobs)-1] if prev == nil { - return fmt.Errorf("Internal error: StorageImageDestination.Commit(): previous layer %d hasn't been committed (lastLayer == nil)", len(layerBlobs)-1) + return fmt.Errorf("Internal error: storageImageDestination.Commit(): previous layer %d hasn't been committed (lastLayer == nil)", len(layerBlobs)-1) } lastLayer = *prev } @@ -775,6 +775,78 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t logrus.Debugf("setting image creation date to %s", inspect.Created) options.CreationDate = *inspect.Created } + + // Set up to save the non-layer blobs as data items. Since we only share layers, they should all be in files, so + // we just need to screen out the ones that are actually layers to get the list of non-layers. + dataBlobs := set.New[digest.Digest]() + for blob := range s.filenames { + dataBlobs.Add(blob) + } + for _, layerBlob := range layerBlobs { + dataBlobs.Delete(layerBlob.Digest) + } + for _, blob := range dataBlobs.Values() { + v, err := os.ReadFile(s.filenames[blob]) + if err != nil { + return fmt.Errorf("copying non-layer blob %q to image: %w", blob, err) + } + options.BigData = append(options.BigData, storage.ImageBigDataOption{ + Key: blob.String(), + Data: v, + Digest: digest.Canonical.FromBytes(v), + }) + } + // Set up to save the unparsedToplevel's manifest if it differs from + // the per-platform one, which is saved below. + if len(toplevelManifest) != 0 && !bytes.Equal(toplevelManifest, s.manifest) { + manifestDigest, err := manifest.Digest(toplevelManifest) + if err != nil { + return fmt.Errorf("digesting top-level manifest: %w", err) + } + options.BigData = append(options.BigData, storage.ImageBigDataOption{ + Key: manifestBigDataKey(manifestDigest), + Data: toplevelManifest, + Digest: manifestDigest, + }) + } + // Set up to save the image's manifest. Allow looking it up by digest by using the key convention defined by the Store. + // Record the manifest twice: using a digest-specific key to allow references to that specific digest instance, + // and using storage.ImageDigestBigDataKey for future users that don’t specify any digest and for compatibility with older readers. + options.BigData = append(options.BigData, storage.ImageBigDataOption{ + Key: manifestBigDataKey(s.manifestDigest), + Data: s.manifest, + Digest: s.manifestDigest, + }) + options.BigData = append(options.BigData, storage.ImageBigDataOption{ + Key: storage.ImageDigestBigDataKey, + Data: s.manifest, + Digest: s.manifestDigest, + }) + // Set up to save the signatures, if we have any. + if len(s.signatures) > 0 { + options.BigData = append(options.BigData, storage.ImageBigDataOption{ + Key: "signatures", + Data: s.signatures, + Digest: digest.Canonical.FromBytes(s.signatures), + }) + } + for instanceDigest, signatures := range s.signatureses { + options.BigData = append(options.BigData, storage.ImageBigDataOption{ + Key: signatureBigDataKey(instanceDigest), + Data: signatures, + Digest: digest.Canonical.FromBytes(signatures), + }) + } + + // Set up to save our metadata. + metadata, err := json.Marshal(s) + if err != nil { + return fmt.Errorf("encoding metadata for image: %w", err) + } + if len(metadata) != 0 { + options.Metadata = string(metadata) + } + // Create the image record, pointing to the most-recently added layer. intendedID := s.imageRef.id if intendedID == "" { @@ -797,8 +869,26 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t } logrus.Debugf("reusing image ID %q", img.ID) oldNames = append(oldNames, img.Names...) + // set the data items and metadata on the already-present image + // FIXME: this _replaces_ any "signatures" blobs and their + // sizes (tracked in the metadata) which might have already + // been present with new values, when ideally we'd find a way + // to merge them since they all apply to the same image + for _, data := range options.BigData { + if err := s.imageRef.transport.store.SetImageBigData(img.ID, data.Key, data.Data, manifest.Digest); err != nil { + logrus.Debugf("error saving big data %q for image %q: %v", data.Key, img.ID, err) + return fmt.Errorf("saving big data %q for image %q: %w", data.Key, img.ID, err) + } + } + if options.Metadata != "" { + if err := s.imageRef.transport.store.SetMetadata(img.ID, options.Metadata); err != nil { + logrus.Debugf("error saving metadata for image %q: %v", img.ID, err) + return fmt.Errorf("saving metadata for image %q: %w", img.ID, err) + } + logrus.Debugf("saved image metadata %q", options.Metadata) + } } else { - logrus.Debugf("created new image ID %q", img.ID) + logrus.Debugf("created new image ID %q with metadata %q", img.ID, options.Metadata) } // Clean up the unfinished image on any error. @@ -813,78 +903,7 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t } }() - // Add the non-layer blobs as data items. Since we only share layers, they should all be in files, so - // we just need to screen out the ones that are actually layers to get the list of non-layers. - dataBlobs := set.New[digest.Digest]() - for blob := range s.filenames { - dataBlobs.Add(blob) - } - for _, layerBlob := range layerBlobs { - dataBlobs.Delete(layerBlob.Digest) - } - for _, blob := range dataBlobs.Values() { - v, err := os.ReadFile(s.filenames[blob]) - if err != nil { - return fmt.Errorf("copying non-layer blob %q to image: %w", blob, err) - } - if err := s.imageRef.transport.store.SetImageBigData(img.ID, blob.String(), v, manifest.Digest); err != nil { - logrus.Debugf("error saving big data %q for image %q: %v", blob.String(), img.ID, err) - return fmt.Errorf("saving big data %q for image %q: %w", blob.String(), img.ID, err) - } - } - // Save the unparsedToplevel's manifest if it differs from the per-platform one, which is saved below. - if len(toplevelManifest) != 0 && !bytes.Equal(toplevelManifest, s.manifest) { - manifestDigest, err := manifest.Digest(toplevelManifest) - if err != nil { - return fmt.Errorf("digesting top-level manifest: %w", err) - } - key := manifestBigDataKey(manifestDigest) - if err := s.imageRef.transport.store.SetImageBigData(img.ID, key, toplevelManifest, manifest.Digest); err != nil { - logrus.Debugf("error saving top-level manifest for image %q: %v", img.ID, err) - return fmt.Errorf("saving top-level manifest for image %q: %w", img.ID, err) - } - } - // Save the image's manifest. Allow looking it up by digest by using the key convention defined by the Store. - // Record the manifest twice: using a digest-specific key to allow references to that specific digest instance, - // and using storage.ImageDigestBigDataKey for future users that don’t specify any digest and for compatibility with older readers. - key := manifestBigDataKey(s.manifestDigest) - if err := s.imageRef.transport.store.SetImageBigData(img.ID, key, s.manifest, manifest.Digest); err != nil { - logrus.Debugf("error saving manifest for image %q: %v", img.ID, err) - return fmt.Errorf("saving manifest for image %q: %w", img.ID, err) - } - key = storage.ImageDigestBigDataKey - if err := s.imageRef.transport.store.SetImageBigData(img.ID, key, s.manifest, manifest.Digest); err != nil { - logrus.Debugf("error saving manifest for image %q: %v", img.ID, err) - return fmt.Errorf("saving manifest for image %q: %w", img.ID, err) - } - // Save the signatures, if we have any. - if len(s.signatures) > 0 { - if err := s.imageRef.transport.store.SetImageBigData(img.ID, "signatures", s.signatures, manifest.Digest); err != nil { - logrus.Debugf("error saving signatures for image %q: %v", img.ID, err) - return fmt.Errorf("saving signatures for image %q: %w", img.ID, err) - } - } - for instanceDigest, signatures := range s.signatureses { - key := signatureBigDataKey(instanceDigest) - if err := s.imageRef.transport.store.SetImageBigData(img.ID, key, signatures, manifest.Digest); err != nil { - logrus.Debugf("error saving signatures for image %q: %v", img.ID, err) - return fmt.Errorf("saving signatures for image %q: %w", img.ID, err) - } - } - // Save our metadata. - metadata, err := json.Marshal(s) - if err != nil { - logrus.Debugf("error encoding metadata for image %q: %v", img.ID, err) - return fmt.Errorf("encoding metadata for image %q: %w", img.ID, err) - } - if len(metadata) != 0 { - if err = s.imageRef.transport.store.SetMetadata(img.ID, string(metadata)); err != nil { - logrus.Debugf("error saving metadata for image %q: %v", img.ID, err) - return fmt.Errorf("saving metadata for image %q: %w", img.ID, err) - } - logrus.Debugf("saved image metadata %q", string(metadata)) - } - // Adds the reference's name on the image. We don't need to worry about avoiding duplicate + // Add the reference's name on the image. We don't need to worry about avoiding duplicate // values because AddNames() will deduplicate the list that we pass to it. if name := s.imageRef.DockerReference(); name != nil { if err := s.imageRef.transport.store.AddNames(img.ID, []string{name.String()}); err != nil { @@ -921,10 +940,7 @@ func (s *storageImageDestination) PutSignaturesWithFormat(ctx context.Context, s return err } sizes = append(sizes, len(sig)) - newblob := make([]byte, len(sigblob)+len(sig)) - copy(newblob, sigblob) - copy(newblob[len(sigblob):], sig) - sigblob = newblob + sigblob = append(sigblob, sig...) } if instanceDigest == nil { s.signatures = sigblob diff --git a/vendor/github.com/containers/image/v5/storage/storage_reference.go b/vendor/github.com/containers/image/v5/storage/storage_reference.go index 49f7d03c851..a55e34054ab 100644 --- a/vendor/github.com/containers/image/v5/storage/storage_reference.go +++ b/vendor/github.com/containers/image/v5/storage/storage_reference.go @@ -10,6 +10,7 @@ import ( "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/transports" "github.com/containers/image/v5/types" "github.com/containers/storage" digest "github.com/opencontainers/go-digest" @@ -101,6 +102,8 @@ func multiArchImageMatchesSystemContext(store storage.Store, img *storage.Image, // Resolve the reference's name to an image ID in the store, if there's already // one present with the same name or ID, and return the image. +// +// Returns an error matching ErrNoSuchImage if an image matching ref was not found. func (s *storageReference) resolveImage(sys *types.SystemContext) (*storage.Image, error) { var loadedImage *storage.Image if s.id == "" && s.named != nil { @@ -283,3 +286,31 @@ func (s storageReference) NewImageSource(ctx context.Context, sys *types.SystemC func (s storageReference) NewImageDestination(ctx context.Context, sys *types.SystemContext) (types.ImageDestination, error) { return newImageDestination(sys, s) } + +// ResolveReference finds the underlying storage image for a storage.Transport reference. +// It returns that image, and an updated reference which can be used to refer back to the _same_ +// image again. +// +// This matters if the input reference contains a tagged name; the destination of the tag can +// move in local storage. The updated reference returned by this function contains the resolved +// image ID, so later uses of that updated reference will either continue to refer to the same +// image, or fail. +// +// Note that it _is_ possible for the later uses to fail, either because the image was removed +// completely, or because the name used in the reference was untaged (even if the underlying image +// ID still exists in local storage). +// +// Returns an error matching ErrNoSuchImage if an image matching ref was not found. +func ResolveReference(ref types.ImageReference) (types.ImageReference, *storage.Image, error) { + sref, ok := ref.(*storageReference) + if !ok { + return nil, nil, fmt.Errorf("trying to resolve a non-%s: reference %q", Transport.Name(), + transports.ImageName(ref)) + } + clone := *sref // A shallow copy we can update + img, err := clone.resolveImage(nil) + if err != nil { + return nil, nil, err + } + return clone, img, nil +} diff --git a/vendor/github.com/containers/image/v5/storage/storage_src.go b/vendor/github.com/containers/image/v5/storage/storage_src.go index 03c2fa28c6c..f1ce0861e0c 100644 --- a/vendor/github.com/containers/image/v5/storage/storage_src.go +++ b/vendor/github.com/containers/image/v5/storage/storage_src.go @@ -23,6 +23,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/storage" "github.com/containers/storage/pkg/archive" + "github.com/containers/storage/pkg/ioutils" digest "github.com/opencontainers/go-digest" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" @@ -124,20 +125,25 @@ func (s *storageImageSource) GetBlob(ctx context.Context, info types.BlobInfo, c } defer rc.Close() - tmpFile, err := os.CreateTemp(tmpdir.TemporaryDirectoryForBigFiles(s.systemContext), "") + tmpFile, err := tmpdir.CreateBigFileTemp(s.systemContext, "") if err != nil { return nil, 0, err } success := false + tmpFileRemovePending := true defer func() { if !success { tmpFile.Close() + if tmpFileRemovePending { + os.Remove(tmpFile.Name()) + } } }() // On Unix and modern Windows (2022 at least) we can eagerly unlink the file to ensure it's automatically // cleaned up on process termination (or if the caller forgets to invoke Close()) + // On older versions of Windows we will have to fallback to relying on the caller to invoke Close() if err := os.Remove(tmpFile.Name()); err != nil { - return nil, 0, err + tmpFileRemovePending = false } if _, err := io.Copy(tmpFile, rc); err != nil { @@ -148,6 +154,14 @@ func (s *storageImageSource) GetBlob(ctx context.Context, info types.BlobInfo, c } success = true + + if tmpFileRemovePending { + return ioutils.NewReadCloserWrapper(tmpFile, func() error { + tmpFile.Close() + return os.Remove(tmpFile.Name()) + }), n, nil + } + return tmpFile, n, nil } diff --git a/vendor/github.com/containers/image/v5/storage/storage_transport.go b/vendor/github.com/containers/image/v5/storage/storage_transport.go index 58ba3ee651e..deb500b4d27 100644 --- a/vendor/github.com/containers/image/v5/storage/storage_transport.go +++ b/vendor/github.com/containers/image/v5/storage/storage_transport.go @@ -48,9 +48,26 @@ type StoreTransport interface { GetStoreIfSet() storage.Store // GetImage retrieves the image from the transport's store that's named // by the reference. + // Deprecated: Surprisingly, with a StoreTransport reference which contains an ID, + // this ignores that ID; and repeated calls of GetStoreImage with the same named reference + // can return different images, with no way for the caller to "freeze" the storage.Image identity + // without discarding the name entirely. + // + // Use storage.ResolveReference instead; note that if the image is not found, ResolveReference returns + // c/image/v5/storage.ErrNoSuchImage, not c/storage.ErrImageUnknown. GetImage(types.ImageReference) (*storage.Image, error) // GetStoreImage retrieves the image from a specified store that's named // by the reference. + // + // Deprecated: Surprisingly, with a StoreTransport reference which contains an ID, + // this ignores that ID; and repeated calls of GetStoreImage with the same named reference + // can return different images, with no way for the caller to "freeze" the storage.Image identity + // without discarding the name entirely. + // + // Also, a StoreTransport reference already contains a store, so providing another one is redundant. + // + // Use storage.ResolveReference instead; note that if the image is not found, ResolveReference returns + // c/image/v5/storage.ErrNoSuchImage, not c/storage.ErrImageUnknown. GetStoreImage(storage.Store, types.ImageReference) (*storage.Image, error) // ParseStoreReference parses a reference, overriding any store // specification that it may contain. @@ -290,6 +307,15 @@ func (s *storageTransport) ParseReference(reference string) (types.ImageReferenc return s.ParseStoreReference(store, reference) } +// Deprecated: Surprisingly, with a StoreTransport reference which contains an ID, +// this ignores that ID; and repeated calls of GetStoreImage with the same named reference +// can return different images, with no way for the caller to "freeze" the storage.Image identity +// without discarding the name entirely. +// +// Also, a StoreTransport reference already contains a store, so providing another one is redundant. +// +// Use storage.ResolveReference instead; note that if the image is not found, ResolveReference returns +// c/image/v5/storage.ErrNoSuchImage, not c/storage.ErrImageUnknown. func (s storageTransport) GetStoreImage(store storage.Store, ref types.ImageReference) (*storage.Image, error) { dref := ref.DockerReference() if dref != nil { @@ -306,6 +332,13 @@ func (s storageTransport) GetStoreImage(store storage.Store, ref types.ImageRefe return nil, storage.ErrImageUnknown } +// Deprecated: Surprisingly, with a StoreTransport reference which contains an ID, +// this ignores that ID; and repeated calls of GetStoreImage with the same named reference +// can return different images, with no way for the caller to "freeze" the storage.Image identity +// without discarding the name entirely. +// +// Use storage.ResolveReference instead; note that if the image is not found, ResolveReference returns +// c/image/v5/storage.ErrNoSuchImage, not c/storage.ErrImageUnknown. func (s *storageTransport) GetImage(ref types.ImageReference) (*storage.Image, error) { store, err := s.GetStore() if err != nil { diff --git a/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go b/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go index 1d9c2dc35d0..a8f1c13adc6 100644 --- a/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go +++ b/vendor/github.com/containers/image/v5/transports/alltransports/alltransports.go @@ -4,8 +4,11 @@ import ( "fmt" "strings" - // register all known transports - // NOTE: Make sure docs/containers-policy.json.5.md is updated when adding or updating + "github.com/containers/image/v5/transports" + "github.com/containers/image/v5/types" + + // Register all known transports. + // NOTE: Make sure docs/containers-transports.5.md and docs/containers-policy.json.5.md are updated when adding or updating // a transport. _ "github.com/containers/image/v5/directory" _ "github.com/containers/image/v5/docker" @@ -15,11 +18,9 @@ import ( _ "github.com/containers/image/v5/openshift" _ "github.com/containers/image/v5/sif" _ "github.com/containers/image/v5/tarball" - + // The docker-daemon transport is registeredy by docker_daemon*.go // The ostree transport is registered by ostree*.go // The storage transport is registered by storage*.go - "github.com/containers/image/v5/transports" - "github.com/containers/image/v5/types" ) // ParseImageName converts a URL-like image name to a types.ImageReference. diff --git a/vendor/github.com/containers/image/v5/types/types.go b/vendor/github.com/containers/image/v5/types/types.go index 33adb5f1dfa..180a98c5ba4 100644 --- a/vendor/github.com/containers/image/v5/types/types.go +++ b/vendor/github.com/containers/image/v5/types/types.go @@ -445,7 +445,7 @@ type ImageCloser interface { Close() error } -// ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest +// ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedImage type ManifestUpdateOptions struct { LayerInfos []BlobInfo // Complete BlobInfos (size+digest+urls+annotations) which should replace the originals, in order (the root layer first, and then successive layered layers). BlobInfos' MediaType fields are ignored. EmbeddedDockerReference reference.Named @@ -457,7 +457,7 @@ type ManifestUpdateOptions struct { // ManifestUpdateInformation is a component of ManifestUpdateOptions, named here // only to make writing struct literals possible. type ManifestUpdateInformation struct { - Destination ImageDestination // and yes, UpdatedManifest may write to Destination (see the schema2 → schema1 conversion logic in image/docker_schema2.go) + Destination ImageDestination // and yes, UpdatedImage may write to Destination (see the schema2 → schema1 conversion logic in image/docker_schema2.go) LayerInfos []BlobInfo // Complete BlobInfos (size+digest) which have been uploaded, in order (the root layer first, and then successive layered layers) LayerDiffIDs []digest.Digest // Digest values for the _uncompressed_ contents of the blobs which have been uploaded, in the same order. } @@ -594,6 +594,10 @@ type SystemContext struct { // this field is ignored if `AuthFilePath` is set (we favor the newer format); // only reading of this data is supported; LegacyFormatAuthFilePath string + // If set, a path to a Docker-compatible "config.json" file containing credentials; and no other files are processed. + // This must not be set if AuthFilePath is set. + // Only credentials and credential helpers in this file apre processed, not any other configuration in this file. + DockerCompatAuthFilePath string // If not "", overrides the use of platform.GOARCH when choosing an image or verifying architecture match. ArchitectureChoice string // If not "", overrides the use of platform.GOOS when choosing an image or verifying OS match. diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go index 584764c9a4e..b24ee881a43 100644 --- a/vendor/github.com/containers/image/v5/version/version.go +++ b/vendor/github.com/containers/image/v5/version/version.go @@ -6,9 +6,9 @@ const ( // VersionMajor is for an API incompatible changes VersionMajor = 5 // VersionMinor is for functionality in a backwards-compatible manner - VersionMinor = 27 + VersionMinor = 29 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 2 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/containers/ocicrypt/Makefile b/vendor/github.com/containers/ocicrypt/Makefile index dc9d9853754..97ddeefbb9b 100644 --- a/vendor/github.com/containers/ocicrypt/Makefile +++ b/vendor/github.com/containers/ocicrypt/Makefile @@ -28,6 +28,7 @@ vendor: go mod tidy test: + go clean -testcache go test ./... -test.v generate-protobuf: diff --git a/vendor/github.com/containers/ocicrypt/keywrap/pkcs11/keywrapper_pkcs11.go b/vendor/github.com/containers/ocicrypt/keywrap/pkcs11/keywrapper_pkcs11.go index 236764d2338..b9a83c53606 100644 --- a/vendor/github.com/containers/ocicrypt/keywrap/pkcs11/keywrapper_pkcs11.go +++ b/vendor/github.com/containers/ocicrypt/keywrap/pkcs11/keywrapper_pkcs11.go @@ -41,7 +41,11 @@ func NewKeyWrapper() keywrap.KeyWrapper { // WrapKeys wraps the session key for recpients and encrypts the optsData, which // describe the symmetric key used for encrypting the layer func (kw *pkcs11KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) { - pkcs11Recipients, err := addPubKeys(&ec.DecryptConfig, append(ec.Parameters["pkcs11-pubkeys"], ec.Parameters["pkcs11-yamls"]...)) + // append({}, ...) allocates a fresh backing array, and that's necessary to guarantee concurrent calls to WrapKeys (as in c/image/copy.Image) + // can't race writing to the same backing array. + pubKeys := append([][]byte{}, ec.Parameters["pkcs11-pubkeys"]...) // In Go 1.21, slices.Clone(ec.Parameters["pkcs11-pubkeys"]) + pubKeys = append(pubKeys, ec.Parameters["pkcs11-yamls"]...) + pkcs11Recipients, err := addPubKeys(&ec.DecryptConfig, pubKeys) if err != nil { return nil, err } diff --git a/vendor/github.com/containers/ocicrypt/spec/spec.go b/vendor/github.com/containers/ocicrypt/spec/spec.go index 8665f6f21c4..c0c171824f7 100644 --- a/vendor/github.com/containers/ocicrypt/spec/spec.go +++ b/vendor/github.com/containers/ocicrypt/spec/spec.go @@ -9,8 +9,12 @@ const ( MediaTypeLayerZstdEnc = "application/vnd.oci.image.layer.v1.tar+zstd+encrypted" // MediaTypeLayerNonDistributableEnc is MIME type used for non distributable encrypted layers. MediaTypeLayerNonDistributableEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+encrypted" - // MediaTypeLayerGzipEnc is MIME type used for non distributable encrypted gzip-compressed layers. + // MediaTypeLayerNonDistributableGzipEnc is MIME type used for non distributable encrypted gzip-compressed layers. MediaTypeLayerNonDistributableGzipEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip+encrypted" - // MediaTypeLayerZstdEnc is MIME type used for non distributable encrypted zstd-compressed layers. - MediaTypeLayerNonDistributableZsdtEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd+encrypted" + // MediaTypeLayerNonDistributableZstdEnc is MIME type used for non distributable encrypted zstd-compressed layers. + MediaTypeLayerNonDistributableZstdEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd+encrypted" + // MediaTypeLayerNonDistributableZsdtEnc is MIME type used for non distributable encrypted zstd-compressed layers. + // + // Deprecated: Use [MediaTypeLayerNonDistributableZstdEnc]. + MediaTypeLayerNonDistributableZsdtEnc = MediaTypeLayerNonDistributableZstdEnc ) diff --git a/vendor/github.com/containers/storage/.cirrus.yml b/vendor/github.com/containers/storage/.cirrus.yml index 00c69d7f128..c41dd5da2c5 100644 --- a/vendor/github.com/containers/storage/.cirrus.yml +++ b/vendor/github.com/containers/storage/.cirrus.yml @@ -17,13 +17,13 @@ env: #### #### Cache-image names to test with (double-quotes around names are critical) ### - FEDORA_NAME: "fedora-38" + FEDORA_NAME: "fedora-39ß" DEBIAN_NAME: "debian-13" # GCE project where images live IMAGE_PROJECT: "libpod-218412" # VM Image built in containers/automation_images - IMAGE_SUFFIX: "c20230816t191118z-f38f37d13" + IMAGE_SUFFIX: "c20231004t194547z-f39f38d13" FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" DEBIAN_CACHE_IMAGE_NAME: "debian-${IMAGE_SUFFIX}" @@ -113,8 +113,6 @@ debian_testing_task: &debian_testing TEST_DRIVER: "fuse-overlay-whiteout" - env: TEST_DRIVER: "btrfs" - - env: - TEST_DRIVER: "zfs" lint_task: diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index 7ef40656729..ba0a719118c 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.50.2 +1.51.0 diff --git a/vendor/github.com/containers/storage/drivers/driver.go b/vendor/github.com/containers/storage/drivers/driver.go index 1fb04dc3edb..ab32d652e7d 100644 --- a/vendor/github.com/containers/storage/drivers/driver.go +++ b/vendor/github.com/containers/storage/drivers/driver.go @@ -189,6 +189,9 @@ type DriverWithDifferOutput struct { BigData map[string][]byte TarSplit []byte TOCDigest digest.Digest + // Artifacts is a collection of additional artifacts + // generated by the differ that the storage driver can use. + Artifacts map[string]interface{} } type DifferOutputFormat int diff --git a/vendor/github.com/containers/storage/drivers/overlay/check.go b/vendor/github.com/containers/storage/drivers/overlay/check.go index 60980994b2c..d8139f65665 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/check.go +++ b/vendor/github.com/containers/storage/drivers/overlay/check.go @@ -275,3 +275,36 @@ func supportsIdmappedLowerLayers(home string) (bool, error) { }() return true, nil } + +// supportsDataOnlyLayers checks if the kernel supports mounting a overlay file system +// that uses data-only layers. +func supportsDataOnlyLayers(home string) (bool, error) { + layerDir, err := os.MkdirTemp(home, "compat") + if err != nil { + return false, err + } + defer func() { + _ = os.RemoveAll(layerDir) + }() + + mergedDir := filepath.Join(layerDir, "merged") + lowerDir := filepath.Join(layerDir, "lower") + lowerDirDataOnly := filepath.Join(layerDir, "lower-data") + upperDir := filepath.Join(layerDir, "upper") + workDir := filepath.Join(layerDir, "work") + + _ = idtools.MkdirAs(mergedDir, 0o700, 0, 0) + _ = idtools.MkdirAs(lowerDir, 0o700, 0, 0) + _ = idtools.MkdirAs(lowerDirDataOnly, 0o700, 0, 0) + _ = idtools.MkdirAs(upperDir, 0o700, 0, 0) + _ = idtools.MkdirAs(workDir, 0o700, 0, 0) + + opts := fmt.Sprintf("lowerdir=%s::%s,upperdir=%s,workdir=%s,metacopy=on", lowerDir, lowerDirDataOnly, upperDir, workDir) + flags := uintptr(0) + if err := unix.Mount("overlay", mergedDir, "overlay", flags, opts); err != nil { + return false, err + } + _ = unix.Unmount(mergedDir, unix.MNT_DETACH) + + return true, nil +} diff --git a/vendor/github.com/containers/storage/drivers/overlay/composefs_notsupported.go b/vendor/github.com/containers/storage/drivers/overlay/composefs_notsupported.go index 5cdbcff6c46..347e4d35c49 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/composefs_notsupported.go +++ b/vendor/github.com/containers/storage/drivers/overlay/composefs_notsupported.go @@ -11,7 +11,7 @@ func composeFsSupported() bool { return false } -func generateComposeFsBlob(toc []byte, composefsDir string) error { +func generateComposeFsBlob(verityDigests map[string]string, toc interface{}, composefsDir string) error { return fmt.Errorf("composefs is not supported") } @@ -19,6 +19,6 @@ func mountComposefsBlob(dataDir, mountPoint string) error { return fmt.Errorf("composefs is not supported") } -func enableVerityRecursive(path string) error { - return fmt.Errorf("composefs is not supported") +func enableVerityRecursive(path string) (map[string]string, error) { + return nil, fmt.Errorf("composefs is not supported") } diff --git a/vendor/github.com/containers/storage/drivers/overlay/composefs_supported.go b/vendor/github.com/containers/storage/drivers/overlay/composefs_supported.go index aaf76913172..26dd36866cc 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/composefs_supported.go +++ b/vendor/github.com/containers/storage/drivers/overlay/composefs_supported.go @@ -4,7 +4,6 @@ package overlay import ( - "bytes" "encoding/binary" "errors" "fmt" @@ -16,6 +15,7 @@ import ( "syscall" "unsafe" + "github.com/containers/storage/pkg/chunked/dump" "github.com/containers/storage/pkg/loopback" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" @@ -29,7 +29,7 @@ var ( func getComposeFsHelper() (string, error) { composeFsHelperOnce.Do(func() { - composeFsHelperPath, composeFsHelperErr = exec.LookPath("composefs-from-json") + composeFsHelperPath, composeFsHelperErr = exec.LookPath("mkcomposefs") }) return composeFsHelperPath, composeFsHelperErr } @@ -53,7 +53,23 @@ func enableVerity(description string, fd int) error { return nil } -func enableVerityRecursive(path string) error { +type verityDigest struct { + Fsv unix.FsverityDigest + Buf [64]byte +} + +func measureVerity(description string, fd int) (string, error) { + var digest verityDigest + digest.Fsv.Size = 64 + _, _, e1 := syscall.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.FS_IOC_MEASURE_VERITY), uintptr(unsafe.Pointer(&digest))) + if e1 != 0 { + return "", fmt.Errorf("failed to measure verity for %q: %w", description, e1) + } + return fmt.Sprintf("%x", digest.Buf[:digest.Fsv.Size]), nil +} + +func enableVerityRecursive(root string) (map[string]string, error) { + digests := make(map[string]string) walkFn := func(path string, d fs.DirEntry, err error) error { if err != nil { return err @@ -71,29 +87,47 @@ func enableVerityRecursive(path string) error { if err := enableVerity(path, int(f.Fd())); err != nil { return err } + + verity, err := measureVerity(path, int(f.Fd())) + if err != nil { + return err + } + + relPath, err := filepath.Rel(root, path) + if err != nil { + return err + } + + digests[relPath] = verity return nil } - return filepath.WalkDir(path, walkFn) + err := filepath.WalkDir(root, walkFn) + return digests, err } func getComposefsBlob(dataDir string) string { return filepath.Join(dataDir, "composefs.blob") } -func generateComposeFsBlob(toc []byte, composefsDir string) error { +func generateComposeFsBlob(verityDigests map[string]string, toc interface{}, composefsDir string) error { if err := os.MkdirAll(composefsDir, 0o700); err != nil { return err } + dumpReader, err := dump.GenerateDump(toc, verityDigests) + if err != nil { + return err + } + destFile := getComposefsBlob(composefsDir) writerJson, err := getComposeFsHelper() if err != nil { - return fmt.Errorf("failed to find composefs-from-json: %w", err) + return fmt.Errorf("failed to find mkcomposefs: %w", err) } fd, err := unix.Openat(unix.AT_FDCWD, destFile, unix.O_WRONLY|unix.O_CREAT|unix.O_TRUNC|unix.O_EXCL|unix.O_CLOEXEC, 0o644) if err != nil { - return fmt.Errorf("failed to open output file: %w", err) + return fmt.Errorf("failed to open output file %q: %w", destFile, err) } outFd := os.NewFile(uintptr(fd), "outFd") @@ -109,10 +143,10 @@ func generateComposeFsBlob(toc []byte, composefsDir string) error { // a scope to close outFd before setting fsverity on the read-only fd. defer outFd.Close() - cmd := exec.Command(writerJson, "--format=erofs", "--out=/proc/self/fd/3", "/proc/self/fd/0") + cmd := exec.Command(writerJson, "--from-file", "-", "/proc/self/fd/3") cmd.ExtraFiles = []*os.File{outFd} cmd.Stderr = os.Stderr - cmd.Stdin = bytes.NewReader(toc) + cmd.Stdin = dumpReader if err := cmd.Run(); err != nil { return fmt.Errorf("failed to convert json to erofs: %w", err) } @@ -166,7 +200,7 @@ func hasACL(path string) (bool, error) { func mountComposefsBlob(dataDir, mountPoint string) error { blobFile := getComposefsBlob(dataDir) - loop, err := loopback.AttachLoopDevice(blobFile) + loop, err := loopback.AttachLoopDeviceRO(blobFile) if err != nil { return err } diff --git a/vendor/github.com/containers/storage/drivers/overlay/mount.go b/vendor/github.com/containers/storage/drivers/overlay/mount.go index 33e60b1189a..8829e55e989 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/mount.go +++ b/vendor/github.com/containers/storage/drivers/overlay/mount.go @@ -141,14 +141,27 @@ func mountOverlayFromMain() { // the new value for the list of lowers, because it's shorter. if lowerv != "" { lowers := strings.Split(lowerv, ":") - for i := range lowers { - lowerFd, err := unix.Open(lowers[i], unix.O_RDONLY, 0) + var newLowers []string + dataOnly := false + for _, lowerPath := range lowers { + if lowerPath == "" { + dataOnly = true + continue + } + lowerFd, err := unix.Open(lowerPath, unix.O_RDONLY, 0) if err != nil { fatal(err) } - lowers[i] = fmt.Sprintf("%d", lowerFd) + var lower string + if dataOnly { + lower = fmt.Sprintf(":%d", lowerFd) + dataOnly = false + } else { + lower = fmt.Sprintf("%d", lowerFd) + } + newLowers = append(newLowers, lower) } - lowerv = strings.Join(lowers, ":") + lowerv = strings.Join(newLowers, ":") } // Reconstruct the Label field. diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index 0f6d74021fb..04ecf871fd0 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -82,7 +82,7 @@ const ( lowerFile = "lower" maxDepth = 500 - zstdChunkedManifest = "zstd-chunked-manifest" + tocArtifact = "toc" // idLength represents the number of random characters // which can be used to create the unique link identifier @@ -1003,8 +1003,10 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable } } if parent != "" { - parentBase, parentImageStore, _ := d.dir2(parent) - if parentImageStore != "" { + parentBase, parentImageStore, inAdditionalStore := d.dir2(parent) + // If parentBase path is additional image store, select the image contained in parentBase. + // See https://github.com/containers/podman/issues/19748 + if parentImageStore != "" && !inAdditionalStore { parentBase = parentImageStore } st, err := system.Stat(filepath.Join(parentBase, "diff")) @@ -1079,12 +1081,13 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable } if parent != "" { - parentDir, parentImageStore, _ := d.dir2(parent) - base := parentDir - if parentImageStore != "" { - base = parentImageStore + parentBase, parentImageStore, inAdditionalStore := d.dir2(parent) + // If parentBase path is additional image store, select the image contained in parentBase. + // See https://github.com/containers/podman/issues/19748 + if parentImageStore != "" && !inAdditionalStore { + parentBase = parentImageStore } - st, err := system.Stat(filepath.Join(base, "diff")) + st, err := system.Stat(filepath.Join(parentBase, "diff")) if err != nil { return err } @@ -1447,7 +1450,9 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO needsIDMapping := !disableShifting && len(options.UidMaps) > 0 && len(options.GidMaps) > 0 && d.options.mountProgram == "" if len(optsList) == 0 { - optsList = strings.Split(d.options.mountOptions, ",") + if d.options.mountOptions != "" { + optsList = strings.Split(d.options.mountOptions, ",") + } } else { // If metacopy=on is present in d.options.mountOptions it must be present in the mount // options otherwise the kernel refuses to follow the metacopy xattr. @@ -1524,15 +1529,8 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO defer cleanupFunc() } - composefsLayers := filepath.Join(workDirBase, "composefs-layers") - if err := os.MkdirAll(composefsLayers, 0o700); err != nil { - return "", err - } - skipIDMappingLayers := make(map[string]string) - composeFsLayers := []string{} - composefsMounts := []string{} defer func() { for _, m := range composefsMounts { @@ -1540,7 +1538,9 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO } }() - maybeAddComposefsMount := func(lowerID string, i int) (string, error) { + composeFsLayers := []string{} + composeFsLayersDir := filepath.Join(workDirBase, "composefs-layers") + maybeAddComposefsMount := func(lowerID string, i int, readWrite bool) (string, error) { composefsBlob := d.getComposefsData(lowerID) _, err = os.Stat(composefsBlob) if err != nil { @@ -1551,7 +1551,11 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO } logrus.Debugf("overlay: using composefs blob %s for lower %s", composefsBlob, lowerID) - dest := filepath.Join(composefsLayers, fmt.Sprintf("%d", i)) + if readWrite && i == 0 { + return "", fmt.Errorf("cannot mount a composefs layer as writeable") + } + + dest := filepath.Join(composeFsLayersDir, fmt.Sprintf("%d", i)) if err := os.MkdirAll(dest, 0o700); err != nil { return "", err } @@ -1571,7 +1575,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO diffDir := path.Join(workDirBase, "diff") - if dest, err := maybeAddComposefsMount(id, 0); err != nil { + if dest, err := maybeAddComposefsMount(id, 0, readWrite); err != nil { return "", err } else if dest != "" { diffDir = dest @@ -1623,7 +1627,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO return "", err } lowerID := filepath.Base(filepath.Dir(linkContent)) - composefsMount, err := maybeAddComposefsMount(lowerID, i+1) + composefsMount, err := maybeAddComposefsMount(lowerID, i+1, readWrite) if err != nil { return "", err } @@ -1655,8 +1659,6 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO optsList = append(optsList, "metacopy=on", "redirect_dir=on") } - absLowers = append(absLowers, composeFsLayers...) - if len(absLowers) == 0 { absLowers = append(absLowers, path.Join(dir, "empty")) } @@ -1750,11 +1752,20 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO absLowers = newAbsDir } + lowerDirs := strings.Join(absLowers, ":") + if len(composeFsLayers) > 0 { + composeFsLayersLowerDirs := strings.Join(composeFsLayers, "::") + lowerDirs = lowerDirs + "::" + composeFsLayersLowerDirs + } + // absLowers is not valid anymore now as we have added composeFsLayers to it, so prevent + // its usage. + absLowers = nil //nolint:ineffassign + var opts string if readWrite { - opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, workdir) + opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDirs, diffDir, workdir) } else { - opts = fmt.Sprintf("lowerdir=%s:%s", diffDir, strings.Join(absLowers, ":")) + opts = fmt.Sprintf("lowerdir=%s:%s", diffDir, lowerDirs) } if len(optsList) > 0 { opts = fmt.Sprintf("%s,%s", opts, strings.Join(optsList, ",")) @@ -1798,9 +1809,9 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO if readWrite { diffDir := path.Join(id, "diff") workDir := path.Join(id, "work") - opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, workDir) + opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDirs, diffDir, workDir) } else { - opts = fmt.Sprintf("lowerdir=%s:%s", diffDir, strings.Join(absLowers, ":")) + opts = fmt.Sprintf("lowerdir=%s:%s", diffDir, lowerDirs) } if len(optsList) > 0 { opts = strings.Join(append([]string{opts}, optsList...), ",") @@ -2007,11 +2018,34 @@ func (d *Driver) CleanupStagingDirectory(stagingDirectory string) error { return os.RemoveAll(stagingDirectory) } +func (d *Driver) supportsDataOnlyLayers() (bool, error) { + feature := "dataonly-layers" + overlayCacheResult, overlayCacheText, err := cachedFeatureCheck(d.runhome, feature) + if err == nil { + if overlayCacheResult { + logrus.Debugf("Cached value indicated that data-only layers for overlay are supported") + return true, nil + } + logrus.Debugf("Cached value indicated that data-only layers for overlay are not supported") + return false, errors.New(overlayCacheText) + } + supportsDataOnly, err := supportsDataOnlyLayers(d.home) + if err2 := cachedFeatureRecord(d.runhome, feature, supportsDataOnly, ""); err2 != nil { + return false, fmt.Errorf("recording overlay data-only layers support status: %w", err2) + } + return supportsDataOnly, err +} + func (d *Driver) useComposeFs() bool { if !composeFsSupported() || unshare.IsRootless() { return false } - return true + supportsDataOnlyLayers, err := d.supportsDataOnlyLayers() + if err != nil { + logrus.Debugf("Check for data-only layers failed with: %v", err) + return false + } + return supportsDataOnlyLayers } // ApplyDiff applies the changes in the new layer using the specified function @@ -2074,11 +2108,12 @@ func (d *Driver) ApplyDiffFromStagingDirectory(id, parent, stagingDirectory stri if d.useComposeFs() { // FIXME: move this logic into the differ so we don't have to open // the file twice. - if err := enableVerityRecursive(stagingDirectory); err != nil && !errors.Is(err, unix.ENOTSUP) && !errors.Is(err, unix.ENOTTY) { + verityDigests, err := enableVerityRecursive(stagingDirectory) + if err != nil && !errors.Is(err, unix.ENOTSUP) && !errors.Is(err, unix.ENOTTY) { logrus.Warningf("%s", err) } - toc := diffOutput.BigData[zstdChunkedManifest] - if err := generateComposeFsBlob(toc, d.getComposefsData(id)); err != nil { + toc := diffOutput.Artifacts[tocArtifact] + if err := generateComposeFsBlob(verityDigests, toc, d.getComposefsData(id)); err != nil { return err } } diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index e5835757f6a..d105e73f6cd 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -1245,8 +1245,8 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount if parentLayer != nil { parent = parentLayer.ID } - var parentMappings, templateIDMappings, oldMappings *idtools.IDMappings var ( + templateIDMappings *idtools.IDMappings templateMetadata string templateCompressedDigest digest.Digest templateCompressedSize int64 @@ -1274,11 +1274,6 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount } else { templateIDMappings = &idtools.IDMappings{} } - if parentLayer != nil { - parentMappings = idtools.NewIDMappingsFromMaps(parentLayer.UIDMap, parentLayer.GIDMap) - } else { - parentMappings = &idtools.IDMappings{} - } if mountLabel != "" { selinux.ReserveLabel(mountLabel) } @@ -1353,6 +1348,12 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount IDMappings: idMappings, } + var parentMappings, oldMappings *idtools.IDMappings + if parentLayer != nil { + parentMappings = idtools.NewIDMappingsFromMaps(parentLayer.UIDMap, parentLayer.GIDMap) + } else { + parentMappings = &idtools.IDMappings{} + } if moreOptions.TemplateLayer != "" { if err = r.driver.CreateFromTemplate(id, moreOptions.TemplateLayer, templateIDMappings, parent, parentMappings, &opts, writeable); err != nil { cleanupFailureContext = fmt.Sprintf("creating a layer from template layer %q", moreOptions.TemplateLayer) @@ -1371,10 +1372,13 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount return nil, -1, fmt.Errorf("creating read-only layer with ID %q: %w", id, err) } } - oldMappings = parentMappings + if parentLayer != nil { + oldMappings = parentMappings + } } - if !reflect.DeepEqual(oldMappings.UIDs(), idMappings.UIDs()) || !reflect.DeepEqual(oldMappings.GIDs(), idMappings.GIDs()) { + if oldMappings != nil && + (!reflect.DeepEqual(oldMappings.UIDs(), idMappings.UIDs()) || !reflect.DeepEqual(oldMappings.GIDs(), idMappings.GIDs())) { if err = r.driver.UpdateLayerIDMap(id, oldMappings, idMappings, mountLabel); err != nil { cleanupFailureContext = "in UpdateLayerIDMap" return nil, -1, err diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go index 29f800b2af5..05d25711827 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive.go @@ -955,14 +955,8 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err if options.ForceMask != nil { // if ForceMask is in place, make sure lchown is disabled. doChown = false - uid, gid, mode, err := GetFileOwner(dest) - if err == nil { - value := fmt.Sprintf("%d:%d:0%o", uid, gid, mode) - if err := system.Lsetxattr(dest, idtools.ContainersOverrideXattr, []byte(value), 0); err != nil { - return err - } - } } + var rootHdr *tar.Header // Iterate through the files in the archive. loop: @@ -1007,6 +1001,9 @@ loop: if err != nil { return err } + if rel == "." { + rootHdr = hdr + } if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { return breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest)) } @@ -1080,6 +1077,14 @@ loop: return err } } + + if options.ForceMask != nil && rootHdr != nil { + value := fmt.Sprintf("%d:%d:0%o", rootHdr.Uid, rootHdr.Gid, rootHdr.Mode) + if err := system.Lsetxattr(dest, idtools.ContainersOverrideXattr, []byte(value), 0); err != nil { + return err + } + } + return nil } diff --git a/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go b/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go index 56c30e2675c..5d4befc2348 100644 --- a/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go +++ b/vendor/github.com/containers/storage/pkg/chunked/cache_linux.go @@ -26,6 +26,8 @@ import ( const ( cacheKey = "chunked-manifest-cache" cacheVersion = 1 + + digestSha256Empty = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ) type metadata struct { @@ -650,6 +652,9 @@ func unmarshalToc(manifest []byte) (*internal.TOC, error) { iter.Skip() } } + if m.Type == TypeReg && m.Size == 0 && m.Digest == "" { + m.Digest = digestSha256Empty + } toc.Entries = append(toc.Entries, m) } break diff --git a/vendor/github.com/containers/storage/pkg/chunked/dump/dump.go b/vendor/github.com/containers/storage/pkg/chunked/dump/dump.go new file mode 100644 index 00000000000..a08928034ad --- /dev/null +++ b/vendor/github.com/containers/storage/pkg/chunked/dump/dump.go @@ -0,0 +1,230 @@ +package dump + +import ( + "bufio" + "fmt" + "io" + "strings" + "time" + "unicode" + + "github.com/containers/storage/pkg/chunked/internal" + "golang.org/x/sys/unix" +) + +const ( + ESCAPE_STANDARD = 0 + NOESCAPE_SPACE = 1 << iota + ESCAPE_EQUAL + ESCAPE_LONE_DASH +) + +func escaped(val string, escape int) string { + noescapeSpace := escape&NOESCAPE_SPACE != 0 + escapeEqual := escape&ESCAPE_EQUAL != 0 + escapeLoneDash := escape&ESCAPE_LONE_DASH != 0 + + length := len(val) + + if escapeLoneDash && val == "-" { + return fmt.Sprintf("\\x%.2x", val[0]) + } + + var result string + for i := 0; i < length; i++ { + c := val[i] + hexEscape := false + var special string + + switch c { + case '\\': + special = "\\\\" + case '\n': + special = "\\n" + case '\r': + special = "\\r" + case '\t': + special = "\\t" + case '=': + hexEscape = escapeEqual + default: + if noescapeSpace { + hexEscape = !unicode.IsPrint(rune(c)) + } else { + hexEscape = !unicode.IsGraphic(rune(c)) + } + } + + if special != "" { + result += special + } else if hexEscape { + result += fmt.Sprintf("\\x%.2x", c) + } else { + result += string(c) + } + } + return result +} + +func escapedOptional(val string, escape int) string { + if val == "" { + return "-" + } + return escaped(val, escape) +} + +func getStMode(mode uint32, typ string) (uint32, error) { + switch typ { + case internal.TypeReg, internal.TypeLink: + mode |= unix.S_IFREG + case internal.TypeChar: + mode |= unix.S_IFCHR + case internal.TypeBlock: + mode |= unix.S_IFBLK + case internal.TypeDir: + mode |= unix.S_IFDIR + case internal.TypeFifo: + mode |= unix.S_IFIFO + case internal.TypeSymlink: + mode |= unix.S_IFLNK + default: + return 0, fmt.Errorf("unknown type %s", typ) + } + return mode, nil +} + +func dumpNode(out io.Writer, links map[string]int, verityDigests map[string]string, entry *internal.FileMetadata) error { + path := entry.Name + if path == "" { + path = "/" + } else if path[0] != '/' { + path = "/" + path + } + + if _, err := fmt.Fprint(out, escaped(path, ESCAPE_STANDARD)); err != nil { + return err + } + + nlinks := links[entry.Name] + links[entry.Linkname] + 1 + link := "" + if entry.Type == internal.TypeLink { + link = "@" + } + + rdev := unix.Mkdev(uint32(entry.Devmajor), uint32(entry.Devminor)) + + entryTime := entry.ModTime + if entryTime == nil { + t := time.Unix(0, 0) + entryTime = &t + } + + mode, err := getStMode(uint32(entry.Mode), entry.Type) + if err != nil { + return err + } + + if _, err := fmt.Fprintf(out, " %d %s%o %d %d %d %d %d.%d ", entry.Size, + link, mode, + nlinks, entry.UID, entry.GID, rdev, + entryTime.Unix(), entryTime.Nanosecond()); err != nil { + return err + } + + var payload string + if entry.Linkname != "" { + payload = entry.Linkname + if entry.Type == internal.TypeLink && payload[0] != '/' { + payload = "/" + payload + } + } else { + if len(entry.Digest) > 10 { + d := strings.Replace(entry.Digest, "sha256:", "", 1) + payload = d[:2] + "/" + d[2:] + } + } + + if _, err := fmt.Fprintf(out, escapedOptional(payload, ESCAPE_LONE_DASH)); err != nil { + return err + } + + /* inline content. */ + if _, err := fmt.Fprint(out, " -"); err != nil { + return err + } + + /* store the digest. */ + if _, err := fmt.Fprint(out, " "); err != nil { + return err + } + digest := verityDigests[payload] + if _, err := fmt.Fprintf(out, escapedOptional(digest, ESCAPE_LONE_DASH)); err != nil { + return err + } + + for k, v := range entry.Xattrs { + name := escaped(k, ESCAPE_EQUAL) + value := escaped(v, ESCAPE_EQUAL) + + if _, err := fmt.Fprintf(out, " %s=%s", name, value); err != nil { + return err + } + } + if _, err := fmt.Fprint(out, "\n"); err != nil { + return err + } + return nil +} + +// GenerateDump generates a dump of the TOC in the same format as `composefs-info dump` +func GenerateDump(tocI interface{}, verityDigests map[string]string) (io.Reader, error) { + toc, ok := tocI.(*internal.TOC) + if !ok { + return nil, fmt.Errorf("invalid TOC type") + } + pipeR, pipeW := io.Pipe() + go func() { + closed := false + w := bufio.NewWriter(pipeW) + defer func() { + if !closed { + w.Flush() + pipeW.Close() + } + }() + + links := make(map[string]int) + for _, e := range toc.Entries { + if e.Linkname == "" { + continue + } + links[e.Linkname] = links[e.Linkname] + 1 + } + + if len(toc.Entries) == 0 || (toc.Entries[0].Name != "" && toc.Entries[0].Name != "/") { + root := &internal.FileMetadata{ + Name: "/", + Type: internal.TypeDir, + Mode: 0o755, + } + + if err := dumpNode(w, links, verityDigests, root); err != nil { + pipeW.CloseWithError(err) + closed = true + return + } + } + + for _, e := range toc.Entries { + if e.Type == internal.TypeChunk { + continue + } + if err := dumpNode(w, links, verityDigests, &e); err != nil { + pipeW.CloseWithError(err) + closed = true + return + } + } + }() + return pipeR, nil +} diff --git a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go index 088c92782cb..8493a2c19aa 100644 --- a/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go +++ b/vendor/github.com/containers/storage/pkg/chunked/storage_linux.go @@ -45,6 +45,7 @@ const ( bigDataKey = "zstd-chunked-manifest" chunkedData = "zstd-chunked-data" chunkedLayerDataKey = "zstd-chunked-layer-data" + tocKey = "toc" fileTypeZstdChunked = iota fileTypeEstargz @@ -1470,10 +1471,7 @@ func makeEntriesFlat(mergedEntries []internal.FileMetadata) ([]internal.FileMeta continue } if mergedEntries[i].Digest == "" { - if mergedEntries[i].Size != 0 { - return nil, fmt.Errorf("missing digest for %q", mergedEntries[i].Name) - } - continue + return nil, fmt.Errorf("missing digest for %q", mergedEntries[i].Name) } digest, err := digest.Parse(mergedEntries[i].Digest) if err != nil { @@ -1542,6 +1540,13 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, diff if err != nil { return graphdriver.DriverWithDifferOutput{}, err } + + // Generate the manifest + toc, err := unmarshalToc(c.manifest) + if err != nil { + return graphdriver.DriverWithDifferOutput{}, err + } + output := graphdriver.DriverWithDifferOutput{ Differ: c, TarSplit: c.tarSplit, @@ -1549,6 +1554,9 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, diff bigDataKey: c.manifest, chunkedLayerDataKey: lcdBigData, }, + Artifacts: map[string]interface{}{ + tocKey: toc, + }, TOCDigest: c.contentDigest, } @@ -1563,12 +1571,6 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions, diff // List of OSTree repositories to use for deduplication ostreeRepos := strings.Split(c.storeOpts.PullOptions["ostree_repos"], ":") - // Generate the manifest - toc, err := unmarshalToc(c.manifest) - if err != nil { - return output, err - } - whiteoutConverter := archive.GetWhiteoutConverter(options.WhiteoutFormat, options.WhiteoutData) var missingParts []missingPart diff --git a/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go b/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go index b8bfa589775..40d8fd2b89a 100644 --- a/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go +++ b/vendor/github.com/containers/storage/pkg/loopback/attach_loopback.go @@ -114,6 +114,16 @@ func openNextAvailableLoopback(index int, sparseName string, sparseFile *os.File // AttachLoopDevice attaches the given sparse file to the next // available loopback device. It returns an opened *os.File. func AttachLoopDevice(sparseName string) (loop *os.File, err error) { + return attachLoopDevice(sparseName, false) +} + +// AttachLoopDeviceRO attaches the given sparse file opened read-only to +// the next available loopback device. It returns an opened *os.File. +func AttachLoopDeviceRO(sparseName string) (loop *os.File, err error) { + return attachLoopDevice(sparseName, true) +} + +func attachLoopDevice(sparseName string, readonly bool) (loop *os.File, err error) { // Try to retrieve the next available loopback device via syscall. // If it fails, we discard error and start looping for a // loopback from index 0. @@ -122,8 +132,14 @@ func AttachLoopDevice(sparseName string) (loop *os.File, err error) { logrus.Debugf("Error retrieving the next available loopback: %s", err) } + var sparseFile *os.File + // OpenFile adds O_CLOEXEC - sparseFile, err := os.OpenFile(sparseName, os.O_RDWR, 0o644) + if readonly { + sparseFile, err = os.OpenFile(sparseName, os.O_RDONLY, 0o644) + } else { + sparseFile, err = os.OpenFile(sparseName, os.O_RDWR, 0o644) + } if err != nil { logrus.Errorf("Opening sparse file: %v", err) return nil, ErrAttachLoopbackDevice diff --git a/vendor/github.com/containers/storage/pkg/system/rm.go b/vendor/github.com/containers/storage/pkg/system/rm.go index 5917fa251d2..12243707ac5 100644 --- a/vendor/github.com/containers/storage/pkg/system/rm.go +++ b/vendor/github.com/containers/storage/pkg/system/rm.go @@ -28,7 +28,7 @@ func EnsureRemoveAll(dir string) error { // track retries exitOnErr := make(map[string]int) - maxRetry := 100 + maxRetry := 1000 // Attempt a simple remove all first, this avoids the more expensive // RecursiveUnmount call if not needed. @@ -38,7 +38,7 @@ func EnsureRemoveAll(dir string) error { // Attempt to unmount anything beneath this dir first if err := mount.RecursiveUnmount(dir); err != nil { - logrus.Debugf("RecusiveUnmount on %s failed: %v", dir, err) + logrus.Debugf("RecursiveUnmount on %s failed: %v", dir, err) } for { @@ -94,6 +94,6 @@ func EnsureRemoveAll(dir string) error { return err } exitOnErr[pe.Path]++ - time.Sleep(100 * time.Millisecond) + time.Sleep(10 * time.Millisecond) } } diff --git a/vendor/github.com/containers/storage/pkg/unshare/unshare_darwin.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_darwin.go index 86ac12ecab2..480e2fcb09e 100644 --- a/vendor/github.com/containers/storage/pkg/unshare/unshare_darwin.go +++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_darwin.go @@ -25,6 +25,11 @@ func GetRootlessUID() int { return os.Getuid() } +// GetRootlessGID returns the GID of the user in the parent userNS +func GetRootlessGID() int { + return os.Getgid() +} + // RootlessEnv returns the environment settings for the rootless containers func RootlessEnv() []string { return append(os.Environ(), UsernsEnvName+"=") diff --git a/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go index e169633d05c..a8dc1ba0387 100644 --- a/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go +++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go @@ -441,6 +441,16 @@ func GetRootlessUID() int { return os.Getuid() } +// GetRootlessGID returns the GID of the user in the parent userNS +func GetRootlessGID() int { + gidEnv := getenv("_CONTAINERS_ROOTLESS_GID") + if gidEnv != "" { + u, _ := strconv.Atoi(gidEnv) + return u + } + return os.Getgid() +} + // RootlessEnv returns the environment settings for the rootless containers func RootlessEnv() []string { return append(os.Environ(), UsernsEnvName+"=done") diff --git a/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported.go index 66dd545966e..83de680c207 100644 --- a/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported.go +++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported.go @@ -25,6 +25,11 @@ func GetRootlessUID() int { return os.Getuid() } +// GetRootlessGID returns the GID of the user in the parent userNS +func GetRootlessGID() int { + return os.Getgid() +} + // RootlessEnv returns the environment settings for the rootless containers func RootlessEnv() []string { return append(os.Environ(), UsernsEnvName+"=") diff --git a/vendor/github.com/containers/storage/storage.conf b/vendor/github.com/containers/storage/storage.conf index 7082c0b7f40..cb4525f27d9 100644 --- a/vendor/github.com/containers/storage/storage.conf +++ b/vendor/github.com/containers/storage/storage.conf @@ -27,9 +27,8 @@ runroot = "/run/containers/storage" # restorecon -R -v /NEWSTORAGEPATH graphroot = "/var/lib/containers/storage" -# Optional value for image storage location -# If set, it must be different than graphroot. - +# Optional alternate location of image store if a location separate from the +# container store is required. If set, it must be different than graphroot. # imagestore = "" diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index dc9d09b89c6..6753b296ff4 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -2666,34 +2666,23 @@ func (s *store) DeleteContainer(id string) error { } var wg multierror.Group - wg.Go(func() error { return s.containerStore.Delete(id) }) middleDir := s.graphDriverName + "-containers" wg.Go(func() error { gcpath := filepath.Join(s.GraphRoot(), middleDir, container.ID) - // attempt a simple rm -rf first - if err := os.RemoveAll(gcpath); err == nil { - return nil - } - // and if it fails get to the more complicated cleanup return system.EnsureRemoveAll(gcpath) }) wg.Go(func() error { rcpath := filepath.Join(s.RunRoot(), middleDir, container.ID) - // attempt a simple rm -rf first - if err := os.RemoveAll(rcpath); err == nil { - return nil - } - // and if it fails get to the more complicated cleanup return system.EnsureRemoveAll(rcpath) }) if multierr := wg.Wait(); multierr != nil { return multierr.ErrorOrNil() } - return nil + return s.containerStore.Delete(id) }) } @@ -3418,16 +3407,16 @@ func (s *store) Shutdown(force bool) ([]string, error) { err = fmt.Errorf("a layer is mounted: %w", ErrLayerUsedByContainer) } if err == nil { - err = s.graphDriver.Cleanup() // We don’t retain the lastWrite value, and treat this update as if someone else did the .Cleanup(), // so that we reload after a .Shutdown() the same way other processes would. // Shutdown() is basically an error path, so reliability is more important than performance. if _, err2 := s.graphLock.RecordWrite(); err2 != nil { - if err == nil { - err = err2 - } else { - err = fmt.Errorf("(graphLock.RecordWrite failed: %v) %w", err2, err) - } + err = fmt.Errorf("graphLock.RecordWrite failed: %w", err2) + } + // Do the Cleanup() only after we are sure that the change was recorded with RecordWrite(), so that + // the next user picks it. + if err == nil { + err = s.graphDriver.Cleanup() } } return mounted, err diff --git a/vendor/github.com/containers/storage/types/options.go b/vendor/github.com/containers/storage/types/options.go index ab041a07069..5ae667a4935 100644 --- a/vendor/github.com/containers/storage/types/options.go +++ b/vendor/github.com/containers/storage/types/options.go @@ -220,9 +220,8 @@ type StoreOptions struct { // GraphRoot is the filesystem path under which we will store the // contents of layers, images, and containers. GraphRoot string `json:"root,omitempty"` - // Image Store is the location of image store which is seperated from the - // container store. Usually this is not recommended unless users wants - // seperate store for image and containers. + // Image Store is the alternate location of image store if a location + // separate from the container store is required. ImageStore string `json:"imagestore,omitempty"` // RootlessStoragePath is the storage path for rootless users // default $HOME/.local/share/containers/storage diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go index b4800567345..42bf32aab00 100644 --- a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go +++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/md2man.go @@ -9,6 +9,8 @@ func Render(doc []byte) []byte { renderer := NewRoffRenderer() return blackfriday.Run(doc, - []blackfriday.Option{blackfriday.WithRenderer(renderer), - blackfriday.WithExtensions(renderer.GetExtensions())}...) + []blackfriday.Option{ + blackfriday.WithRenderer(renderer), + blackfriday.WithExtensions(renderer.GetExtensions()), + }...) } diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go index be2b3436062..4b19188d90f 100644 --- a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go +++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go @@ -1,6 +1,7 @@ package md2man import ( + "bytes" "fmt" "io" "os" @@ -34,10 +35,10 @@ const ( hruleTag = "\n.ti 0\n\\l'\\n(.lu'\n" linkTag = "\n\\[la]" linkCloseTag = "\\[ra]" - codespanTag = "\\fB\\fC" + codespanTag = "\\fB" codespanCloseTag = "\\fR" - codeTag = "\n.PP\n.RS\n\n.nf\n" - codeCloseTag = "\n.fi\n.RE\n" + codeTag = "\n.EX\n" + codeCloseTag = "\n.EE\n" quoteTag = "\n.PP\n.RS\n" quoteCloseTag = "\n.RE\n" listTag = "\n.RS\n" @@ -86,8 +87,7 @@ func (r *roffRenderer) RenderFooter(w io.Writer, ast *blackfriday.Node) { // RenderNode is called for each node in a markdown document; based on the node // type the equivalent roff output is sent to the writer func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus { - - var walkAction = blackfriday.GoToNext + walkAction := blackfriday.GoToNext switch node.Type { case blackfriday.Text: @@ -109,9 +109,16 @@ func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering out(w, strongCloseTag) } case blackfriday.Link: - if !entering { - out(w, linkTag+string(node.LinkData.Destination)+linkCloseTag) + // Don't render the link text for automatic links, because this + // will only duplicate the URL in the roff output. + // See https://daringfireball.net/projects/markdown/syntax#autolink + if !bytes.Equal(node.LinkData.Destination, node.FirstChild.Literal) { + out(w, string(node.FirstChild.Literal)) } + // Hyphens in a link must be escaped to avoid word-wrap in the rendered man page. + escapedLink := strings.ReplaceAll(string(node.LinkData.Destination), "-", "\\-") + out(w, linkTag+escapedLink+linkCloseTag) + walkAction = blackfriday.SkipChildren case blackfriday.Image: // ignore images walkAction = blackfriday.SkipChildren @@ -160,6 +167,11 @@ func (r *roffRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering r.handleTableCell(w, node, entering) case blackfriday.HTMLSpan: // ignore other HTML tags + case blackfriday.HTMLBlock: + if bytes.HasPrefix(node.Literal, []byte("