Merge pull request #18835 from Luap99/update-container-deps

update c/{common,image,storage} to latest
This commit is contained in:
OpenShift Merge Robot 2023-06-12 08:36:07 -04:00 committed by GitHub
commit c83589a852
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
200 changed files with 5119 additions and 12965 deletions

View File

@ -57,6 +57,7 @@ BUILDTAGS ?= \
$(shell hack/libsubid_tag.sh) \ $(shell hack/libsubid_tag.sh) \
exclude_graphdriver_devicemapper \ exclude_graphdriver_devicemapper \
seccomp seccomp
ROOTLESSPORTTAGS ?= exclude_graphdriver_aufs exclude_graphdriver_btrfs exclude_graphdriver_devicemapper exclude_graphdriver_overlay exclude_graphdriver_zfs
PYTHON ?= $(shell command -v python3 python|head -n1) PYTHON ?= $(shell command -v python3 python|head -n1)
PKG_MANAGER ?= $(shell command -v dnf yum|head -n1) PKG_MANAGER ?= $(shell command -v dnf yum|head -n1)
# ~/.local/bin is not in PATH on all systems # ~/.local/bin is not in PATH on all systems
@ -401,6 +402,7 @@ bin/rootlessport: $(SOURCES) go.mod go.sum
CGO_ENABLED=$(CGO_ENABLED) \ CGO_ENABLED=$(CGO_ENABLED) \
$(GO) build \ $(GO) build \
$(BUILDFLAGS) \ $(BUILDFLAGS) \
-tags "$(ROOTLESSPORTTAGS)" \
-o $@ ./cmd/rootlessport -o $@ ./cmd/rootlessport
.PHONY: rootlessport .PHONY: rootlessport

View File

@ -4,6 +4,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"strconv"
"strings"
"github.com/containers/common/libnetwork/types" "github.com/containers/common/libnetwork/types"
"github.com/containers/common/libnetwork/util" "github.com/containers/common/libnetwork/util"
@ -77,6 +79,10 @@ func networkCreateFlags(cmd *cobra.Command) {
flags.StringArrayVar(&networkCreateOptions.Subnets, subnetFlagName, nil, "subnets in CIDR format") flags.StringArrayVar(&networkCreateOptions.Subnets, subnetFlagName, nil, "subnets in CIDR format")
_ = cmd.RegisterFlagCompletionFunc(subnetFlagName, completion.AutocompleteNone) _ = cmd.RegisterFlagCompletionFunc(subnetFlagName, completion.AutocompleteNone)
routeFlagName := "route"
flags.StringArrayVar(&networkCreateOptions.Routes, routeFlagName, nil, "static routes")
_ = cmd.RegisterFlagCompletionFunc(routeFlagName, completion.AutocompleteNone)
interfaceFlagName := "interface-name" interfaceFlagName := "interface-name"
flags.StringVar(&networkCreateOptions.InterfaceName, interfaceFlagName, "", "interface name which is used by the driver") flags.StringVar(&networkCreateOptions.InterfaceName, interfaceFlagName, "", "interface name which is used by the driver")
_ = cmd.RegisterFlagCompletionFunc(interfaceFlagName, completion.AutocompleteNone) _ = cmd.RegisterFlagCompletionFunc(interfaceFlagName, completion.AutocompleteNone)
@ -176,6 +182,16 @@ func networkCreate(cmd *cobra.Command, args []string) error {
return errors.New("cannot set gateway or range without subnet") return errors.New("cannot set gateway or range without subnet")
} }
for i := range networkCreateOptions.Routes {
route, err := parseRoute(networkCreateOptions.Routes[i])
if err != nil {
return err
}
network.Routes = append(network.Routes, *route)
}
extraCreateOptions := types.NetworkCreateOptions{ extraCreateOptions := types.NetworkCreateOptions{
IgnoreIfExists: networkCreateOptions.IgnoreIfExists, IgnoreIfExists: networkCreateOptions.IgnoreIfExists,
} }
@ -188,6 +204,46 @@ func networkCreate(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func parseRoute(routeStr string) (*types.Route, error) {
s := strings.Split(routeStr, ",")
var metric *uint32
if len(s) == 2 || len(s) == 3 {
dstStr := s[0]
gwStr := s[1]
destination, err := types.ParseCIDR(dstStr)
gateway := net.ParseIP(gwStr)
if err != nil {
return nil, fmt.Errorf("invalid route destination %s", dstStr)
}
if gateway == nil {
return nil, fmt.Errorf("invalid route gateway %s", gwStr)
}
if len(s) == 3 {
mtr, err := strconv.ParseUint(s[2], 10, 32)
if err != nil {
return nil, fmt.Errorf("invalid route metric %s", s[2])
}
x := uint32(mtr)
metric = &x
}
r := types.Route{
Destination: destination,
Gateway: gateway,
Metric: metric,
}
return &r, nil
}
return nil, fmt.Errorf("invalid route: %s\nFormat: --route <destination in CIDR>,<gateway>,<metric (optional)>", routeStr)
}
func parseRange(iprange string) (*types.LeaseRange, error) { func parseRange(iprange string) (*types.LeaseRange, error) {
_, subnet, err := net.ParseCIDR(iprange) _, subnet, err := net.ParseCIDR(iprange)
if err != nil { if err != nil {

View File

@ -95,10 +95,12 @@ Set metadata for a network (e.g., --label mykey=value).
Set driver specific options. Set driver specific options.
All drivers accept the `mtu` and `metric` options. All drivers accept the `mtu`, `metric`, `no_default_route` and options.
- `mtu`: Sets the Maximum Transmission Unit (MTU) and takes an integer value. - `mtu`: Sets the Maximum Transmission Unit (MTU) and takes an integer value.
- `metric` Sets the Route Metric for the default route created in every container joined to this network. Accepts a positive integer value. Can only be used with the Netavark network backend. - `metric` Sets the Route Metric for the default route created in every container joined to this network. Accepts a positive integer value. Can only be used with the Netavark network backend.
- `no_default_route`: If set to 1, Podman will not automatically add a default route to subnets. Routes can still be added
manually by creating a custom route using `--route`.
Additionally the `bridge` driver supports the following options: Additionally the `bridge` driver supports the following options:
@ -114,6 +116,10 @@ The `macvlan` and `ipvlan` driver support the following options:
- Supported values for `macvlan` are `bridge`, `private`, `vepa`, `passthru`. Defaults to `bridge`. - Supported values for `macvlan` are `bridge`, `private`, `vepa`, `passthru`. Defaults to `bridge`.
- Supported values for `ipvlan` are `l2`, `l3`, `l3s`. Defaults to `l2`. - Supported values for `ipvlan` are `l2`, `l3`, `l3s`. Defaults to `l2`.
#### **--route**=*route*
A static route in the format <destination in CIDR notation>,<gateway>,<route metric (optional)>. This route will be added to every container in this network. Only available with the netavark backend. It can be specified multiple times if more than one static route is desired.
#### **--subnet**=*subnet* #### **--subnet**=*subnet*
The subnet in CIDR notation. Can be specified multiple times to allocate more than one subnet for this network. The subnet in CIDR notation. Can be specified multiple times to allocate more than one subnet for this network.
@ -158,6 +164,17 @@ $ podman network create --subnet 192.168.55.0/24 --gateway 192.168.55.3 --subnet
podman4 podman4
``` ```
Create a network with a static subnet and a static route.
```
$ podman network create --subnet 192.168.33.0/24 --route 10.1.0.0/24,192.168.33.10 newnet
```
Create a network with a static subnet and a static route without a default
route.
```
$ podman network create --subnet 192.168.33.0/24 --route 10.1.0.0/24,192.168.33.10 --opt no_default_route=1 newnet
```
Create a Macvlan based network using the host interface eth0. Macvlan networks can only be used as root. Create a Macvlan based network using the host interface eth0. Macvlan networks can only be used as root.
``` ```
$ sudo podman network create -d macvlan -o parent=eth0 --subnet 192.5.0.0/16 newnet $ sudo podman network create -d macvlan -o parent=eth0 --subnet 192.5.0.0/16 newnet

View File

@ -28,6 +28,7 @@ Pretty-print networks to JSON or using a Go template.
| .NetworkDNSServers | Array of DNS servers used in this network | | .NetworkDNSServers | Array of DNS servers used in this network |
| .NetworkInterface | Name of the network interface on the host | | .NetworkInterface | Name of the network interface on the host |
| .Options | Network options | | .Options | Network options |
| .Routes | List of static routes for this network |
| .Subnets | List of subnets on this network | | .Subnets | List of subnets on this network |
## EXAMPLE ## EXAMPLE

View File

@ -56,6 +56,7 @@ Valid placeholders for the Go template are listed below:
| .NetworkDNSServers | Array of DNS servers used in this network | | .NetworkDNSServers | Array of DNS servers used in this network |
| .NetworkInterface | Name of the network interface on the host | | .NetworkInterface | Name of the network interface on the host |
| .Options | Network options | | .Options | Network options |
| .Routes | List of static routes for this network |
| .Subnets | List of subnets on this network | | .Subnets | List of subnets on this network |
#### **--no-trunc** #### **--no-trunc**

43
go.mod
View File

@ -13,19 +13,19 @@ require (
github.com/containernetworking/cni v1.1.2 github.com/containernetworking/cni v1.1.2
github.com/containernetworking/plugins v1.3.0 github.com/containernetworking/plugins v1.3.0
github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07 github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07
github.com/containers/common v0.53.1-0.20230506101404-3e93a76d461c github.com/containers/common v0.53.1-0.20230608150349-2c1849f43e14
github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.25.1-0.20230505072505-dc4a4be9cc1e github.com/containers/image/v5 v5.25.1-0.20230608153337-8ad019310ff2
github.com/containers/libhvee v0.0.5 github.com/containers/libhvee v0.0.5
github.com/containers/ocicrypt v1.1.7 github.com/containers/ocicrypt v1.1.7
github.com/containers/psgo v1.8.0 github.com/containers/psgo v1.8.0
github.com/containers/storage v1.46.1 github.com/containers/storage v1.46.2-0.20230530174214-1dc289a244ce
github.com/coreos/go-systemd/v22 v22.5.0 github.com/coreos/go-systemd/v22 v22.5.0
github.com/coreos/stream-metadata-go v0.4.2 github.com/coreos/stream-metadata-go v0.4.2
github.com/crc-org/vfkit v0.0.5-0.20230602131541-3d57f09010c9 github.com/crc-org/vfkit v0.0.5-0.20230602131541-3d57f09010c9
github.com/cyphar/filepath-securejoin v0.2.3 github.com/cyphar/filepath-securejoin v0.2.3
github.com/digitalocean/go-qemu v0.0.0-20221209210016-f035778c97f7 github.com/digitalocean/go-qemu v0.0.0-20221209210016-f035778c97f7
github.com/docker/docker v24.0.0+incompatible github.com/docker/docker v24.0.2+incompatible
github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651 github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0
@ -43,7 +43,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.17 github.com/mattn/go-sqlite3 v1.14.17
github.com/moby/term v0.5.0 github.com/moby/term v0.5.0
github.com/nxadm/tail v1.4.8 github.com/nxadm/tail v1.4.8
github.com/onsi/ginkgo/v2 v2.9.7 github.com/onsi/ginkgo/v2 v2.10.0
github.com/onsi/gomega v1.27.8 github.com/onsi/gomega v1.27.8
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc3 github.com/opencontainers/image-spec v1.1.0-rc3
@ -74,19 +74,19 @@ require (
) )
require ( require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/hcsshim v0.10.0-rc.7 // indirect github.com/Microsoft/hcsshim v0.10.0-rc.8 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/chzyer/readline v1.5.1 // indirect github.com/chzyer/readline v1.5.1 // indirect
github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/containerd v1.7.0 // indirect github.com/containerd/containerd v1.7.2 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
github.com/coreos/go-oidc/v3 v3.5.0 // indirect github.com/coreos/go-oidc/v3 v3.6.0 // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e // indirect github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e // indirect
github.com/disiqueira/gotree/v3 v3.0.2 // indirect github.com/disiqueira/gotree/v3 v3.0.2 // indirect
@ -113,14 +113,13 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-containerregistry v0.14.0 // indirect github.com/google/go-containerregistry v0.15.2 // indirect
github.com/google/go-intervals v0.0.2 // indirect github.com/google/go-intervals v0.0.2 // indirect
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect
github.com/google/trillian v1.5.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
github.com/imdario/mergo v0.3.15 // indirect github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/copier v0.3.5 // indirect github.com/jinzhu/copier v0.3.5 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
@ -132,7 +131,7 @@ require (
github.com/manifoldco/promptui v0.9.0 // 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.14 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mistifyio/go-zfs/v3 v3.0.0 // indirect github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/patternmatcher v0.5.0 // indirect
github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect
@ -151,11 +150,11 @@ require (
github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/seccomp/libseccomp-golang v0.10.0 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect github.com/segmentio/ksuid v1.0.4 // indirect
github.com/sigstore/fulcio v1.3.1 // indirect github.com/sigstore/fulcio v1.3.1 // indirect
github.com/sigstore/rekor v1.1.2-0.20230508234306-ad288b385a44 // indirect github.com/sigstore/rekor v1.2.2-0.20230601122533-4c81ff246d12 // indirect
github.com/sigstore/sigstore v1.6.4 // indirect github.com/sigstore/sigstore v1.6.5 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
github.com/sylabs/sif/v2 v2.11.3 // indirect github.com/sylabs/sif/v2 v2.11.4 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/theupdateframework/go-tuf v0.5.2 // indirect github.com/theupdateframework/go-tuf v0.5.2 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
@ -166,11 +165,11 @@ require (
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.15.0 // indirect go.opentelemetry.io/otel v1.15.0 // indirect
go.opentelemetry.io/otel/trace v1.15.0 // indirect go.opentelemetry.io/otel/trace v1.15.0 // indirect
golang.org/x/crypto v0.8.0 // indirect golang.org/x/crypto v0.9.0 // indirect
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/mod v0.10.0 // indirect golang.org/x/mod v0.10.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/tools v0.9.1 // indirect golang.org/x/tools v0.9.3 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.55.0 // indirect google.golang.org/grpc v1.55.0 // indirect

115
go.sum
View File

@ -14,7 +14,6 @@ cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZ
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 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.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
@ -28,8 +27,8 @@ github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
@ -66,8 +65,8 @@ 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.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.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.10.0-rc.7 h1:HBytQPxcv8Oy4244zbQbe6hnOnx544eL5QPUqhJldz8= github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek=
github.com/Microsoft/hcsshim v0.10.0-rc.7/go.mod h1:ILuwjA+kNW+MrN/w5un7n3mTqkwsFu4Bp05/okFUZlE= github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= 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/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/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@ -181,8 +180,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.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.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
github.com/containerd/containerd v1.7.0 h1:G/ZQr3gMZs6ZT0qPUZ15znx5QSdQdASW11nXTLTM2Pg= github.com/containerd/containerd v1.7.2 h1:UF2gdONnxO8I6byZXDi5sXWiWvlW3D/sci7dTQimEJo=
github.com/containerd/containerd v1.7.0/go.mod h1:QfR7Efgb/6X2BDpTPJRvPTYDE9rsF0FsXX9J8sIs/sc= github.com/containerd/containerd v1.7.2/go.mod h1:afcz74+K10M/+cjGHIVQrCt3RAQhUSCAjJ9iMYhhkuI=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= 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-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
@ -240,12 +239,12 @@ github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q
github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0= github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0=
github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07 h1:Bs2sNFh/fSYr4J6JJLFqzyn3dp6HhlA6ewFwRYUpeIE= github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07 h1:Bs2sNFh/fSYr4J6JJLFqzyn3dp6HhlA6ewFwRYUpeIE=
github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07/go.mod h1:6A/BK0YJLXL8+AqlbceKJrhUT+NtEgsvAc51F7TAllc= github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07/go.mod h1:6A/BK0YJLXL8+AqlbceKJrhUT+NtEgsvAc51F7TAllc=
github.com/containers/common v0.53.1-0.20230506101404-3e93a76d461c h1:NPf//8NAa6xjlj62eBbEBabu8LWVqxPRuweNAFCAYxs= github.com/containers/common v0.53.1-0.20230608150349-2c1849f43e14 h1:THwcUhmyEiq/W7S0eUtGLcm6EB8ih1iQpd7OCV4xuT8=
github.com/containers/common v0.53.1-0.20230506101404-3e93a76d461c/go.mod h1:vAG2WNLK9d4umy56l413SS9xiJVe5m7LwOUSoi1x10k= github.com/containers/common v0.53.1-0.20230608150349-2c1849f43e14/go.mod h1:xBDye1c2T/Ms2zGhMeamNi6u158M3FbRLEsWdAwmSkk=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= 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 v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.25.1-0.20230505072505-dc4a4be9cc1e h1:9rH8hFLJjmwMkNAdFfXP3O6cAODKujsTn8JurumYz6I= github.com/containers/image/v5 v5.25.1-0.20230608153337-8ad019310ff2 h1:Fh+hVnBC+/oCVACYwBttfNz0ZEiTaXbempEJPc0CkM4=
github.com/containers/image/v5 v5.25.1-0.20230505072505-dc4a4be9cc1e/go.mod h1:fGnQk2T+xmEk1/yL9Ky6djJ2F86vBIeo6X14zZQ33iM= github.com/containers/image/v5 v5.25.1-0.20230608153337-8ad019310ff2/go.mod h1:lbnQxsf2S4lhn6fiBH2ucjiQu5kfBuGkGCif+AICyx0=
github.com/containers/libhvee v0.0.5 h1:5tUiF2eVe8XbVSPD/Os4dIU1gJWoQgtkQHIjQ5X7wpE= github.com/containers/libhvee v0.0.5 h1:5tUiF2eVe8XbVSPD/Os4dIU1gJWoQgtkQHIjQ5X7wpE=
github.com/containers/libhvee v0.0.5/go.mod h1:AYsyMe44w9ylWWEZNW+IOzA7oZ2i/P9TChNljavhYMI= github.com/containers/libhvee v0.0.5/go.mod h1:AYsyMe44w9ylWWEZNW+IOzA7oZ2i/P9TChNljavhYMI=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
@ -258,15 +257,15 @@ github.com/containers/ocicrypt v1.1.7/go.mod h1:7CAhjcj2H8AYp5YvEie7oVSK2AhBY8Ns
github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY= github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY=
github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc= 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.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s=
github.com/containers/storage v1.46.1 h1:GcAe8J0Y6T2CF70fXPojUpnme6zXamuzGCrNujVtIGE= github.com/containers/storage v1.46.2-0.20230530174214-1dc289a244ce h1:who8o0q9CLMCOs8DunR66IfWno2eLwgNH8u7JsJP69A=
github.com/containers/storage v1.46.1/go.mod h1:81vNDX4h+nXJ2o0D6Yqy6JGXDYJGVpHZpz0nr09iJuQ= github.com/containers/storage v1.46.2-0.20230530174214-1dc289a244ce/go.mod h1:ke6qnPYu0t2bUfYvBSWI7R8dNitNsS97t3z3hveOINY=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 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/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-oidc/v3 v3.5.0 h1:VxKtbccHZxs8juq7RdJntSqtXFtde9YpNpGn0yqgEHw= github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o=
github.com/coreos/go-oidc/v3 v3.5.0/go.mod h1:ecXRtV4romGPeO6ieExAsUK9cb/3fp9hXNz1tlv8PIM= github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
@ -291,8 +290,8 @@ github.com/crc-org/vfkit v0.0.5-0.20230602131541-3d57f09010c9/go.mod h1:sluZ7Q1Z
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 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.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 h1:vU+EP9ZuFUCYE0NYLwTSob+3LNEJATzNfP/DC7SWGWI= github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1 h1:8Pq5UNTC+/UfvcOPKQGZoKCkeF+ZaKa4wJ9OS2gsQQM=
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= github.com/cyberphone/json-canonicalization v0.0.0-20230514072755-504adb8a8af1/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
@ -320,8 +319,8 @@ github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= 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.2+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 v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.0+incompatible h1:z4bf8HvONXX9Tde5lGBMQ7yCJgNahmJumdrStZAbeY4= github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg=
github.com/docker/docker v24.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.2+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.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 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
@ -356,7 +355,6 @@ github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yi
github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 h1:IeaD1VDVBPlx3viJT9Md8if8IxxJnO+x0JCGb054heg= github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 h1:IeaD1VDVBPlx3viJT9Md8if8IxxJnO+x0JCGb054heg=
github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 h1:a4DFiKFJiDRGFD1qIcqGLX/WlUMD9dyLSLDt+9QZgt8= github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 h1:a4DFiKFJiDRGFD1qIcqGLX/WlUMD9dyLSLDt+9QZgt8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
@ -436,7 +434,7 @@ github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
github.com/go-rod/rod v0.112.9 h1:uA/yLbB+t0UlqJcLJtK2pZrCNPzd15dOKRUEOnmnt9k= github.com/go-rod/rod v0.113.1 h1:+Qb4K/vkR7BOhW6FhfhtLzUD3l11+0XlF4do+27sOQk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
@ -530,12 +528,11 @@ 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.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.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.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 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.5.9/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.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
github.com/google/go-containerregistry v0.14.0 h1:z58vMqHxuwvAsVwvKEkmVBz2TlgBgH5k6koEXBtlYkw= github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMdlgB8eXiiYOY55gfN91Wk= github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM= github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM=
github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y= github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -555,8 +552,6 @@ github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHa
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/trillian v1.5.1 h1:2p1l13f0eWd7eOShwarwIxutYYnGzY/5S+xYewQIPkU=
github.com/google/trillian v1.5.1/go.mod h1:EcDttN8nf+EoAiyLigBAp9ebncZI6rhJPyxZ+dQ6HSo=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -592,14 +587,14 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA=
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@ -613,8 +608,8 @@ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
@ -687,9 +682,7 @@ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsI
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 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 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@ -707,8 +700,9 @@ github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mistifyio/go-zfs/v3 v3.0.0 h1:J5QK618xRcXnQYZ2GE5FdmpS1ufIrWue+lR/mpe6/14=
github.com/mistifyio/go-zfs/v3 v3.0.0/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k= github.com/mistifyio/go-zfs/v3 v3.0.0/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@ -763,8 +757,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.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 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.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs=
github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 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 v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@ -840,7 +834,7 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 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.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.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 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.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@ -887,10 +881,10 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 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 h1:0ntW9VbQbt2JytoSs8BOGB84A65eeyvGSavWteYp29Y=
github.com/sigstore/fulcio v1.3.1/go.mod h1:/XfqazOec45ulJZpyL9sq+OsVQ8g2UOVoNVi7abFgqU= github.com/sigstore/fulcio v1.3.1/go.mod h1:/XfqazOec45ulJZpyL9sq+OsVQ8g2UOVoNVi7abFgqU=
github.com/sigstore/rekor v1.1.2-0.20230508234306-ad288b385a44 h1:03iBveStHVfP97eB54lMjkgrSMYWW7F7X9IlOI9N+A0= github.com/sigstore/rekor v1.2.2-0.20230601122533-4c81ff246d12 h1:x/WnxasgR40qGY67IHwioakXLuhDxJ10vF8/INuOTiI=
github.com/sigstore/rekor v1.1.2-0.20230508234306-ad288b385a44/go.mod h1:4/htUXiP2z4KwvZOXTalCkh5C9I7msJbVWrdjWyD+fU= github.com/sigstore/rekor v1.2.2-0.20230601122533-4c81ff246d12/go.mod h1:8c+a8Yo7r8gKuYbIaz+c3oOdw9iMXx+tMdOg2+b+2jQ=
github.com/sigstore/sigstore v1.6.4 h1:jH4AzR7qlEH/EWzm+opSpxCfuUcjHL+LJPuQE7h40WE= github.com/sigstore/sigstore v1.6.5 h1:/liHIo7YPJp6sN31DzBYDOuRPmN1xbzROMBE5DLllYM=
github.com/sigstore/sigstore v1.6.4/go.mod h1:pjR64lBxnjoSrAr+Ydye/FV73IfrgtoYlAI11a8xMfA= github.com/sigstore/sigstore v1.6.5/go.mod h1:h+EoQsf9+6UKgNYxKhBcPgo4PZeEVfzAJxKRRIYhyN4=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= 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.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -946,8 +940,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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 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/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/sylabs/sif/v2 v2.11.3 h1:EQxi5zl6i5DsbVal9HHpk/zuSx7aNLeZBy8vmvFz838= github.com/sylabs/sif/v2 v2.11.4 h1:4dRvsRFVkyS7e8oD8AEL0HrJocnet05+EFW+DhVb/Ic=
github.com/sylabs/sif/v2 v2.11.3/go.mod h1:0ryivqvvsncJOJjU5QQIEc77a5zKK46F+urBXMdA07w= github.com/sylabs/sif/v2 v2.11.4/go.mod h1:83kqbKZFRFfFLe1ui5BH+rAxF2obICM/i3zto4ivM7s=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= 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-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
@ -1008,14 +1002,14 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/ysmood/fetchup v0.2.2 h1:Qn8/q5uDW7szclt4sVXCFJ1TXup3hogz94OaLf6kloo= github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ= github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
github.com/ysmood/got v0.34.1 h1:IrV2uWLs45VXNvZqhJ6g2nIhY+pgIG1CUoOcqfXFl1s=
github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=
github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak= github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
@ -1067,11 +1061,10 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-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-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.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1082,8 +1075,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-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-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-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 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/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= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -1105,7 +1098,6 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.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.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1151,9 +1143,6 @@ golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-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.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1161,9 +1150,8 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/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-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1176,7 +1164,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1259,17 +1246,13 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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-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-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1281,7 +1264,6 @@ 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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1340,9 +1322,8 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1509,11 +1490,9 @@ k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=

View File

@ -50,6 +50,7 @@ type NetworkCreateOptions struct {
NetworkDNSServers []string NetworkDNSServers []string
Ranges []string Ranges []string
Subnets []string Subnets []string
Routes []string
IPv6 bool IPv6 bool
// Mapping of driver options and values. // Mapping of driver options and values.
Options map[string]string Options map[string]string

View File

@ -277,6 +277,7 @@ ln -s vendor src
LDFLAGS="-X %{import_path}/libpod/define.buildInfo=$(date +%s)" LDFLAGS="-X %{import_path}/libpod/define.buildInfo=$(date +%s)"
# build rootlessport first # build rootlessport first
export BUILDTAGS="exclude_graphdriver_aufs exclude_graphdriver_btrfs exclude_graphdriver_devicemapper exclude_graphdriver_overlay exclude_graphdriver_zfs"
%gobuild -o bin/rootlessport %{import_path}/cmd/rootlessport %gobuild -o bin/rootlessport %{import_path}/cmd/rootlessport
export BASEBUILDTAGS="seccomp exclude_graphdriver_devicemapper $(hack/systemd_tag.sh) $(hack/libsubid_tag.sh)" export BASEBUILDTAGS="seccomp exclude_graphdriver_devicemapper $(hack/systemd_tag.sh) $(hack/libsubid_tag.sh)"

View File

@ -62,6 +62,215 @@ var _ = Describe("Podman network create", func() {
Expect(subnet.Contains(containerIP)).To(BeTrue(), "subnet contains containerIP") Expect(subnet.Contains(containerIP)).To(BeTrue(), "subnet contains containerIP")
}) })
It("podman network create with name and subnet and static route", func() {
SkipIfCNI(podmanTest)
netName := "subnet-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{
"network",
"create",
"--subnet",
"10.19.12.0/24",
"--route",
"10.21.0.0/24,10.19.12.250",
netName,
})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
// JSON the network configuration into something usable
var results []types.Network
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(HaveLen(1))
result := results[0]
Expect(result).To(HaveField("Name", netName))
Expect(result.Subnets).To(HaveLen(1))
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.12.0/24"))
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.12.1"))
Expect(result.Routes[0].Destination.String()).To(Equal("10.21.0.0/24"))
Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.12.250"))
Expect(result.Routes[0].Metric).To(BeNil())
// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
defer removeNetworkDevice(result.NetworkInterface)
})
It("podman network create with name and subnet and static route and metric", func() {
SkipIfCNI(podmanTest)
netName := "subnet-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{
"network",
"create",
"--subnet",
"10.19.13.0/24",
"--route",
"10.21.1.0/24,10.19.13.250,120",
netName,
})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
// JSON the network configuration into something usable
var results []types.Network
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(HaveLen(1))
result := results[0]
Expect(result).To(HaveField("Name", netName))
Expect(result.Subnets).To(HaveLen(1))
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.13.0/24"))
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.13.1"))
Expect(result.Routes[0].Destination.String()).To(Equal("10.21.1.0/24"))
Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.13.250"))
Expect(*result.Routes[0].Metric).To(Equal(uint32(120)))
// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
defer removeNetworkDevice(result.NetworkInterface)
})
It("podman network create with name and subnet and two static routes", func() {
SkipIfCNI(podmanTest)
netName := "subnet-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{
"network",
"create",
"--subnet",
"10.19.14.0/24",
"--route",
"10.21.2.0/24,10.19.14.250",
"--route",
"10.21.3.0/24,10.19.14.251,120",
netName,
})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
// JSON the network configuration into something usable
var results []types.Network
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(HaveLen(1))
result := results[0]
Expect(result).To(HaveField("Name", netName))
Expect(result.Subnets).To(HaveLen(1))
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.14.0/24"))
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.14.1"))
Expect(result.Routes).To(HaveLen(2))
Expect(result.Routes[0].Destination.String()).To(Equal("10.21.2.0/24"))
Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.14.250"))
Expect(result.Routes[0].Metric).To(BeNil())
Expect(result.Routes[1].Destination.String()).To(Equal("10.21.3.0/24"))
Expect(result.Routes[1].Gateway.String()).To(Equal("10.19.14.251"))
Expect(*result.Routes[1].Metric).To(Equal(uint32(120)))
// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
defer removeNetworkDevice(result.NetworkInterface)
})
It("podman network create with name and subnet and static route (ipv6)", func() {
SkipIfCNI(podmanTest)
netName := "subnet-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{
"network",
"create",
"--subnet",
"fd:ab04::/64",
"--route",
"fd:1::/64,fd::1,120",
netName,
})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
// JSON the network configuration into something usable
var results []types.Network
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(HaveLen(1))
result := results[0]
Expect(result).To(HaveField("Name", netName))
Expect(result.Subnets).To(HaveLen(1))
Expect(result.Subnets[0].Subnet.String()).To(Equal("fd:ab04::/64"))
Expect(result.Subnets[0].Gateway.String()).To(Equal("fd:ab04::1"))
Expect(result.Routes[0].Destination.String()).To(Equal("fd:1::/64"))
Expect(result.Routes[0].Gateway.String()).To(Equal("fd::1"))
Expect(*result.Routes[0].Metric).To(Equal(uint32(120)))
// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
defer removeNetworkDevice(result.NetworkInterface)
})
It("podman network create with name and subnet with --opt no_default_route=1", func() {
SkipIfCNI(podmanTest)
netName := "subnet-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{
"network",
"create",
"--subnet",
"10.19.15.0/24",
"--opt",
"no_default_route=1",
netName,
})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
Expect(nc).Should(Exit(0))
// Inspect the network configuration
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
// JSON the network configuration into something usable
var results []types.Network
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
Expect(err).ToNot(HaveOccurred())
Expect(results).To(HaveLen(1))
result := results[0]
Expect(result).To(HaveField("Name", netName))
Expect(result.Subnets).To(HaveLen(1))
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.15.0/24"))
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.15.1"))
Expect(result.Options[types.NoDefaultRoute]).To(Equal("true"))
// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
defer removeNetworkDevice(result.NetworkInterface)
})
It("podman network create with name and IPv6 subnet", func() { It("podman network create with name and IPv6 subnet", func() {
netName := "ipv6-" + stringid.GenerateRandomID() netName := "ipv6-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName}) nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName})

View File

@ -43,7 +43,9 @@ setup() {
fi fi
# cgroup-manager=systemd does not work inside a container # cgroup-manager=systemd does not work inside a container
export _PODMAN_TEST_OPTS="--cgroup-manager=cgroupfs --root=$PODMAN_UPGRADE_WORKDIR/root --runroot=$PODMAN_UPGRADE_WORKDIR/runroot --tmpdir=$PODMAN_UPGRADE_WORKDIR/tmp" # skip_mount_home=true is required so we can share the storage mounts between host and container,
# the default c/storage behavior is to make the mount propagation private.
export _PODMAN_TEST_OPTS="--storage-opt=skip_mount_home=true --cgroup-manager=cgroupfs --root=$PODMAN_UPGRADE_WORKDIR/root --runroot=$PODMAN_UPGRADE_WORKDIR/runroot --tmpdir=$PODMAN_UPGRADE_WORKDIR/tmp"
} }
############################################################################### ###############################################################################
@ -180,7 +182,7 @@ EOF
-v /var/lib/cni:/var/lib/cni \ -v /var/lib/cni:/var/lib/cni \
-v /etc/cni/net.d:/etc/cni/net.d \ -v /etc/cni/net.d:/etc/cni/net.d \
-v /dev/shm:/dev/shm \ -v /dev/shm:/dev/shm \
-v $pmroot:$pmroot \ -v $pmroot:$pmroot:rshared \
$OLD_PODMAN $pmroot/setup $OLD_PODMAN $pmroot/setup
_PODMAN_TEST_OPTS= wait_for_ready podman_parent _PODMAN_TEST_OPTS= wait_for_ready podman_parent

41
vendor/github.com/Azure/go-ansiterm/SECURITY.md generated vendored Normal file
View File

@ -0,0 +1,41 @@
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.8 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->

View File

@ -94,23 +94,9 @@ out/delta.tar.gz: bin/init bin/vsockexec bin/cmd/gcs bin/cmd/gcstools bin/cmd/ho
tar -zcf $@ -C rootfs . tar -zcf $@ -C rootfs .
rm -rf rootfs rm -rf rootfs
-include deps/cmd/gcs.gomake bin/cmd/gcs bin/cmd/gcstools bin/cmd/hooks/wait-paths bin/cmd/tar2ext4 bin/internal/tools/snp-report:
-include deps/cmd/gcstools.gomake
-include deps/cmd/hooks/wait-paths.gomake
-include deps/cmd/tar2ext4.gomake
-include deps/internal/tools/snp-report.gomake
# Implicit rule for includes that define Go targets.
%.gomake: $(SRCROOT)/Makefile
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
@/bin/echo $(@:deps/%.gomake=bin/%): $(SRCROOT)/hack/gomakedeps.sh > $@.new GOOS=linux $(GO_BUILD) -o $@ $(SRCROOT)/$(@:bin/%=%)
@/bin/echo -e '\t@mkdir -p $$(dir $$@) $(dir $@)' >> $@.new
@/bin/echo -e '\t$$(GO_BUILD) -o $$@.new $$(SRCROOT)/$$(@:bin/%=%)' >> $@.new
@/bin/echo -e '\tGO="$(GO)" $$(SRCROOT)/hack/gomakedeps.sh $$@ $$(SRCROOT)/$$(@:bin/%=%) $$(GO_FLAGS) $$(GO_FLAGS_EXTRA) > $(@:%.gomake=%.godeps).new' >> $@.new
@/bin/echo -e '\tmv $(@:%.gomake=%.godeps).new $(@:%.gomake=%.godeps)' >> $@.new
@/bin/echo -e '\tmv $$@.new $$@' >> $@.new
@/bin/echo -e '-include $(@:%.gomake=%.godeps)' >> $@.new
mv $@.new $@
bin/vsockexec: vsockexec/vsockexec.o vsockexec/vsock.o bin/vsockexec: vsockexec/vsockexec.o vsockexec/vsock.o
@mkdir -p bin @mkdir -p bin

View File

@ -0,0 +1,85 @@
package log
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net"
"reflect"
"time"
"github.com/containerd/containerd/log"
)
const TimeFormat = log.RFC3339NanoFixed
func FormatTime(t time.Time) string {
return t.Format(TimeFormat)
}
// DurationFormat formats a [time.Duration] log entry.
//
// A nil value signals an error with the formatting.
type DurationFormat func(time.Duration) interface{}
func DurationFormatString(d time.Duration) interface{} { return d.String() }
func DurationFormatSeconds(d time.Duration) interface{} { return d.Seconds() }
func DurationFormatMilliseconds(d time.Duration) interface{} { return d.Milliseconds() }
// FormatIO formats net.Conn and other types that have an `Addr()` or `Name()`.
//
// See FormatEnabled for more information.
func FormatIO(ctx context.Context, v interface{}) string {
m := make(map[string]string)
m["type"] = reflect.TypeOf(v).String()
switch t := v.(type) {
case net.Conn:
m["localAddress"] = formatAddr(t.LocalAddr())
m["remoteAddress"] = formatAddr(t.RemoteAddr())
case interface{ Addr() net.Addr }:
m["address"] = formatAddr(t.Addr())
default:
return Format(ctx, t)
}
return Format(ctx, m)
}
func formatAddr(a net.Addr) string {
return a.Network() + "://" + a.String()
}
// Format formats an object into a JSON string, without any indendtation or
// HTML escapes.
// Context is used to output a log waring if the conversion fails.
//
// This is intended primarily for `trace.StringAttribute()`
func Format(ctx context.Context, v interface{}) string {
b, err := encode(v)
if err != nil {
G(ctx).WithError(err).Warning("could not format value")
return ""
}
return string(b)
}
func encode(v interface{}) ([]byte, error) {
return encodeBuffer(&bytes.Buffer{}, v)
}
func encodeBuffer(buf *bytes.Buffer, v interface{}) ([]byte, error) {
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
enc.SetIndent("", "")
if err := enc.Encode(v); err != nil {
err = fmt.Errorf("could not marshall %T to JSON for logging: %w", v, err)
return nil, err
}
// encoder.Encode appends a newline to the end
return bytes.TrimSpace(buf.Bytes()), nil
}

View File

@ -1,23 +1,58 @@
package log package log
import ( import (
"bytes"
"reflect"
"time"
"github.com/Microsoft/hcsshim/internal/logfields" "github.com/Microsoft/hcsshim/internal/logfields"
"github.com/containerd/containerd/log"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/trace" "go.opencensus.io/trace"
) )
// Hook serves to intercept and format `logrus.Entry`s before they are passed const nullString = "null"
// to the ETW hook.
// Hook intercepts and formats a [logrus.Entry] before it logged.
// //
// The containerd shim discards the (formatted) logrus output, and outputs only via ETW. // The shim either outputs the logs through an ETW hook, discarding the (formatted) output
// The Linux GCS outputs logrus entries over stdout, which is consumed by the shim and // or logs output to a pipe for logging binaries to consume.
// then re-output via the ETW hook. // The Linux GCS outputs logrus entries over stdout, which is then consumed and re-output
type Hook struct{} // by the shim.
type Hook struct {
// EncodeAsJSON formats structs, maps, arrays, slices, and [bytes.Buffer] as JSON.
// Variables of [bytes.Buffer] will be converted to []byte.
//
// Default is false.
EncodeAsJSON bool
// FormatTime specifies the format for [time.Time] variables.
// An empty string disables formatting.
// When disabled, the fall back will the JSON encoding, if enabled.
//
// Default is [github.com/containerd/containerd/log.RFC3339NanoFixed].
TimeFormat string
// Duration format converts a [time.Duration] fields to an appropriate encoding.
// nil disables formatting.
// When disabled, the fall back will the JSON encoding, if enabled.
//
// Default is [DurationFormatString], which appends a duration unit after the value.
DurationFormat DurationFormat
// AddSpanContext adds [logfields.TraceID] and [logfields.SpanID] fields to
// the entry from the span context stored in [logrus.Entry.Context], if it exists.
AddSpanContext bool
}
var _ logrus.Hook = &Hook{} var _ logrus.Hook = &Hook{}
func NewHook() *Hook { func NewHook() *Hook {
return &Hook{} return &Hook{
TimeFormat: log.RFC3339NanoFixed,
DurationFormat: DurationFormatString,
AddSpanContext: true,
}
} }
func (h *Hook) Levels() []logrus.Level { func (h *Hook) Levels() []logrus.Level {
@ -25,14 +60,108 @@ func (h *Hook) Levels() []logrus.Level {
} }
func (h *Hook) Fire(e *logrus.Entry) (err error) { func (h *Hook) Fire(e *logrus.Entry) (err error) {
// JSON encode, if necessary, then add span information
h.encode(e)
h.addSpanContext(e) h.addSpanContext(e)
return nil return nil
} }
// encode loops through all the fields in the [logrus.Entry] and encodes them according to
// the settings in [Hook].
// If [Hook.TimeFormat] is non-empty, it will be passed to [time.Time.Format] for
// fields of type [time.Time].
//
// If [Hook.EncodeAsJSON] is true, then fields that are not numeric, boolean, strings, or
// errors will be encoded via a [json.Marshal] (with HTML escaping disabled).
// Chanel- and function-typed fields, as well as unsafe pointers are left alone and not encoded.
//
// If [Hook.TimeFormat] and [Hook.DurationFormat] are empty and [Hook.EncodeAsJSON] is false,
// then this is a no-op.
func (h *Hook) encode(e *logrus.Entry) {
d := e.Data
formatTime := h.TimeFormat != ""
formatDuration := h.DurationFormat != nil
if !(h.EncodeAsJSON || formatTime || formatDuration) {
return
}
for k, v := range d {
// encode types with dedicated formatting options first
if vv, ok := v.(time.Time); formatTime && ok {
d[k] = vv.Format(h.TimeFormat)
continue
}
if vv, ok := v.(time.Duration); formatDuration && ok {
d[k] = h.DurationFormat(vv)
continue
}
// general case JSON encoding
if !h.EncodeAsJSON {
continue
}
switch vv := v.(type) {
// built in types
// "json" marshals errors as "{}", so leave alone here
case bool, string, error, uintptr,
int8, int16, int32, int64, int,
uint8, uint32, uint64, uint,
float32, float64:
continue
// Rather than setting d[k] = vv.String(), JSON encode []byte value, since it
// may be a binary payload and not representable as a string.
// `case bytes.Buffer,*bytes.Buffer:` resolves `vv` to `interface{}`,
// so cannot use `vv.Bytes`.
// Could move to below the `reflect.Indirect()` call below, but
// that would require additional typematching and dereferencing.
// Easier to keep these duplicate branches here.
case bytes.Buffer:
v = vv.Bytes()
case *bytes.Buffer:
v = vv.Bytes()
}
// dereference pointer or interface variables
rv := reflect.Indirect(reflect.ValueOf(v))
// check if `v` is a null pointer
if !rv.IsValid() {
d[k] = nullString
continue
}
switch rv.Kind() {
case reflect.Map, reflect.Struct, reflect.Array, reflect.Slice:
default:
// Bool, [U]?Int*, Float*, Complex*, Uintptr, String: encoded as normal
// Chan, Func: not supported by json
// Interface, Pointer: dereferenced above
// UnsafePointer: not supported by json, not safe to de-reference; leave alone
continue
}
b, err := encode(v)
if err != nil {
// Errors are written to stderr (ie, to `panic.log`) and stops the remaining
// hooks (ie, exporting to ETW) from firing. So add encoding errors to
// the entry data to be written out, but keep on processing.
d[k+"-"+logrus.ErrorKey] = err.Error()
// keep the original `v` as the value,
continue
}
d[k] = string(b)
}
}
func (h *Hook) addSpanContext(e *logrus.Entry) { func (h *Hook) addSpanContext(e *logrus.Entry) {
ctx := e.Context ctx := e.Context
if ctx == nil { if !h.AddSpanContext || ctx == nil {
return return
} }
span := trace.FromContext(ctx) span := trace.FromContext(ctx)

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"strings"
"sync/atomic" "sync/atomic"
hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
@ -56,11 +55,11 @@ func ScrubProcessParameters(s string) (string, error) {
} }
pp.Environment = map[string]string{_scrubbedReplacement: _scrubbedReplacement} pp.Environment = map[string]string{_scrubbedReplacement: _scrubbedReplacement}
buf := bytes.NewBuffer(b[:0]) b, err := encodeBuffer(bytes.NewBuffer(b[:0]), pp)
if err := encode(buf, pp); err != nil { if err != nil {
return "", err return "", err
} }
return strings.TrimSpace(buf.String()), nil return string(b), nil
} }
// ScrubBridgeCreate scrubs requests sent over the bridge of type // ScrubBridgeCreate scrubs requests sent over the bridge of type
@ -150,21 +149,12 @@ func scrubBytes(b []byte, scrub scrubberFunc) ([]byte, error) {
return nil, err return nil, err
} }
buf := &bytes.Buffer{} b, err := encode(m)
if err := encode(buf, m); err != nil { if err != nil {
return nil, err return nil, err
} }
return bytes.TrimSpace(buf.Bytes()), nil return b, nil
}
func encode(buf *bytes.Buffer, v interface{}) error {
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
if err := enc.Encode(v); err != nil {
return err
}
return nil
} }
func isRequestBase(m genMap) bool { func isRequestBase(m genMap) bool {

View File

@ -0,0 +1,69 @@
package oc
import (
"errors"
"io"
"net"
"os"
"github.com/containerd/containerd/errdefs"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// todo: break import cycle with "internal/hcs/errors.go" and reference errors defined there
// todo: add errors defined in "internal/guest/gcserror" (Hresult does not implement error)
func toStatusCode(err error) codes.Code {
// checks if err implements GRPCStatus() *"google.golang.org/grpc/status".Status,
// wraps an error defined in "github.com/containerd/containerd/errdefs", or is a
// context timeout or cancelled error
if s, ok := status.FromError(errdefs.ToGRPC(err)); ok {
return s.Code()
}
switch {
// case isAny(err):
// return codes.Cancelled
case isAny(err, os.ErrInvalid):
return codes.InvalidArgument
case isAny(err, os.ErrDeadlineExceeded):
return codes.DeadlineExceeded
case isAny(err, os.ErrNotExist):
return codes.NotFound
case isAny(err, os.ErrExist):
return codes.AlreadyExists
case isAny(err, os.ErrPermission):
return codes.PermissionDenied
// case isAny(err):
// return codes.ResourceExhausted
case isAny(err, os.ErrClosed, net.ErrClosed, io.ErrClosedPipe, io.ErrShortBuffer):
return codes.FailedPrecondition
// case isAny(err):
// return codes.Aborted
// case isAny(err):
// return codes.OutOfRange
// case isAny(err):
// return codes.Unimplemented
case isAny(err, io.ErrNoProgress):
return codes.Internal
// case isAny(err):
// return codes.Unavailable
case isAny(err, io.ErrShortWrite, io.ErrUnexpectedEOF):
return codes.DataLoss
// case isAny(err):
// return codes.Unauthenticated
default:
return codes.Unknown
}
}
// isAny returns true if errors.Is is true for any of the provided errors, errs.
func isAny(err error, errs ...error) bool {
for _, e := range errs {
if errors.Is(err, e) {
return true
}
}
return false
}

View File

@ -3,19 +3,26 @@ package oc
import ( import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/trace" "go.opencensus.io/trace"
"google.golang.org/grpc/codes"
"github.com/Microsoft/hcsshim/internal/log"
"github.com/Microsoft/hcsshim/internal/logfields"
) )
var _ = (trace.Exporter)(&LogrusExporter{}) const spanMessage = "Span"
var _errorCodeKey = logrus.ErrorKey + "Code"
// LogrusExporter is an OpenCensus `trace.Exporter` that exports // LogrusExporter is an OpenCensus `trace.Exporter` that exports
// `trace.SpanData` to logrus output. // `trace.SpanData` to logrus output.
type LogrusExporter struct { type LogrusExporter struct{}
}
var _ trace.Exporter = &LogrusExporter{}
// ExportSpan exports `s` based on the the following rules: // ExportSpan exports `s` based on the the following rules:
// //
// 1. All output will contain `s.Attributes`, `s.TraceID`, `s.SpanID`, // 1. All output will contain `s.Attributes`, `s.SpanKind`, `s.TraceID`,
// `s.ParentSpanID` for correlation // `s.SpanID`, and `s.ParentSpanID` for correlation
// //
// 2. Any calls to .Annotate will not be supported. // 2. Any calls to .Annotate will not be supported.
// //
@ -23,21 +30,57 @@ type LogrusExporter struct {
// `s.Status.Code != 0` in which case it will be written at `logrus.ErrorLevel` // `s.Status.Code != 0` in which case it will be written at `logrus.ErrorLevel`
// providing `s.Status.Message` as the error value. // providing `s.Status.Message` as the error value.
func (le *LogrusExporter) ExportSpan(s *trace.SpanData) { func (le *LogrusExporter) ExportSpan(s *trace.SpanData) {
// Combine all span annotations with traceID, spanID, parentSpanID if s.DroppedAnnotationCount > 0 {
baseEntry := logrus.WithFields(logrus.Fields(s.Attributes)) logrus.WithFields(logrus.Fields{
baseEntry.Data["traceID"] = s.TraceID.String() "name": s.Name,
baseEntry.Data["spanID"] = s.SpanID.String() logfields.TraceID: s.TraceID.String(),
baseEntry.Data["parentSpanID"] = s.ParentSpanID.String() logfields.SpanID: s.SpanID.String(),
baseEntry.Data["startTime"] = s.StartTime "dropped": s.DroppedAttributeCount,
baseEntry.Data["endTime"] = s.EndTime "maxAttributes": len(s.Attributes),
baseEntry.Data["duration"] = s.EndTime.Sub(s.StartTime).String() }).Warning("span had dropped attributes")
baseEntry.Data["name"] = s.Name }
baseEntry.Time = s.StartTime
entry := log.L.Dup()
// Combine all span annotations with span data (eg, trace ID, span ID, parent span ID,
// error, status code)
// (OC) Span attributes are guaranteed to be strings, bools, or int64s, so we can
// can skip overhead in entry.WithFields() and add them directly to entry.Data.
// Preallocate ahead of time, since we should add, at most, 10 additional entries
data := make(logrus.Fields, len(entry.Data)+len(s.Attributes)+10)
// Default log entry may have prexisting/application-wide data
for k, v := range entry.Data {
data[k] = v
}
for k, v := range s.Attributes {
data[k] = v
}
data[logfields.Name] = s.Name
data[logfields.TraceID] = s.TraceID.String()
data[logfields.SpanID] = s.SpanID.String()
data[logfields.ParentSpanID] = s.ParentSpanID.String()
data[logfields.StartTime] = s.StartTime
data[logfields.EndTime] = s.EndTime
data[logfields.Duration] = s.EndTime.Sub(s.StartTime)
if sk := spanKindToString(s.SpanKind); sk != "" {
data["spanKind"] = sk
}
level := logrus.InfoLevel level := logrus.InfoLevel
if s.Status.Code != 0 { if s.Status.Code != 0 {
level = logrus.ErrorLevel level = logrus.ErrorLevel
baseEntry.Data[logrus.ErrorKey] = s.Status.Message
// don't overwrite an existing "error" or "errorCode" attributes
if _, ok := data[logrus.ErrorKey]; !ok {
data[logrus.ErrorKey] = s.Status.Message
} }
baseEntry.Log(level, "Span") if _, ok := data[_errorCodeKey]; !ok {
data[_errorCodeKey] = codes.Code(s.Status.Code).String()
}
}
entry.Data = data
entry.Time = s.StartTime
entry.Log(level, spanMessage)
} }

View File

@ -14,8 +14,7 @@ var DefaultSampler = trace.AlwaysSample()
func SetSpanStatus(span *trace.Span, err error) { func SetSpanStatus(span *trace.Span, err error) {
status := trace.Status{} status := trace.Status{}
if err != nil { if err != nil {
// TODO: JTERRY75 - Handle errors in a non-generic way status.Code = int32(toStatusCode(err))
status.Code = trace.StatusCodeUnknown
status.Message = err.Error() status.Message = err.Error()
} }
span.SetStatus(status) span.SetStatus(status)
@ -46,3 +45,14 @@ func update(ctx context.Context, s *trace.Span) (context.Context, *trace.Span) {
var WithServerSpanKind = trace.WithSpanKind(trace.SpanKindServer) var WithServerSpanKind = trace.WithSpanKind(trace.SpanKindServer)
var WithClientSpanKind = trace.WithSpanKind(trace.SpanKindClient) var WithClientSpanKind = trace.WithSpanKind(trace.SpanKindClient)
func spanKindToString(sk int) string {
switch sk {
case trace.SpanKindClient:
return "client"
case trace.SpanKindServer:
return "server"
default:
return ""
}
}

View File

@ -23,20 +23,14 @@ type (
) )
type explicitAccess struct { type explicitAccess struct {
//nolint:structcheck
accessPermissions accessMask accessPermissions accessMask
//nolint:structcheck
accessMode accessMode accessMode accessMode
//nolint:structcheck
inheritance inheritMode inheritance inheritMode
//nolint:structcheck
trustee trustee trustee trustee
} }
type trustee struct { type trustee struct {
//nolint:unused,structcheck
multipleTrustee *trustee multipleTrustee *trustee
//nolint:unused,structcheck
multipleTrusteeOperation int32 multipleTrusteeOperation int32
trusteeForm trusteeForm trusteeForm trusteeForm
trusteeType trusteeType trusteeType trusteeType

View File

@ -17,6 +17,7 @@ import (
"github.com/containernetworking/cni/libcni" "github.com/containernetworking/cni/libcni"
"github.com/containers/common/libnetwork/types" "github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
cutil "github.com/containers/common/pkg/util"
"github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/lockfile"
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -295,6 +296,43 @@ func (n *cniNetwork) DefaultInterfaceName() string {
return cniDeviceName return cniDeviceName
} }
// NetworkInfo return the network information about binary path,
// package version and program version.
func (n *cniNetwork) NetworkInfo() types.NetworkInfo {
path := ""
packageVersion := ""
for _, p := range n.cniPluginDirs {
ver := cutil.PackageVersion(p)
if ver != cutil.UnknownPackage {
path = p
packageVersion = ver
break
}
}
info := types.NetworkInfo{
Backend: types.CNI,
Package: packageVersion,
Path: path,
}
dnsPath := filepath.Join(path, "dnsname")
dnsPackage := cutil.PackageVersion(dnsPath)
dnsProgram, err := cutil.ProgramVersionDnsname(dnsPath)
if err != nil {
logrus.Infof("Failed to get the dnsname plugin version: %v", err)
}
if _, err := os.Stat(dnsPath); err == nil {
info.DNS = types.DNSNetworkInfo{
Path: dnsPath,
Package: dnsPackage,
Version: dnsProgram,
}
}
return info
}
func (n *cniNetwork) Network(nameOrID string) (*types.Network, error) { func (n *cniNetwork) Network(nameOrID string) (*types.Network, error) {
network, err := n.getNetwork(nameOrID) network, err := n.getNetwork(nameOrID)
if err != nil { if err != nil {

View File

@ -81,6 +81,43 @@ func ValidateSubnets(network *types.Network, addGateway bool, usedNetworks []*ne
return nil return nil
} }
func ValidateRoutes(routes []types.Route) error {
for _, route := range routes {
err := ValidateRoute(route)
if err != nil {
return err
}
}
return nil
}
func ValidateRoute(route types.Route) error {
if route.Destination.IP == nil {
return fmt.Errorf("route destination ip nil")
}
if route.Destination.Mask == nil {
return fmt.Errorf("route destination mask nil")
}
if route.Gateway == nil {
return fmt.Errorf("route gateway nil")
}
// Reparse to ensure destination is valid.
ip, ipNet, err := net.ParseCIDR(route.Destination.String())
if err != nil {
return fmt.Errorf("route destination invalid: %w", err)
}
// check that destination is a network and not an address
if !ip.Equal(ipNet.IP) {
return fmt.Errorf("route destination invalid")
}
return nil
}
func ValidateSetupOptions(n NetUtil, namespacePath string, options types.SetupOptions) error { func ValidateSetupOptions(n NetUtil, namespacePath string, options types.SetupOptions) error {
if namespacePath == "" { if namespacePath == "" {
return errors.New("namespacePath is empty") return errors.New("namespacePath is empty")

View File

@ -198,6 +198,13 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo
if err != nil { if err != nil {
return nil, err return nil, err
} }
case types.NoDefaultRoute:
val, err := strconv.ParseBool(value)
if err != nil {
return nil, err
}
// 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)
default: default:
return nil, fmt.Errorf("unsupported bridge network option %s", key) return nil, fmt.Errorf("unsupported bridge network option %s", key)
@ -237,6 +244,12 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo
return nil, err return nil, err
} }
//validate routes
err = internalutil.ValidateRoutes(newNetwork.Routes)
if err != nil {
return nil, err
}
newNetwork.Created = time.Now() newNetwork.Created = time.Now()
if !defaultNet { if !defaultNet {
@ -317,6 +330,24 @@ func createIpvlanOrMacvlan(network *types.Network) error {
if err != nil { if err != nil {
return err return err
} }
case types.NoDefaultRoute:
val, err := strconv.ParseBool(value)
if err != nil {
return err
}
// rust only support "true" or "false" while go can parse 1 and 0 as well so we need to change it
network.Options[types.NoDefaultRoute] = strconv.FormatBool(val)
case types.BclimOption:
if isMacVlan {
_, err := strconv.ParseInt(value, 10, 32)
if err != nil {
return fmt.Errorf("failed to parse %q option: %w", key, err)
}
// do not fallthrough for macvlan
break
}
// bclim is only valid for macvlan not ipvlan so fallthrough to error case
fallthrough
default: default:
return fmt.Errorf("unsupported %s network option %s", driver, key) return fmt.Errorf("unsupported %s network option %s", driver, key)
} }

View File

@ -15,6 +15,7 @@ import (
"github.com/containers/common/libnetwork/internal/util" "github.com/containers/common/libnetwork/internal/util"
"github.com/containers/common/libnetwork/types" "github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
cutil "github.com/containers/common/pkg/util"
"github.com/containers/storage/pkg/lockfile" "github.com/containers/storage/pkg/lockfile"
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -336,6 +337,37 @@ func (n *netavarkNetwork) DefaultInterfaceName() string {
return defaultBridgeName return defaultBridgeName
} }
// NetworkInfo return the network information about binary path,
// package version and program version.
func (n *netavarkNetwork) NetworkInfo() types.NetworkInfo {
path := n.netavarkBinary
packageVersion := cutil.PackageVersion(path)
programVersion, err := cutil.ProgramVersion(path)
if err != nil {
logrus.Infof("Failed to get the netavark version: %v", err)
}
info := types.NetworkInfo{
Backend: types.Netavark,
Version: programVersion,
Package: packageVersion,
Path: path,
}
dnsPath := n.aardvarkBinary
dnsPackage := cutil.PackageVersion(dnsPath)
dnsProgram, err := cutil.ProgramVersion(dnsPath)
if err != nil {
logrus.Infof("Failed to get the aardvark version: %v", err)
}
info.DNS = types.DNSNetworkInfo{
Package: dnsPackage,
Path: dnsPath,
Version: dnsProgram,
}
return info
}
func (n *netavarkNetwork) Network(nameOrID string) (*types.Network, error) { func (n *netavarkNetwork) Network(nameOrID string) (*types.Network, error) {
network, err := n.getNetwork(nameOrID) network, err := n.getNetwork(nameOrID)
if err != nil { if err != nil {

View File

@ -41,6 +41,8 @@ const (
ModeOption = "mode" ModeOption = "mode"
IsolateOption = "isolate" IsolateOption = "isolate"
MetricOption = "metric" MetricOption = "metric"
NoDefaultRoute = "no_default_route"
BclimOption = "bclim"
) )
type NetworkBackend string type NetworkBackend string

View File

@ -34,6 +34,10 @@ type ContainerNetwork interface {
// DefaultNetworkName will return the default network name // DefaultNetworkName will return the default network name
// for this interface. // for this interface.
DefaultNetworkName() string DefaultNetworkName() string
// NetworkInfo return the network information about backend type,
// binary path, package version and so on.
NetworkInfo() NetworkInfo
} }
// Network describes the Network attributes. // Network describes the Network attributes.
@ -50,6 +54,8 @@ type Network struct {
Created time.Time `json:"created,omitempty"` Created time.Time `json:"created,omitempty"`
// Subnets to use for this network. // Subnets to use for this network.
Subnets []Subnet `json:"subnets,omitempty"` Subnets []Subnet `json:"subnets,omitempty"`
// Routes to use for this network.
Routes []Route `json:"routes,omitempty"`
// IPv6Enabled if set to true an ipv6 subnet should be created for this net. // IPv6Enabled if set to true an ipv6 subnet should be created for this net.
IPv6Enabled bool `json:"ipv6_enabled"` IPv6Enabled bool `json:"ipv6_enabled"`
// Internal is whether the Network should not have external routes // Internal is whether the Network should not have external routes
@ -80,6 +86,22 @@ type NetworkUpdateOptions struct {
RemoveDNSServers []string `json:"remove_dns_servers,omitempty"` RemoveDNSServers []string `json:"remove_dns_servers,omitempty"`
} }
// NetworkInfo contains the network information.
type NetworkInfo struct {
Backend NetworkBackend `json:"backend"`
Version string `json:"version,omitempty"`
Package string `json:"package,omitempty"`
Path string `json:"path,omitempty"`
DNS DNSNetworkInfo `json:"dns,omitempty"`
}
// NetworkInfo contains the DNS information.
type DNSNetworkInfo struct {
Version string `json:"version,omitempty"`
Package string `json:"package,omitempty"`
Path string `json:"path,omitempty"`
}
// IPNet is used as custom net.IPNet type to add Marshal/Unmarshal methods. // IPNet is used as custom net.IPNet type to add Marshal/Unmarshal methods.
type IPNet struct { type IPNet struct {
net.IPNet net.IPNet
@ -169,6 +191,17 @@ type Subnet struct {
LeaseRange *LeaseRange `json:"lease_range,omitempty"` LeaseRange *LeaseRange `json:"lease_range,omitempty"`
} }
type Route struct {
// Destination for this route in CIDR form.
// swagger:strfmt string
Destination IPNet `json:"destination"`
// Gateway IP for this route.
// swagger:strfmt string
Gateway net.IP `json:"gateway"`
// Metric for this route. Optional.
Metric *uint32 `json:"metric,omitempty"`
}
// LeaseRange contains the range where IP are leased. // LeaseRange contains the range where IP are leased.
type LeaseRange struct { type LeaseRange struct {
// StartIP first IP in the subnet which should be used to assign ips. // StartIP first IP in the subnet which should be used to assign ips.

View File

@ -584,6 +584,10 @@ type NetworkConfig struct {
// are always assigned randomly. // are always assigned randomly.
DefaultSubnetPools []SubnetPool `toml:"default_subnet_pools,omitempty"` DefaultSubnetPools []SubnetPool `toml:"default_subnet_pools,omitempty"`
// DefaultRootlessNetworkCmd is used to set the default rootless network
// program, either "slirp4nents" (default) or "pasta".
DefaultRootlessNetworkCmd string `toml:"default_rootless_network_cmd,omitempty"`
// NetworkConfigDir is where network configuration files are stored. // NetworkConfigDir is where network configuration files are stored.
NetworkConfigDir string `toml:"network_config_dir,omitempty"` NetworkConfigDir string `toml:"network_config_dir,omitempty"`
@ -591,6 +595,10 @@ type NetworkConfig struct {
// for netavark rootful bridges with dns enabled. This can be necessary // for netavark rootful bridges with dns enabled. This can be necessary
// when other dns forwarders run on the machine. 53 is used if unset. // when other dns forwarders run on the machine. 53 is used if unset.
DNSBindPort uint16 `toml:"dns_bind_port,omitempty,omitzero"` DNSBindPort uint16 `toml:"dns_bind_port,omitempty,omitzero"`
// PastaOptions contains a default list of pasta(1) options that should
// be used when running pasta.
PastaOptions []string `toml:"pasta_options,omitempty"`
} }
type SubnetPool struct { type SubnetPool struct {

View File

@ -344,6 +344,13 @@ default_sysctls = [
# {"base" = "10.128.0.0/9", "size" = 24}, # {"base" = "10.128.0.0/9", "size" = 24},
#] #]
# Configure which rootless network program to use by default. Valid options are
# `slirp4netns` (default) and `pasta`.
#
#default_rootless_network_cmd = "slirp4netns"
# Path to the directory where network configuration files are located. # Path to the directory where network configuration files are located.
# For the CNI backend the default is "/etc/cni/net.d" as root # For the CNI backend the default is "/etc/cni/net.d" as root
# and "$HOME/.config/cni/net.d" as rootless. # and "$HOME/.config/cni/net.d" as rootless.
@ -359,6 +366,11 @@ default_sysctls = [
# #
#dns_bind_port = 53 #dns_bind_port = 53
# A list of default pasta options that should be used running pasta.
# It accepts the pasta cli options, see pasta(1) for the full list of options.
#
#pasta_options = []
[engine] [engine]
# Index to the active service # Index to the active service
# #
@ -407,7 +419,7 @@ default_sysctls = [
# Format is a single character [a-Z] or a comma separated sequence of # Format is a single character [a-Z] or a comma separated sequence of
# `ctrl-<value>`, where `<value>` is one of: # `ctrl-<value>`, where `<value>` is one of:
# `a-z`, `@`, `^`, `[`, `\`, `]`, `^` or `_` # `a-z`, `@`, `^`, `[`, `\`, `]`, `^` or `_`
# # Specifying "" disables this feature.
#detach_keys = "ctrl-p,ctrl-q" #detach_keys = "ctrl-p,ctrl-q"
# Determines whether engine will reserve ports on the host when they are # Determines whether engine will reserve ports on the host when they are

View File

@ -218,6 +218,7 @@ func DefaultConfig() (*Config, error) {
DefaultNetwork: "podman", DefaultNetwork: "podman",
DefaultSubnet: DefaultSubnet, DefaultSubnet: DefaultSubnet,
DefaultSubnetPools: DefaultSubnetPools, DefaultSubnetPools: DefaultSubnetPools,
DefaultRootlessNetworkCmd: "slirp4netns",
DNSBindPort: 0, DNSBindPort: 0,
CNIPluginDirs: DefaultCNIPluginDirs, CNIPluginDirs: DefaultCNIPluginDirs,
NetavarkPluginDirs: DefaultNetavarkPluginDirs, NetavarkPluginDirs: DefaultNetavarkPluginDirs,
@ -283,6 +284,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes") c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes")
c.VolumePluginTimeout = DefaultVolumePluginTimeout c.VolumePluginTimeout = DefaultVolumePluginTimeout
c.CompressionFormat = "gzip"
c.HelperBinariesDir = defaultHelperBinariesDir c.HelperBinariesDir = defaultHelperBinariesDir
if additionalHelperBinariesDir != "" { if additionalHelperBinariesDir != "" {

View File

@ -1,6 +1,94 @@
package util package util
import "regexp" import (
"bytes"
"fmt"
"os/exec"
"regexp"
"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)
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 // StringInSlice determines if a string is in a string slice, returns bool
func StringInSlice(s string, sl []string) bool { func StringInSlice(s string, sl []string) bool {

View File

@ -12,11 +12,41 @@ import (
internalManifest "github.com/containers/image/v5/internal/manifest" internalManifest "github.com/containers/image/v5/internal/manifest"
"github.com/containers/image/v5/manifest" "github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/signature" "github.com/containers/image/v5/signature"
digest "github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
type instanceCopyKind int
const (
instanceCopyCopy instanceCopyKind = iota
instanceCopyClone
)
type instanceCopy struct {
op instanceCopyKind
sourceDigest digest.Digest
}
// prepareInstanceCopies prepares a list of instances which needs to copied to the manifest list.
func prepareInstanceCopies(instanceDigests []digest.Digest, options *Options) []instanceCopy {
res := []instanceCopy{}
for i, instanceDigest := range instanceDigests {
if options.ImageListSelection == CopySpecificImages &&
!slices.Contains(options.Instances, instanceDigest) {
logrus.Debugf("Skipping instance %s (%d/%d)", instanceDigest, i+1, len(instanceDigests))
continue
}
res = append(res, instanceCopy{
op: instanceCopyCopy,
sourceDigest: instanceDigest,
})
}
return res
}
// copyMultipleImages copies some or all of an image list's instances, using // copyMultipleImages copies some or all of an image list's instances, using
// policyContext to validate source image admissibility. // policyContext to validate source image admissibility.
func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedToplevel *image.UnparsedImage) (copiedManifest []byte, retErr error) { func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signature.PolicyContext, options *Options, unparsedToplevel *image.UnparsedImage) (copiedManifest []byte, retErr error) {
@ -88,44 +118,35 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
// Copy each image, or just the ones we want to copy, in turn. // Copy each image, or just the ones we want to copy, in turn.
instanceDigests := updatedList.Instances() instanceDigests := updatedList.Instances()
imagesToCopy := len(instanceDigests) instanceEdits := []internalManifest.ListEdit{}
if options.ImageListSelection == CopySpecificImages { instanceCopyList := prepareInstanceCopies(instanceDigests, options)
imagesToCopy = len(options.Instances) c.Printf("Copying %d of %d images in list\n", len(instanceCopyList), len(instanceDigests))
} for i, instance := range instanceCopyList {
c.Printf("Copying %d of %d images in list\n", imagesToCopy, len(instanceDigests)) // Update instances to be edited by their `ListOperation` and
updates := make([]manifest.ListUpdate, len(instanceDigests)) // populate necessary fields.
instancesCopied := 0 switch instance.op {
for i, instanceDigest := range instanceDigests { case instanceCopyCopy:
if options.ImageListSelection == CopySpecificImages && logrus.Debugf("Copying instance %s (%d/%d)", instance.sourceDigest, i+1, len(instanceCopyList))
!slices.Contains(options.Instances, instanceDigest) { c.Printf("Copying image %s (%d/%d)\n", instance.sourceDigest, i+1, len(instanceCopyList))
update, err := updatedList.Instance(instanceDigest) unparsedInstance := image.UnparsedInstance(c.rawSource, &instanceCopyList[i].sourceDigest)
updatedManifest, updatedManifestType, updatedManifestDigest, err := c.copySingleImage(ctx, policyContext, options, unparsedToplevel, unparsedInstance, &instanceCopyList[i].sourceDigest)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("copying image %d/%d from manifest list: %w", i+1, len(instanceCopyList), err)
} }
logrus.Debugf("Skipping instance %s (%d/%d)", instanceDigest, i+1, len(instanceDigests))
// Record the digest/size/type of the manifest that we didn't copy.
updates[i] = update
continue
}
logrus.Debugf("Copying instance %s (%d/%d)", instanceDigest, i+1, len(instanceDigests))
c.Printf("Copying image %s (%d/%d)\n", instanceDigest, instancesCopied+1, imagesToCopy)
unparsedInstance := image.UnparsedInstance(c.rawSource, &instanceDigest)
updatedManifest, updatedManifestType, updatedManifestDigest, err := c.copySingleImage(ctx, policyContext, options, unparsedToplevel, unparsedInstance, &instanceDigest)
if err != nil {
return nil, fmt.Errorf("copying image %d/%d from manifest list: %w", instancesCopied+1, imagesToCopy, err)
}
instancesCopied++
// Record the result of a possible conversion here. // Record the result of a possible conversion here.
update := manifest.ListUpdate{ instanceEdits = append(instanceEdits, internalManifest.ListEdit{
Digest: updatedManifestDigest, ListOperation: internalManifest.ListOpUpdate,
Size: int64(len(updatedManifest)), UpdateOldDigest: instance.sourceDigest,
MediaType: updatedManifestType, UpdateDigest: updatedManifestDigest,
UpdateSize: int64(len(updatedManifest)),
UpdateMediaType: updatedManifestType})
default:
return nil, fmt.Errorf("copying image: invalid copy operation %d", instance.op)
} }
updates[i] = update
} }
// Now reset the digest/size/types of the manifests in the list to account for any conversions that we made. // Now reset the digest/size/types of the manifests in the list to account for any conversions that we made.
if err = updatedList.UpdateInstances(updates); err != nil { if err = updatedList.EditInstances(instanceEdits); err != nil {
return nil, fmt.Errorf("updating manifest list: %w", err) return nil, fmt.Errorf("updating manifest list: %w", err)
} }

View File

@ -69,27 +69,71 @@ func (list *Schema2ListPublic) Instance(instanceDigest digest.Digest) (ListUpdat
// UpdateInstances updates the sizes, digests, and media types of the manifests // UpdateInstances updates the sizes, digests, and media types of the manifests
// which the list catalogs. // which the list catalogs.
func (list *Schema2ListPublic) UpdateInstances(updates []ListUpdate) error { func (index *Schema2ListPublic) UpdateInstances(updates []ListUpdate) error {
if len(updates) != len(list.Manifests) { editInstances := []ListEdit{}
return fmt.Errorf("incorrect number of update entries passed to Schema2List.UpdateInstances: expected %d, got %d", len(list.Manifests), len(updates)) for i, instance := range updates {
editInstances = append(editInstances, ListEdit{
UpdateOldDigest: index.Manifests[i].Digest,
UpdateDigest: instance.Digest,
UpdateSize: instance.Size,
UpdateMediaType: instance.MediaType,
ListOperation: ListOpUpdate})
} }
for i := range updates { return index.editInstances(editInstances)
if err := updates[i].Digest.Validate(); err != nil { }
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances contained an invalid digest: %w", i+1, len(updates), err)
func (index *Schema2ListPublic) editInstances(editInstances []ListEdit) error {
addedEntries := []Schema2ManifestDescriptor{}
for i, editInstance := range editInstances {
switch editInstance.ListOperation {
case ListOpUpdate:
if err := editInstance.UpdateOldDigest.Validate(); err != nil {
return fmt.Errorf("Schema2List.EditInstances: Attempting to update %s which is an invalid digest: %w", editInstance.UpdateOldDigest, err)
} }
list.Manifests[i].Digest = updates[i].Digest if err := editInstance.UpdateDigest.Validate(); err != nil {
if updates[i].Size < 0 { return fmt.Errorf("Schema2List.EditInstances: Modified digest %s is an invalid digest: %w", editInstance.UpdateDigest, err)
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances had an invalid size (%d)", i+1, len(updates), updates[i].Size)
} }
list.Manifests[i].Size = updates[i].Size targetIndex := slices.IndexFunc(index.Manifests, func(m Schema2ManifestDescriptor) bool {
if updates[i].MediaType == "" { return m.Digest == editInstance.UpdateOldDigest
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances had no media type (was %q)", i+1, len(updates), list.Manifests[i].MediaType) })
if targetIndex == -1 {
return fmt.Errorf("Schema2List.EditInstances: digest %s not found", editInstance.UpdateOldDigest)
} }
list.Manifests[i].MediaType = updates[i].MediaType index.Manifests[targetIndex].Digest = editInstance.UpdateDigest
if editInstance.UpdateSize < 0 {
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances had an invalid size (%d)", i+1, len(editInstances), editInstance.UpdateSize)
}
index.Manifests[targetIndex].Size = editInstance.UpdateSize
if editInstance.UpdateMediaType == "" {
return fmt.Errorf("update %d of %d passed to Schema2List.UpdateInstances had no media type (was %q)", i+1, len(editInstances), index.Manifests[i].MediaType)
}
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,
},
}
addedEntries = append(addedEntries, addInstance)
default:
return fmt.Errorf("internal error: invalid operation: %d", editInstance.ListOperation)
}
}
if len(addedEntries) != 0 {
index.Manifests = append(index.Manifests, addedEntries...)
} }
return nil return nil
} }
func (index *Schema2List) EditInstances(editInstances []ListEdit) error {
return index.editInstances(editInstances)
}
func (list *Schema2ListPublic) ChooseInstanceByCompression(ctx *types.SystemContext, preferGzip types.OptionalBool) (digest.Digest, error) { func (list *Schema2ListPublic) ChooseInstanceByCompression(ctx *types.SystemContext, preferGzip types.OptionalBool) (digest.Digest, error) {
// ChooseInstanceByCompression is same as ChooseInstance for schema2 manifest list. // ChooseInstanceByCompression is same as ChooseInstance for schema2 manifest list.
return list.ChooseInstance(ctx) return list.ChooseInstance(ctx)

View File

@ -55,6 +55,10 @@ type List interface {
// SystemContext ( or for the current platform if the SystemContext doesn't specify any detail ) and preferGzip for compression which // SystemContext ( or for the current platform if the SystemContext doesn't specify any detail ) and preferGzip for compression which
// when configured to OptionalBoolTrue and chooses best available compression when it is OptionalBoolFalse or left OptionalBoolUndefined. // when configured to OptionalBoolTrue and chooses best available compression when it is OptionalBoolFalse or left OptionalBoolUndefined.
ChooseInstanceByCompression(ctx *types.SystemContext, preferGzip types.OptionalBool) (digest.Digest, error) ChooseInstanceByCompression(ctx *types.SystemContext, preferGzip types.OptionalBool) (digest.Digest, error)
// Edit information about the list's instances. Contains Slice of ListEdit where each element
// is responsible for either Modifying or Adding a new instance to the Manifest. Operation is
// selected on the basis of configured ListOperation field.
EditInstances([]ListEdit) error
} }
// ListUpdate includes the fields which a List's UpdateInstances() method will modify. // ListUpdate includes the fields which a List's UpdateInstances() method will modify.
@ -65,6 +69,32 @@ type ListUpdate struct {
MediaType string MediaType string
} }
type ListOp int
const (
listOpInvalid ListOp = iota
ListOpAdd
ListOpUpdate
)
// ListEdit includes the fields which a List's EditInstances() method will modify.
type ListEdit struct {
ListOperation ListOp
// if Op == ListEditUpdate (basically the previous UpdateInstances). All fields must be set.
UpdateOldDigest digest.Digest
UpdateDigest digest.Digest
UpdateSize int64
UpdateMediaType string
// If Op = ListEditAdd. All fields must be set.
AddDigest digest.Digest
AddSize int64
AddMediaType string
AddPlatform *imgspecv1.Platform
AddAnnotations map[string]string
}
// ListPublicFromBlob parses a list of manifests. // ListPublicFromBlob parses a list of manifests.
// This is publicly visible as c/image/manifest.ListFromBlob. // This is publicly visible as c/image/manifest.ListFromBlob.
func ListPublicFromBlob(manifest []byte, manifestMIMEType string) (ListPublic, error) { func ListPublicFromBlob(manifest []byte, manifestMIMEType string) (ListPublic, error) {

View File

@ -64,26 +64,68 @@ func (index *OCI1IndexPublic) Instance(instanceDigest digest.Digest) (ListUpdate
// UpdateInstances updates the sizes, digests, and media types of the manifests // UpdateInstances updates the sizes, digests, and media types of the manifests
// which the list catalogs. // which the list catalogs.
func (index *OCI1IndexPublic) UpdateInstances(updates []ListUpdate) error { func (index *OCI1IndexPublic) UpdateInstances(updates []ListUpdate) error {
if len(updates) != len(index.Manifests) { editInstances := []ListEdit{}
return fmt.Errorf("incorrect number of update entries passed to OCI1Index.UpdateInstances: expected %d, got %d", len(index.Manifests), len(updates)) for i, instance := range updates {
editInstances = append(editInstances, ListEdit{
UpdateOldDigest: index.Manifests[i].Digest,
UpdateDigest: instance.Digest,
UpdateSize: instance.Size,
UpdateMediaType: instance.MediaType,
ListOperation: ListOpUpdate})
} }
for i := range updates { return index.editInstances(editInstances)
if err := updates[i].Digest.Validate(); err != nil { }
return fmt.Errorf("update %d of %d passed to OCI1Index.UpdateInstances contained an invalid digest: %w", i+1, len(updates), err)
func (index *OCI1IndexPublic) editInstances(editInstances []ListEdit) error {
addedEntries := []imgspecv1.Descriptor{}
for i, editInstance := range editInstances {
switch editInstance.ListOperation {
case ListOpUpdate:
if err := editInstance.UpdateOldDigest.Validate(); err != nil {
return fmt.Errorf("OCI1Index.EditInstances: Attempting to update %s which is an invalid digest: %w", editInstance.UpdateOldDigest, err)
} }
index.Manifests[i].Digest = updates[i].Digest if err := editInstance.UpdateDigest.Validate(); err != nil {
if updates[i].Size < 0 { return fmt.Errorf("OCI1Index.EditInstances: Modified digest %s is an invalid digest: %w", editInstance.UpdateDigest, err)
return fmt.Errorf("update %d of %d passed to OCI1Index.UpdateInstances had an invalid size (%d)", i+1, len(updates), updates[i].Size)
} }
index.Manifests[i].Size = updates[i].Size targetIndex := slices.IndexFunc(index.Manifests, func(m imgspecv1.Descriptor) bool {
if updates[i].MediaType == "" { return m.Digest == editInstance.UpdateOldDigest
return fmt.Errorf("update %d of %d passed to OCI1Index.UpdateInstances had no media type (was %q)", i+1, len(updates), index.Manifests[i].MediaType) })
if targetIndex == -1 {
return fmt.Errorf("OCI1Index.EditInstances: digest %s not found", editInstance.UpdateOldDigest)
} }
index.Manifests[i].MediaType = updates[i].MediaType index.Manifests[targetIndex].Digest = editInstance.UpdateDigest
if editInstance.UpdateSize < 0 {
return fmt.Errorf("update %d of %d passed to OCI1Index.UpdateInstances had an invalid size (%d)", i+1, len(editInstances), editInstance.UpdateSize)
}
index.Manifests[targetIndex].Size = editInstance.UpdateSize
if editInstance.UpdateMediaType == "" {
return fmt.Errorf("update %d of %d passed to OCI1Index.UpdateInstances had no media type (was %q)", i+1, len(editInstances), index.Manifests[i].MediaType)
}
index.Manifests[targetIndex].MediaType = editInstance.UpdateMediaType
case ListOpAdd:
addedEntries = append(addedEntries, imgspecv1.Descriptor{
MediaType: editInstance.AddMediaType,
Size: editInstance.AddSize,
Digest: editInstance.AddDigest,
Platform: editInstance.AddPlatform,
Annotations: editInstance.AddAnnotations})
default:
return fmt.Errorf("internal error: invalid operation: %d", editInstance.ListOperation)
}
}
if len(addedEntries) != 0 {
index.Manifests = append(index.Manifests, addedEntries...)
slices.SortStableFunc(index.Manifests, func(a, b imgspecv1.Descriptor) bool {
return !instanceIsZstd(a) && instanceIsZstd(b)
})
} }
return nil return nil
} }
func (index *OCI1Index) EditInstances(editInstances []ListEdit) error {
return index.editInstances(editInstances)
}
// instanceIsZstd returns true if instance is a zstd instance otherwise false. // instanceIsZstd returns true if instance is a zstd instance otherwise false.
func instanceIsZstd(manifest imgspecv1.Descriptor) bool { func instanceIsZstd(manifest imgspecv1.Descriptor) bool {
if value, ok := manifest.Annotations[OCI1InstanceAnnotationCompressionZSTD]; ok && value == "true" { if value, ok := manifest.Annotations[OCI1InstanceAnnotationCompressionZSTD]; ok && value == "true" {
@ -131,8 +173,6 @@ func (index *OCI1IndexPublic) chooseInstance(ctx *types.SystemContext, preferGzi
for manifestIndex, d := range index.Manifests { for manifestIndex, d := range index.Manifests {
candidate := instanceCandidate{platformIndex: math.MaxInt, manifestPosition: manifestIndex, isZstd: instanceIsZstd(d), digest: d.Digest} candidate := instanceCandidate{platformIndex: math.MaxInt, manifestPosition: manifestIndex, isZstd: instanceIsZstd(d), digest: d.Digest}
if d.Platform != nil { if d.Platform != nil {
foundPlatform := false
for platformIndex, wantedPlatform := range wantedPlatforms {
imagePlatform := imgspecv1.Platform{ imagePlatform := imgspecv1.Platform{
Architecture: d.Platform.Architecture, Architecture: d.Platform.Architecture,
OS: d.Platform.OS, OS: d.Platform.OS,
@ -140,15 +180,13 @@ func (index *OCI1IndexPublic) chooseInstance(ctx *types.SystemContext, preferGzi
OSFeatures: slices.Clone(d.Platform.OSFeatures), OSFeatures: slices.Clone(d.Platform.OSFeatures),
Variant: d.Platform.Variant, Variant: d.Platform.Variant,
} }
if platform.MatchesPlatform(imagePlatform, wantedPlatform) { platformIndex := slices.IndexFunc(wantedPlatforms, func(wantedPlatform imgspecv1.Platform) bool {
foundPlatform = true return platform.MatchesPlatform(imagePlatform, wantedPlatform)
candidate.platformIndex = platformIndex })
break if platformIndex == -1 {
}
}
if !foundPlatform {
continue continue
} }
candidate.platformIndex = platformIndex
} }
if bestMatch == nil || candidate.isPreferredOver(bestMatch, didPreferGzip) { if bestMatch == nil || candidate.isPreferredOver(bestMatch, didPreferGzip) {
bestMatch = &candidate bestMatch = &candidate

View File

@ -24,11 +24,11 @@ func NewWithValues[E comparable](values ...E) *Set[E] {
return s return s
} }
func (s Set[E]) Add(v E) { func (s *Set[E]) Add(v E) {
s.m[v] = struct{}{} // Possibly writing the same struct{}{} presence marker again. s.m[v] = struct{}{} // Possibly writing the same struct{}{} presence marker again.
} }
func (s Set[E]) Delete(v E) { func (s *Set[E]) Delete(v E) {
delete(s.m, v) delete(s.m, v)
} }

View File

@ -48,9 +48,9 @@ var (
ErrNotSupported = errors.New("not supported") ErrNotSupported = errors.New("not supported")
) )
// authPath combines a path to a file with container registry access keys, // authPath combines a path to a file with container registry credentials,
// along with expected properties of that path (currently just whether it's) // along with expected properties of that path (currently just whether it's
// legacy format or not. // legacy format or not).
type authPath struct { type authPath struct {
path string path string
legacyFormat bool legacyFormat bool
@ -87,12 +87,12 @@ func SetCredentials(sys *types.SystemContext, key, username, password string) (s
switch helper { switch helper {
// Special-case the built-in helpers for auth files. // Special-case the built-in helpers for auth files.
case sysregistriesv2.AuthenticationFileHelper: case sysregistriesv2.AuthenticationFileHelper:
desc, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, string, error) { desc, err = modifyJSON(sys, func(fileContents *dockerConfigFile) (bool, string, error) {
if ch, exists := auths.CredHelpers[key]; exists { if ch, exists := fileContents.CredHelpers[key]; exists {
if isNamespaced { if isNamespaced {
return false, "", unsupportedNamespaceErr(ch) return false, "", unsupportedNamespaceErr(ch)
} }
desc, err := setAuthToCredHelper(ch, key, username, password) desc, err := setCredsInCredHelper(ch, key, username, password)
if err != nil { if err != nil {
return false, "", err return false, "", err
} }
@ -100,7 +100,7 @@ func SetCredentials(sys *types.SystemContext, key, username, password string) (s
} }
creds := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) creds := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
newCreds := dockerAuthConfig{Auth: creds} newCreds := dockerAuthConfig{Auth: creds}
auths.AuthConfigs[key] = newCreds fileContents.AuthConfigs[key] = newCreds
return true, "", nil return true, "", nil
}) })
// External helpers. // External helpers.
@ -108,7 +108,7 @@ func SetCredentials(sys *types.SystemContext, key, username, password string) (s
if isNamespaced { if isNamespaced {
err = unsupportedNamespaceErr(helper) err = unsupportedNamespaceErr(helper)
} else { } else {
desc, err = setAuthToCredHelper(helper, key, username, password) desc, err = setCredsInCredHelper(helper, key, username, password)
} }
} }
if err != nil { if err != nil {
@ -156,17 +156,17 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
case sysregistriesv2.AuthenticationFileHelper: case sysregistriesv2.AuthenticationFileHelper:
for _, path := range getAuthFilePaths(sys, homedir.Get()) { for _, path := range getAuthFilePaths(sys, homedir.Get()) {
// parse returns an empty map in case the path doesn't exist. // parse returns an empty map in case the path doesn't exist.
auths, err := path.parse() fileContents, err := path.parse()
if err != nil { if err != nil {
return nil, fmt.Errorf("reading JSON file %q: %w", path.path, err) return nil, fmt.Errorf("reading JSON file %q: %w", path.path, err)
} }
// Credential helpers in the auth file have a // Credential helpers in the auth file have a
// direct mapping to a registry, so we can just // direct mapping to a registry, so we can just
// walk the map. // walk the map.
for registry := range auths.CredHelpers { for registry := range fileContents.CredHelpers {
allKeys.Add(registry) allKeys.Add(registry)
} }
for key := range auths.AuthConfigs { for key := range fileContents.AuthConfigs {
key := normalizeAuthFileKey(key, path.legacyFormat) key := normalizeAuthFileKey(key, path.legacyFormat)
if key == normalizedDockerIORegistry { if key == normalizedDockerIORegistry {
key = "docker.io" key = "docker.io"
@ -176,7 +176,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
} }
// External helpers. // External helpers.
default: default:
creds, err := listAuthsFromCredHelper(helper) creds, err := listCredsInCredHelper(helper)
if err != nil { if err != nil {
logrus.Debugf("Error listing credentials stored in credential helper %s: %v", helper, err) logrus.Debugf("Error listing credentials stored in credential helper %s: %v", helper, err)
if errors.Is(err, exec.ErrNotFound) { if errors.Is(err, exec.ErrNotFound) {
@ -193,19 +193,19 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
// Now use `GetCredentials` to the specific auth configs for each // Now use `GetCredentials` to the specific auth configs for each
// previously listed registry. // previously listed registry.
authConfigs := make(map[string]types.DockerAuthConfig) allCreds := make(map[string]types.DockerAuthConfig)
for _, key := range allKeys.Values() { for _, key := range allKeys.Values() {
authConf, err := GetCredentials(sys, key) creds, err := GetCredentials(sys, key)
if err != nil { if err != nil {
// Note: we rely on the logging in `GetCredentials`. // Note: we rely on the logging in `GetCredentials`.
return nil, err return nil, err
} }
if authConf != (types.DockerAuthConfig{}) { if creds != (types.DockerAuthConfig{}) {
authConfigs[key] = authConf allCreds[key] = creds
} }
} }
return authConfigs, nil return allCreds, nil
} }
// getAuthFilePaths returns a slice of authPaths based on the system context // getAuthFilePaths returns a slice of authPaths based on the system context
@ -285,13 +285,13 @@ func getCredentialsWithHomeDir(sys *types.SystemContext, key, homeDir string) (t
// Anonymous function to query credentials from auth files. // Anonymous function to query credentials from auth files.
getCredentialsFromAuthFiles := func() (types.DockerAuthConfig, string, error) { getCredentialsFromAuthFiles := func() (types.DockerAuthConfig, string, error) {
for _, path := range getAuthFilePaths(sys, homeDir) { for _, path := range getAuthFilePaths(sys, homeDir) {
authConfig, err := findCredentialsInFile(key, registry, path) creds, err := findCredentialsInFile(key, registry, path)
if err != nil { if err != nil {
return types.DockerAuthConfig{}, "", err return types.DockerAuthConfig{}, "", err
} }
if authConfig != (types.DockerAuthConfig{}) { if creds != (types.DockerAuthConfig{}) {
return authConfig, path.path, nil return creds, path.path, nil
} }
} }
return types.DockerAuthConfig{}, "", nil return types.DockerAuthConfig{}, "", nil
@ -320,7 +320,7 @@ func getCredentialsWithHomeDir(sys *types.SystemContext, key, homeDir string) (t
// This intentionally uses "registry", not "key"; we don't support namespaced // This intentionally uses "registry", not "key"; we don't support namespaced
// credentials in helpers, but a "registry" is a valid parent of "key". // credentials in helpers, but a "registry" is a valid parent of "key".
helperKey = registry helperKey = registry
creds, err = getAuthFromCredHelper(helper, registry) creds, err = getCredsFromCredHelper(helper, registry)
} }
if err != nil { if err != nil {
logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", helperKey, helper, err) logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", helperKey, helper, err)
@ -360,14 +360,14 @@ func GetAuthentication(sys *types.SystemContext, key string) (string, string, er
// getAuthenticationWithHomeDir is an internal implementation detail of GetAuthentication, // getAuthenticationWithHomeDir is an internal implementation detail of GetAuthentication,
// it exists only to allow testing it with an artificial home directory. // it exists only to allow testing it with an artificial home directory.
func getAuthenticationWithHomeDir(sys *types.SystemContext, key, homeDir string) (string, string, error) { func getAuthenticationWithHomeDir(sys *types.SystemContext, key, homeDir string) (string, string, error) {
auth, err := getCredentialsWithHomeDir(sys, key, homeDir) creds, err := getCredentialsWithHomeDir(sys, key, homeDir)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
if auth.IdentityToken != "" { if creds.IdentityToken != "" {
return "", "", fmt.Errorf("non-empty identity token found and this API doesn't support it: %w", ErrNotSupported) return "", "", fmt.Errorf("non-empty identity token found and this API doesn't support it: %w", ErrNotSupported)
} }
return auth.Username, auth.Password, nil return creds.Username, creds.Password, nil
} }
// RemoveAuthentication removes credentials for `key` from all possible // RemoveAuthentication removes credentials for `key` from all possible
@ -393,7 +393,7 @@ func RemoveAuthentication(sys *types.SystemContext, key string) error {
logrus.Debugf("Not removing credentials because namespaced keys are not supported for the credential helper: %s", helper) logrus.Debugf("Not removing credentials because namespaced keys are not supported for the credential helper: %s", helper)
return return
} }
err := deleteAuthFromCredHelper(helper, key) err := deleteCredsFromCredHelper(helper, key)
if err == nil { if err == nil {
logrus.Debugf("Credentials for %q were deleted from credential helper %s", key, helper) logrus.Debugf("Credentials for %q were deleted from credential helper %s", key, helper)
isLoggedIn = true isLoggedIn = true
@ -411,13 +411,13 @@ func RemoveAuthentication(sys *types.SystemContext, key string) error {
switch helper { switch helper {
// Special-case the built-in helper for auth files. // Special-case the built-in helper for auth files.
case sysregistriesv2.AuthenticationFileHelper: case sysregistriesv2.AuthenticationFileHelper:
_, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, string, error) { _, err = modifyJSON(sys, func(fileContents *dockerConfigFile) (bool, string, error) {
if innerHelper, exists := auths.CredHelpers[key]; exists { if innerHelper, exists := fileContents.CredHelpers[key]; exists {
removeFromCredHelper(innerHelper) removeFromCredHelper(innerHelper)
} }
if _, ok := auths.AuthConfigs[key]; ok { if _, ok := fileContents.AuthConfigs[key]; ok {
isLoggedIn = true isLoggedIn = true
delete(auths.AuthConfigs, key) delete(fileContents.AuthConfigs, key)
} }
return true, "", multiErr return true, "", multiErr
}) })
@ -454,23 +454,23 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
switch helper { switch helper {
// Special-case the built-in helper for auth files. // Special-case the built-in helper for auth files.
case sysregistriesv2.AuthenticationFileHelper: case sysregistriesv2.AuthenticationFileHelper:
_, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, string, error) { _, err = modifyJSON(sys, func(fileContents *dockerConfigFile) (bool, string, error) {
for registry, helper := range auths.CredHelpers { for registry, helper := range fileContents.CredHelpers {
// Helpers in auth files are expected // Helpers in auth files are expected
// to exist, so no special treatment // to exist, so no special treatment
// for them. // for them.
if err := deleteAuthFromCredHelper(helper, registry); err != nil { if err := deleteCredsFromCredHelper(helper, registry); err != nil {
return false, "", err return false, "", err
} }
} }
auths.CredHelpers = make(map[string]string) fileContents.CredHelpers = make(map[string]string)
auths.AuthConfigs = make(map[string]dockerAuthConfig) fileContents.AuthConfigs = make(map[string]dockerAuthConfig)
return true, "", nil return true, "", nil
}) })
// External helpers. // External helpers.
default: default:
var creds map[string]string var creds map[string]string
creds, err = listAuthsFromCredHelper(helper) creds, err = listCredsInCredHelper(helper)
if err != nil { if err != nil {
if errors.Is(err, exec.ErrNotFound) { if errors.Is(err, exec.ErrNotFound) {
// It's okay if the helper doesn't exist. // It's okay if the helper doesn't exist.
@ -480,7 +480,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
} }
} }
for registry := range creds { for registry := range creds {
err = deleteAuthFromCredHelper(helper, registry) err = deleteCredsFromCredHelper(helper, registry)
if err != nil { if err != nil {
break break
} }
@ -497,7 +497,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
return multiErr return multiErr
} }
func listAuthsFromCredHelper(credHelper string) (map[string]string, error) { func listCredsInCredHelper(credHelper string) (map[string]string, error) {
helperName := fmt.Sprintf("docker-credential-%s", credHelper) helperName := fmt.Sprintf("docker-credential-%s", credHelper)
p := helperclient.NewShellProgramFunc(helperName) p := helperclient.NewShellProgramFunc(helperName)
return helperclient.List(p) return helperclient.List(p)
@ -543,40 +543,40 @@ func getPathToAuthWithOS(sys *types.SystemContext, goOS string) (authPath, bool,
return newAuthPathDefault(fmt.Sprintf(defaultPerUIDPathFormat, os.Getuid())), false, nil return newAuthPathDefault(fmt.Sprintf(defaultPerUIDPathFormat, os.Getuid())), false, nil
} }
// parse unmarshals the authentications stored in the auth.json file and returns it // parse unmarshals the credentials stored in the auth.json file and returns it
// or returns an empty dockerConfigFile data structure if auth.json does not exist // or returns an empty dockerConfigFile data structure if auth.json does not exist
// if the file exists and is empty, this function returns an error. // if the file exists and is empty, this function returns an error.
func (path authPath) parse() (dockerConfigFile, error) { func (path authPath) parse() (dockerConfigFile, error) {
var auths dockerConfigFile var fileContents dockerConfigFile
raw, err := os.ReadFile(path.path) raw, err := os.ReadFile(path.path)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
auths.AuthConfigs = map[string]dockerAuthConfig{} fileContents.AuthConfigs = map[string]dockerAuthConfig{}
return auths, nil return fileContents, nil
} }
return dockerConfigFile{}, err return dockerConfigFile{}, err
} }
if path.legacyFormat { if path.legacyFormat {
if err = json.Unmarshal(raw, &auths.AuthConfigs); err != nil { if err = json.Unmarshal(raw, &fileContents.AuthConfigs); err != nil {
return dockerConfigFile{}, fmt.Errorf("unmarshaling JSON at %q: %w", path.path, err) return dockerConfigFile{}, fmt.Errorf("unmarshaling JSON at %q: %w", path.path, err)
} }
return auths, nil return fileContents, nil
} }
if err = json.Unmarshal(raw, &auths); err != nil { if err = json.Unmarshal(raw, &fileContents); err != nil {
return dockerConfigFile{}, fmt.Errorf("unmarshaling JSON at %q: %w", path.path, err) return dockerConfigFile{}, fmt.Errorf("unmarshaling JSON at %q: %w", path.path, err)
} }
if auths.AuthConfigs == nil { if fileContents.AuthConfigs == nil {
auths.AuthConfigs = map[string]dockerAuthConfig{} fileContents.AuthConfigs = map[string]dockerAuthConfig{}
} }
if auths.CredHelpers == nil { if fileContents.CredHelpers == nil {
auths.CredHelpers = make(map[string]string) fileContents.CredHelpers = make(map[string]string)
} }
return auths, nil return fileContents, nil
} }
// modifyJSON finds an auth.json file, calls editor on the contents, and // modifyJSON finds an auth.json file, calls editor on the contents, and
@ -585,7 +585,7 @@ func (path authPath) parse() (dockerConfigFile, error) {
// //
// The editor may also return a human-readable description of the updated location; if it is "", // The editor may also return a human-readable description of the updated location; if it is "",
// the file itself is used. // the file itself is used.
func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (bool, string, error)) (string, error) { func modifyJSON(sys *types.SystemContext, editor func(fileContents *dockerConfigFile) (bool, string, error)) (string, error) {
path, _, err := getPathToAuth(sys) path, _, err := getPathToAuth(sys)
if err != nil { if err != nil {
return "", err return "", err
@ -599,17 +599,17 @@ func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (
return "", err return "", err
} }
auths, err := path.parse() fileContents, err := path.parse()
if err != nil { if err != nil {
return "", fmt.Errorf("reading JSON file %q: %w", path.path, err) return "", fmt.Errorf("reading JSON file %q: %w", path.path, err)
} }
updated, description, err := editor(&auths) updated, description, err := editor(&fileContents)
if err != nil { if err != nil {
return "", fmt.Errorf("updating %q: %w", path.path, err) return "", fmt.Errorf("updating %q: %w", path.path, err)
} }
if updated { if updated {
newData, err := json.MarshalIndent(auths, "", "\t") newData, err := json.MarshalIndent(fileContents, "", "\t")
if err != nil { if err != nil {
return "", fmt.Errorf("marshaling JSON %q: %w", path.path, err) return "", fmt.Errorf("marshaling JSON %q: %w", path.path, err)
} }
@ -625,7 +625,7 @@ func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (
return description, nil return description, nil
} }
func getAuthFromCredHelper(credHelper, registry string) (types.DockerAuthConfig, error) { func getCredsFromCredHelper(credHelper, registry string) (types.DockerAuthConfig, error) {
helperName := fmt.Sprintf("docker-credential-%s", credHelper) helperName := fmt.Sprintf("docker-credential-%s", credHelper)
p := helperclient.NewShellProgramFunc(helperName) p := helperclient.NewShellProgramFunc(helperName)
creds, err := helperclient.Get(p, registry) creds, err := helperclient.Get(p, registry)
@ -650,9 +650,9 @@ func getAuthFromCredHelper(credHelper, registry string) (types.DockerAuthConfig,
} }
} }
// setAuthToCredHelper stores (username, password) for registry in credHelper. // setCredsInCredHelper stores (username, password) for registry in credHelper.
// Returns a human-readable description of the destination, to be returned by SetCredentials. // Returns a human-readable description of the destination, to be returned by SetCredentials.
func setAuthToCredHelper(credHelper, registry, username, password string) (string, error) { func setCredsInCredHelper(credHelper, registry, username, password string) (string, error) {
helperName := fmt.Sprintf("docker-credential-%s", credHelper) helperName := fmt.Sprintf("docker-credential-%s", credHelper)
p := helperclient.NewShellProgramFunc(helperName) p := helperclient.NewShellProgramFunc(helperName)
creds := &credentials.Credentials{ creds := &credentials.Credentials{
@ -666,7 +666,7 @@ func setAuthToCredHelper(credHelper, registry, username, password string) (strin
return fmt.Sprintf("credential helper: %s", credHelper), nil return fmt.Sprintf("credential helper: %s", credHelper), nil
} }
func deleteAuthFromCredHelper(credHelper, registry string) error { func deleteCredsFromCredHelper(credHelper, registry string) error {
helperName := fmt.Sprintf("docker-credential-%s", credHelper) helperName := fmt.Sprintf("docker-credential-%s", credHelper)
p := helperclient.NewShellProgramFunc(helperName) p := helperclient.NewShellProgramFunc(helperName)
return helperclient.Erase(p, registry) return helperclient.Erase(p, registry)
@ -675,7 +675,7 @@ func deleteAuthFromCredHelper(credHelper, registry string) error {
// findCredentialsInFile looks for credentials matching "key" // findCredentialsInFile looks for credentials matching "key"
// (which is "registry" or a namespace in "registry") in "path". // (which is "registry" or a namespace in "registry") in "path".
func findCredentialsInFile(key, registry string, path authPath) (types.DockerAuthConfig, error) { func findCredentialsInFile(key, registry string, path authPath) (types.DockerAuthConfig, error) {
auths, err := path.parse() fileContents, err := path.parse()
if err != nil { if err != nil {
return types.DockerAuthConfig{}, fmt.Errorf("reading JSON file %q: %w", path.path, err) return types.DockerAuthConfig{}, fmt.Errorf("reading JSON file %q: %w", path.path, err)
} }
@ -683,9 +683,9 @@ func findCredentialsInFile(key, registry string, path authPath) (types.DockerAut
// First try cred helpers. They should always be normalized. // First try cred helpers. They should always be normalized.
// This intentionally uses "registry", not "key"; we don't support namespaced // This intentionally uses "registry", not "key"; we don't support namespaced
// credentials in helpers. // credentials in helpers.
if ch, exists := auths.CredHelpers[registry]; exists { if ch, exists := fileContents.CredHelpers[registry]; exists {
logrus.Debugf("Looking up in credential helper %s based on credHelpers entry in %s", ch, path.path) logrus.Debugf("Looking up in credential helper %s based on credHelpers entry in %s", ch, path.path)
return getAuthFromCredHelper(ch, registry) return getCredsFromCredHelper(ch, registry)
} }
// Support sub-registry namespaces in auth. // Support sub-registry namespaces in auth.
@ -701,7 +701,7 @@ func findCredentialsInFile(key, registry string, path authPath) (types.DockerAut
// Repo or namespace keys are only supported as exact matches. For registry // Repo or namespace keys are only supported as exact matches. For registry
// keys we prefer exact matches as well. // keys we prefer exact matches as well.
for _, key := range keys { for _, key := range keys {
if val, exists := auths.AuthConfigs[key]; exists { if val, exists := fileContents.AuthConfigs[key]; exists {
return decodeDockerAuth(path.path, key, val) return decodeDockerAuth(path.path, key, val)
} }
} }
@ -715,7 +715,7 @@ func findCredentialsInFile(key, registry string, path authPath) (types.DockerAut
// The docker.io registry still uses the /v1/ key with a special host name, // The docker.io registry still uses the /v1/ key with a special host name,
// so account for that as well. // so account for that as well.
registry = normalizeRegistry(registry) registry = normalizeRegistry(registry)
for k, v := range auths.AuthConfigs { for k, v := range fileContents.AuthConfigs {
if normalizeAuthFileKey(k, path.legacyFormat) == registry { if normalizeAuthFileKey(k, path.legacyFormat) == registry {
return decodeDockerAuth(path.path, k, v) return decodeDockerAuth(path.path, k, v)
} }

View File

@ -585,9 +585,9 @@ type SystemContext struct {
// resolving to Docker Hub in the Docker-compatible REST API of Podman; it should never be used outside this // resolving to Docker Hub in the Docker-compatible REST API of Podman; it should never be used outside this
// specific context. // specific context.
PodmanOnlyShortNamesIgnoreRegistriesConfAndForceDockerHub bool PodmanOnlyShortNamesIgnoreRegistriesConfAndForceDockerHub bool
// If not "", overrides the default path for the authentication file, but only new format files // If not "", overrides the default path for the registry authentication file, but only new format files
AuthFilePath string AuthFilePath string
// if not "", overrides the default path for the authentication file, but with the legacy format; // if not "", overrides the default path for the registry authentication file, but with the legacy format;
// the code currently will by default look for legacy format files like .dockercfg in the $HOME dir; // the code currently will by default look for legacy format files like .dockercfg in the $HOME dir;
// but in addition to the home dir, openshift may mount .dockercfg files (via secret mount) // but in addition to the home dir, openshift may mount .dockercfg files (via secret mount)
// in locations other than the home dir; openshift components should then set this field in those cases; // in locations other than the home dir; openshift components should then set this field in those cases;

View File

@ -17,13 +17,13 @@ env:
#### ####
#### Cache-image names to test with (double-quotes around names are critical) #### Cache-image names to test with (double-quotes around names are critical)
### ###
FEDORA_NAME: "fedora-37" FEDORA_NAME: "fedora-38"
DEBIAN_NAME: "debian-12" DEBIAN_NAME: "debian-12"
# GCE project where images live # GCE project where images live
IMAGE_PROJECT: "libpod-218412" IMAGE_PROJECT: "libpod-218412"
# VM Image built in containers/automation_images # VM Image built in containers/automation_images
IMAGE_SUFFIX: "c20230405t152256z-f37f36d12" IMAGE_SUFFIX: "c20230517t144652z-f38f37d12"
FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}"
DEBIAN_CACHE_IMAGE_NAME: "debian-${IMAGE_SUFFIX}" DEBIAN_CACHE_IMAGE_NAME: "debian-${IMAGE_SUFFIX}"
@ -56,7 +56,6 @@ gce_instance:
linux_testing: &linux_testing linux_testing: &linux_testing
depends_on: depends_on:
- lint - lint
only_if: $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
gce_instance: # Only need to specify differences from defaults (above) gce_instance: # Only need to specify differences from defaults (above)
image_name: "${VM_IMAGE}" image_name: "${VM_IMAGE}"
@ -127,10 +126,12 @@ lint_task:
fingerprint_script: cat go.sum fingerprint_script: cat go.sum
folder: $GOPATH/pkg/mod folder: $GOPATH/pkg/mod
build_script: | build_script: |
echo "deb http://deb.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/backports.list
apt-get update apt-get update
apt-get install -y libbtrfs-dev libdevmapper-dev apt-get install -y libbtrfs-dev libdevmapper-dev
test_script: make TAGS=regex_precompile local-validate && make lint && make clean test_script: |
make TAGS=regex_precompile local-validate
make lint
make clean
# Update metadata on VM images referenced by this repository state # Update metadata on VM images referenced by this repository state
@ -168,7 +169,7 @@ vendor_task:
cross_task: cross_task:
container: container:
image: golang:1.17 image: golang:1.19
build_script: make cross build_script: make cross
@ -182,6 +183,6 @@ success_task:
- vendor - vendor
- cross - cross
container: container:
image: golang:1.17 image: golang:1.19
clone_script: 'mkdir -p "$CIRRUS_WORKING_DIR"' # Source code not needed clone_script: 'mkdir -p "$CIRRUS_WORKING_DIR"' # Source code not needed
script: /bin/true script: /bin/true

View File

@ -4,68 +4,8 @@ run:
deadline: 5m deadline: 5m
skip-dirs-use-default: true skip-dirs-use-default: true
linters: linters:
enable-all: true enable:
disable:
- cyclop
- deadcode
- dogsled
- dupl
- errcheck
- errname
- errorlint
- exhaustive
- exhaustivestruct
- exhaustruct
- forbidigo
- forcetypeassert
- funlen
- gci
- gochecknoglobals
- gochecknoinits
- gocognit
- gocritic
- gocyclo
- godot
- godox
- goerr113
- gofumpt - gofumpt
- golint disable:
- gomnd - errcheck
- gosec
- gosimple
- govet
- ifshort
- ineffassign
- interfacer
- interfacebloat
- ireturn
- lll
- maintidx
- maligned
- misspell
- musttag
- nakedret
- nestif
- nlreturn
- nolintlint
- nonamedreturns
- nosnakecase
- paralleltest
- prealloc
- predeclared
- rowserrcheck
- scopelint
- staticcheck - staticcheck
- structcheck
- stylecheck
- tagliatelle
- testpackage
- thelper
- unconvert
- unparam
- varcheck
- varnamelen
- wastedassign
- whitespace
- wrapcheck
- wsl

View File

@ -1,13 +1,18 @@
export GO111MODULE=off
export GOPROXY=https://proxy.golang.org
.PHONY: \ .PHONY: \
all \ all \
binary \
clean \ clean \
codespell \
containers-storage \
cross \
default \ default \
docs \ docs \
gccgo \
help \ help \
install \
install.docs \
install.tools \ install.tools \
lint \
local-binary \ local-binary \
local-cross \ local-cross \
local-gccgo \ local-gccgo \
@ -15,33 +20,25 @@ export GOPROXY=https://proxy.golang.org
local-test-integration \ local-test-integration \
local-test-unit \ local-test-unit \
local-validate \ local-validate \
lint \ test-integration \
vendor test-unit \
validate \
vendor \
vendor-in-container
PACKAGE := github.com/containers/storage
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
GIT_BRANCH_CLEAN := $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g")
EPOCH_TEST_COMMIT := 0418ebf59f9e1f564831c0ba9378b7f8e40a1c73
NATIVETAGS := NATIVETAGS :=
AUTOTAGS := $(shell ./hack/btrfs_tag.sh) $(shell ./hack/libdm_tag.sh) $(shell ./hack/libsubid_tag.sh) AUTOTAGS := $(shell ./hack/btrfs_tag.sh) $(shell ./hack/libdm_tag.sh) $(shell ./hack/libsubid_tag.sh)
BUILDFLAGS := -tags "$(AUTOTAGS) $(TAGS)" $(FLAGS) BUILDFLAGS := -tags "$(AUTOTAGS) $(TAGS)" $(FLAGS)
GO ?= go GO ?= go
TESTFLAGS := $(shell $(GO) test -race $(BUILDFLAGS) ./pkg/stringutils 2>&1 > /dev/null && echo -race) TESTFLAGS := $(shell $(GO) test -race $(BUILDFLAGS) ./pkg/stringutils 2>&1 > /dev/null && echo -race)
# Go module support: set `-mod=vendor` to use the vendored sources
ifeq ($(shell $(GO) help mod >/dev/null 2>&1 && echo true), true)
GO:=GO111MODULE=on $(GO)
MOD_VENDOR=-mod=vendor
endif
default all: local-binary docs local-validate local-cross ## validate all checks, build and cross-build\nbinaries and docs default all: local-binary docs local-validate local-cross ## validate all checks, build and cross-build\nbinaries and docs
clean: ## remove all built files clean: ## remove all built files
$(RM) -f containers-storage containers-storage.* docs/*.1 docs/*.5 $(RM) -f containers-storage containers-storage.* docs/*.1 docs/*.5
sources := $(wildcard *.go cmd/containers-storage/*.go drivers/*.go drivers/*/*.go internal/*/*.go pkg/*/*.go pkg/*/*/*.go types/*.go) containers-storage: ## build using gc on the host
containers-storage: $(sources) ## build using gc on the host $(GO) build -compiler gc $(BUILDFLAGS) ./cmd/containers-storage
$(GO) build $(MOD_VENDOR) -compiler gc $(BUILDFLAGS) ./cmd/containers-storage
codespell: codespell:
codespell -S Makefile,build,buildah,buildah.spec,imgtype,copy,AUTHORS,bin,vendor,.git,go.sum,CHANGELOG.md,changelog.txt,seccomp.json,.cirrus.yml,"*.xz,*.gz,*.tar,*.tgz,*ico,*.png,*.1,*.5,*.orig,*.rej" -L worl,flate,uint,iff,od,ERRO -w codespell -S Makefile,build,buildah,buildah.spec,imgtype,copy,AUTHORS,bin,vendor,.git,go.sum,CHANGELOG.md,changelog.txt,seccomp.json,.cirrus.yml,"*.xz,*.gz,*.tar,*.tgz,*ico,*.png,*.1,*.5,*.orig,*.rej" -L worl,flate,uint,iff,od,ERRO -w
@ -49,15 +46,15 @@ codespell:
binary local-binary: containers-storage binary local-binary: containers-storage
local-gccgo gccgo: ## build using gccgo on the host local-gccgo gccgo: ## build using gccgo on the host
GCCGO=$(PWD)/hack/gccgo-wrapper.sh $(GO) build $(MOD_VENDOR) -compiler gccgo $(BUILDFLAGS) -o containers-storage.gccgo ./cmd/containers-storage GCCGO=$(PWD)/hack/gccgo-wrapper.sh $(GO) build -compiler gccgo $(BUILDFLAGS) -o containers-storage.gccgo ./cmd/containers-storage
local-cross cross: ## cross build the binaries for arm, darwin, and freebsd local-cross cross: ## cross build the binaries for arm, darwin, and freebsd
@for target in linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64 linux/ppc64le linux/s390x linux/mips linux/mipsle linux/mips64 linux/mips64le darwin/amd64 windows/amd64 freebsd/amd64 freebsd/arm64 ; do \ @for target in linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64 linux/ppc64le linux/s390x linux/mips linux/mipsle linux/mips64 linux/mips64le darwin/amd64 windows/amd64 freebsd/amd64 freebsd/arm64 ; do \
os=`echo $${target} | cut -f1 -d/` ; \ os=`echo $${target} | cut -f1 -d/` ; \
arch=`echo $${target} | cut -f2 -d/` ; \ arch=`echo $${target} | cut -f2 -d/` ; \
suffix=$${os}.$${arch} ; \ suffix=$${os}.$${arch} ; \
echo env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO) build $(MOD_VENDOR) -compiler gc -tags \"$(NATIVETAGS) $(TAGS)\" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage ; \ echo env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO) build -compiler gc -tags \"$(NATIVETAGS) $(TAGS)\" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage ; \
env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO) build $(MOD_VENDOR) -compiler gc -tags "$(NATIVETAGS) $(TAGS)" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage || exit 1 ; \ env CGO_ENABLED=0 GOOS=$${os} GOARCH=$${arch} $(GO) build -compiler gc -tags "$(NATIVETAGS) $(TAGS)" $(FLAGS) -o containers-storage.$${suffix} ./cmd/containers-storage || exit 1 ; \
done done
docs: install.tools ## build the docs on the host docs: install.tools ## build the docs on the host
@ -66,21 +63,17 @@ docs: install.tools ## build the docs on the host
local-test: local-binary local-test-unit local-test-integration ## build the binaries and run the tests local-test: local-binary local-test-unit local-test-integration ## build the binaries and run the tests
local-test-unit test-unit: local-binary ## run the unit tests on the host (requires\nsuperuser privileges) local-test-unit test-unit: local-binary ## run the unit tests on the host (requires\nsuperuser privileges)
@$(GO) test $(MOD_VENDOR) $(BUILDFLAGS) $(TESTFLAGS) $(shell $(GO) list ./... | grep -v ^$(PACKAGE)/vendor) @$(GO) test -count 1 $(BUILDFLAGS) $(TESTFLAGS) ./...
local-test-integration test-integration: local-binary ## run the integration tests on the host (requires\nsuperuser privileges) local-test-integration test-integration: local-binary ## run the integration tests on the host (requires\nsuperuser privileges)
@cd tests; ./test_runner.bash @cd tests; ./test_runner.bash
local-validate validate: install.tools ## validate DCO and gofmt on the host local-validate validate: install.tools ## validate DCO on the host
@./hack/git-validation.sh @./hack/git-validation.sh
@./hack/gofmt.sh
install.tools: install.tools:
$(MAKE) -C tests/tools $(MAKE) -C tests/tools
$(FFJSON):
$(MAKE) -C tests/tools
install.docs: docs install.docs: docs
$(MAKE) -C docs install $(MAKE) -C docs install

View File

@ -1 +1 @@
1.46.1 1.47.0-dev

1086
vendor/github.com/containers/storage/check.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -523,13 +523,20 @@ func (r *containerStore) load(lockedForWriting bool) (bool, error) {
// The caller must hold r.inProcessLock for reading (but usually holds it for writing in order to make the desired changes). // The caller must hold r.inProcessLock for reading (but usually holds it for writing in order to make the desired changes).
func (r *containerStore) save(saveLocations containerLocations) error { func (r *containerStore) save(saveLocations containerLocations) error {
r.lockfile.AssertLockedForWriting() r.lockfile.AssertLockedForWriting()
// This must be done before we write the file, because the process could be terminated
// after the file is written but before the lock file is updated.
lw, err := r.lockfile.RecordWrite()
if err != nil {
return err
}
r.lastWrite = lw
for locationIndex := 0; locationIndex < numContainerLocationIndex; locationIndex++ { for locationIndex := 0; locationIndex < numContainerLocationIndex; locationIndex++ {
location := containerLocationFromIndex(locationIndex) location := containerLocationFromIndex(locationIndex)
if location&saveLocations == 0 { if location&saveLocations == 0 {
continue continue
} }
rpath := r.jsonPath[locationIndex] rpath := r.jsonPath[locationIndex]
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(rpath), 0o700); err != nil {
return err return err
} }
subsetContainers := make([]*Container, 0, len(r.containers)) subsetContainers := make([]*Container, 0, len(r.containers))
@ -549,15 +556,10 @@ func (r *containerStore) save(saveLocations containerLocations) error {
NoSync: true, NoSync: true,
} }
} }
if err := ioutils.AtomicWriteFileWithOpts(rpath, jdata, 0600, opts); err != nil { if err := ioutils.AtomicWriteFileWithOpts(rpath, jdata, 0o600, opts); err != nil {
return err return err
} }
} }
lw, err := r.lockfile.RecordWrite()
if err != nil {
return err
}
r.lastWrite = lw
return nil return nil
} }
@ -569,12 +571,12 @@ func (r *containerStore) saveFor(modifiedContainer *Container) error {
} }
func newContainerStore(dir string, runDir string, transient bool) (rwContainerStore, error) { func newContainerStore(dir string, runDir string, transient bool) (rwContainerStore, error) {
if err := os.MkdirAll(dir, 0700); err != nil { if err := os.MkdirAll(dir, 0o700); err != nil {
return nil, err return nil, err
} }
volatileDir := dir volatileDir := dir
if transient { if transient {
if err := os.MkdirAll(runDir, 0700); err != nil { if err := os.MkdirAll(runDir, 0o700); err != nil {
return nil, err return nil, err
} }
volatileDir = runDir volatileDir = runDir
@ -926,10 +928,10 @@ func (r *containerStore) SetBigData(id, key string, data []byte) error {
if !ok { if !ok {
return ErrContainerUnknown return ErrContainerUnknown
} }
if err := os.MkdirAll(r.datadir(c.ID), 0700); err != nil { if err := os.MkdirAll(r.datadir(c.ID), 0o700); err != nil {
return err return err
} }
err := ioutils.AtomicWriteFile(r.datapath(c.ID, key), data, 0600) err := ioutils.AtomicWriteFile(r.datapath(c.ID, key), data, 0o600)
if err == nil { if err == nil {
save := false save := false
if c.BigDataSizes == nil { if c.BigDataSizes == nil {

View File

@ -64,7 +64,7 @@ var (
enableDirperm bool enableDirperm bool
) )
const defaultPerms = os.FileMode(0555) const defaultPerms = os.FileMode(0o555)
func init() { func init() {
graphdriver.MustRegister("aufs", Init) graphdriver.MustRegister("aufs", Init)
@ -87,11 +87,9 @@ type Driver struct {
// Init returns a new AUFS driver. // Init returns a new AUFS driver.
// An error is returned if AUFS is not supported. // An error is returned if AUFS is not supported.
func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) { func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) {
// Try to load the aufs kernel module // Try to load the aufs kernel module
if err := supportsAufs(); err != nil { if err := supportsAufs(); err != nil {
return nil, fmt.Errorf("kernel does not support aufs: %w", graphdriver.ErrNotSupported) return nil, fmt.Errorf("kernel does not support aufs: %w", graphdriver.ErrNotSupported)
} }
fsMagic, err := graphdriver.GetFSMagic(home) fsMagic, err := graphdriver.GetFSMagic(home)
@ -145,7 +143,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
// Create the root aufs driver dir and return // Create the root aufs driver dir and return
// if it already exists // if it already exists
// If not populate the dir structure // If not populate the dir structure
if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(home, 0o700, rootUID, rootGID); err != nil {
if os.IsExist(err) { if os.IsExist(err) {
return a, nil return a, nil
} }
@ -158,7 +156,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
// Populate the dir structure // Populate the dir structure
for _, p := range paths { for _, p := range paths {
if err := idtools.MkdirAllAs(path.Join(home, p), 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(path.Join(home, p), 0o700, rootUID, rootGID); err != nil {
return nil, err return nil, err
} }
} }
@ -251,9 +249,21 @@ func (a *Driver) Exists(id string) bool {
return true return true
} }
// List layers (not including additional image stores) // ListLayers() returns all of the layers known to the driver.
func (a *Driver) ListLayers() ([]string, error) { func (a *Driver) ListLayers() ([]string, error) {
return nil, graphdriver.ErrNotSupported diffsDir := filepath.Join(a.rootPath(), "diff")
entries, err := os.ReadDir(diffsDir)
if err != nil {
return nil, err
}
results := make([]string, 0, len(entries))
for _, entry := range entries {
if !entry.IsDir() {
continue
}
results = append(results, entry.Name())
}
return results, nil
} }
// AdditionalImageStores returns additional image stores supported by the driver // AdditionalImageStores returns additional image stores supported by the driver
@ -278,7 +288,6 @@ func (a *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts
// Create three folders for each id // Create three folders for each id
// mnt, layers, and diff // mnt, layers, and diff
func (a *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { func (a *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
if opts != nil && len(opts.StorageOpt) != 0 { if opts != nil && len(opts.StorageOpt) != 0 {
return fmt.Errorf("--storage-opt is not supported for aufs") return fmt.Errorf("--storage-opt is not supported for aufs")
} }

View File

@ -42,7 +42,7 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
const defaultPerms = os.FileMode(0555) const defaultPerms = os.FileMode(0o555)
func init() { func init() {
graphdriver.MustRegister("btrfs", Init) graphdriver.MustRegister("btrfs", Init)
@ -56,7 +56,6 @@ type btrfsOptions struct {
// Init returns a new BTRFS driver. // Init returns a new BTRFS driver.
// An error is returned if BTRFS is not supported. // An error is returned if BTRFS is not supported.
func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) { func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) {
fsMagic, err := graphdriver.GetFSMagic(home) fsMagic, err := graphdriver.GetFSMagic(home)
if err != nil { if err != nil {
return nil, err return nil, err
@ -70,7 +69,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(filepath.Join(home, "subvolumes"), 0o700, rootUID, rootGID); err != nil {
return nil, err return nil, err
} }
@ -119,7 +118,7 @@ func parseOptions(opt []string) (btrfsOptions, bool, error) {
case "btrfs.mountopt": case "btrfs.mountopt":
return options, userDiskQuota, fmt.Errorf("btrfs driver does not support mount options") return options, userDiskQuota, fmt.Errorf("btrfs driver does not support mount options")
default: default:
return options, userDiskQuota, fmt.Errorf("unknown option %s", key) return options, userDiskQuota, fmt.Errorf("unknown option %s (%q)", key, option)
} }
} }
return options, userDiskQuota, nil return options, userDiskQuota, nil
@ -127,7 +126,7 @@ func parseOptions(opt []string) (btrfsOptions, bool, error) {
// Driver contains information about the filesystem mounted. // Driver contains information about the filesystem mounted.
type Driver struct { type Driver struct {
//root of the file system // root of the file system
home string home string
uidMaps []idtools.IDMap uidMaps []idtools.IDMap
gidMaps []idtools.IDMap gidMaps []idtools.IDMap
@ -226,7 +225,7 @@ func subvolSnapshot(src, dest, name string) error {
var args C.struct_btrfs_ioctl_vol_args_v2 var args C.struct_btrfs_ioctl_vol_args_v2
args.fd = C.__s64(getDirFd(srcDir)) args.fd = C.__s64(getDirFd(srcDir))
var cs = C.CString(name) cs := C.CString(name)
C.set_name_btrfs_ioctl_vol_args_v2(&args, cs) C.set_name_btrfs_ioctl_vol_args_v2(&args, cs)
C.free(unsafe.Pointer(cs)) C.free(unsafe.Pointer(cs))
@ -479,13 +478,13 @@ func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts
// Create the filesystem with given id. // Create the filesystem with given id.
func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
quotas := path.Join(d.home, "quotas") quotas := d.quotasDir()
subvolumes := path.Join(d.home, "subvolumes") subvolumes := d.subvolumesDir()
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
if err != nil { if err != nil {
return err return err
} }
if err := idtools.MkdirAllAs(subvolumes, 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(subvolumes, 0o700, rootUID, rootGID); err != nil {
return err return err
} }
if parent == "" { if parent == "" {
@ -523,10 +522,10 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
if err := d.setStorageSize(path.Join(subvolumes, id), driver); err != nil { if err := d.setStorageSize(path.Join(subvolumes, id), driver); err != nil {
return err return err
} }
if err := idtools.MkdirAllAs(quotas, 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(quotas, 0o700, rootUID, rootGID); err != nil {
return err return err
} }
if err := os.WriteFile(path.Join(quotas, id), []byte(fmt.Sprint(driver.options.size)), 0644); err != nil { if err := os.WriteFile(path.Join(quotas, id), []byte(fmt.Sprint(driver.options.size)), 0o644); err != nil {
return err return err
} }
} }
@ -560,7 +559,7 @@ func (d *Driver) parseStorageOpt(storageOpt map[string]string, driver *Driver) e
} }
driver.options.size = uint64(size) driver.options.size = uint64(size)
default: default:
return fmt.Errorf("unknown option %s", key) return fmt.Errorf("unknown option %s (%q)", key, storageOpt)
} }
} }
@ -679,9 +678,21 @@ func (d *Driver) Exists(id string) bool {
return err == nil return err == nil
} }
// List layers (not including additional image stores) // List all of the layers known to the driver.
func (d *Driver) ListLayers() ([]string, error) { func (d *Driver) ListLayers() ([]string, error) {
return nil, graphdriver.ErrNotSupported subvolumesDir := filepath.Join(d.home, "subvolumes")
entries, err := os.ReadDir(subvolumesDir)
if err != nil {
return nil, err
}
results := make([]string, 0, len(entries))
for _, entry := range entries {
if !entry.IsDir() {
continue
}
results = append(results, entry.Name())
}
return results, nil
} }
// AdditionalImageStores returns additional image stores supported by the driver // AdditionalImageStores returns additional image stores supported by the driver

View File

@ -10,8 +10,7 @@ import (
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
) )
type platformChowner struct { type platformChowner struct{}
}
func newLChowner() *platformChowner { func newLChowner() *platformChowner {
return &platformChowner{} return &platformChowner{}

View File

@ -11,6 +11,7 @@ package copy
#endif #endif
*/ */
import "C" import "C"
import ( import (
"container/list" "container/list"
"errors" "errors"

View File

@ -53,7 +53,7 @@ func (c *RefCounter) incdec(path string, infoOp func(minfo *minfo)) int {
} }
} else if !c.checker.IsMounted(path) { } else if !c.checker.IsMounted(path) {
// if the unmount was performed outside of this process (e.g. conmon cleanup) // if the unmount was performed outside of this process (e.g. conmon cleanup)
//the ref counter would lose track of it. Check if it is still mounted. // the ref counter would lose track of it. Check if it is still mounted.
m.count = 0 m.count = 0
} }
infoOp(m) infoOp(m)

View File

@ -177,7 +177,7 @@ func writeLVMConfig(root string, cfg directLVMConfig) error {
if err != nil { if err != nil {
return fmt.Errorf("marshalling direct lvm config: %w", err) return fmt.Errorf("marshalling direct lvm config: %w", err)
} }
if err := os.WriteFile(p, b, 0600); err != nil { if err := os.WriteFile(p, b, 0o600); err != nil {
return fmt.Errorf("writing direct lvm config to file: %w", err) return fmt.Errorf("writing direct lvm config to file: %w", err)
} }
return nil return nil
@ -193,7 +193,7 @@ func setupDirectLVM(cfg directLVMConfig) error {
} }
} }
err := os.MkdirAll(lvmProfileDir, 0755) err := os.MkdirAll(lvmProfileDir, 0o755)
if err != nil { if err != nil {
return fmt.Errorf("creating lvm profile directory: %w", err) return fmt.Errorf("creating lvm profile directory: %w", err)
} }
@ -241,7 +241,7 @@ func setupDirectLVM(cfg directLVMConfig) error {
} }
profile := fmt.Sprintf("activation{\nthin_pool_autoextend_threshold=%d\nthin_pool_autoextend_percent=%d\n}", cfg.AutoExtendThreshold, cfg.AutoExtendPercent) profile := fmt.Sprintf("activation{\nthin_pool_autoextend_threshold=%d\nthin_pool_autoextend_percent=%d\n}", cfg.AutoExtendThreshold, cfg.AutoExtendPercent)
err = os.WriteFile(lvmProfileDir+"/storage-thinpool.profile", []byte(profile), 0600) err = os.WriteFile(lvmProfileDir+"/storage-thinpool.profile", []byte(profile), 0o600)
if err != nil { if err != nil {
return fmt.Errorf("writing storage thinp autoextend profile: %w", err) return fmt.Errorf("writing storage thinp autoextend profile: %w", err)
} }

View File

@ -124,7 +124,7 @@ type DeviceSet struct {
deletionWorkerTicker *time.Ticker deletionWorkerTicker *time.Ticker
uidMaps []idtools.IDMap uidMaps []idtools.IDMap
gidMaps []idtools.IDMap gidMaps []idtools.IDMap
minFreeSpacePercent uint32 //min free space percentage in thinpool minFreeSpacePercent uint32 // min free space percentage in thinpool
xfsNospaceRetries string // max retries when xfs receives ENOSPC xfsNospaceRetries string // max retries when xfs receives ENOSPC
lvmSetupConfig directLVMConfig lvmSetupConfig directLVMConfig
} }
@ -273,7 +273,7 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
if err := idtools.MkdirAllAs(dirname, 0700, uid, gid); err != nil { if err := idtools.MkdirAllAs(dirname, 0o700, uid, gid); err != nil {
return "", err return "", err
} }
@ -282,7 +282,7 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
return "", err return "", err
} }
logrus.Debugf("devmapper: Creating loopback file %s for device-manage use", filename) logrus.Debugf("devmapper: Creating loopback file %s for device-manage use", filename)
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0o600)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -293,7 +293,7 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
} }
} else { } else {
if fi.Size() < size { if fi.Size() < size {
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600) file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0o600)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -421,7 +421,6 @@ func (devices *DeviceSet) constructDeviceIDMap() {
} }
func (devices *DeviceSet) deviceFileWalkFunction(path string, name string) error { func (devices *DeviceSet) deviceFileWalkFunction(path string, name string) error {
// Skip some of the meta files which are not device files. // Skip some of the meta files which are not device files.
if strings.HasSuffix(name, ".migrated") { if strings.HasSuffix(name, ".migrated") {
logrus.Debugf("devmapper: Skipping file %s", path) logrus.Debugf("devmapper: Skipping file %s", path)
@ -458,7 +457,7 @@ func (devices *DeviceSet) loadDeviceFilesOnStart() error {
logrus.Debug("devmapper: loadDeviceFilesOnStart()") logrus.Debug("devmapper: loadDeviceFilesOnStart()")
defer logrus.Debug("devmapper: loadDeviceFilesOnStart() END") defer logrus.Debug("devmapper: loadDeviceFilesOnStart() END")
var scan = func(path string, d fs.DirEntry, err error) error { scan := func(path string, d fs.DirEntry, err error) error {
if err != nil { if err != nil {
logrus.Debugf("devmapper: Can't walk the file %s: %v", path, err) logrus.Debugf("devmapper: Can't walk the file %s: %v", path, err)
return nil return nil
@ -1001,6 +1000,10 @@ func (devices *DeviceSet) verifyBaseDeviceUUIDFS(baseInfo *devInfo) error {
devices.Lock() devices.Lock()
defer devices.Unlock() defer devices.Unlock()
if devices.filesystem == "" {
devices.filesystem = determineDefaultFS()
}
if err := devices.activateDeviceIfNeeded(baseInfo, false); err != nil { if err := devices.activateDeviceIfNeeded(baseInfo, false); err != nil {
return err return err
} }
@ -1152,7 +1155,6 @@ func (devices *DeviceSet) setupVerifyBaseImageUUIDFS(baseInfo *devInfo) error {
} }
func (devices *DeviceSet) checkGrowBaseDeviceFS(info *devInfo) error { func (devices *DeviceSet) checkGrowBaseDeviceFS(info *devInfo) error {
if !userBaseSize { if !userBaseSize {
return nil return nil
} }
@ -1191,7 +1193,7 @@ func (devices *DeviceSet) growFS(info *devInfo) error {
fsMountPoint := "/run/containers/storage/mnt" fsMountPoint := "/run/containers/storage/mnt"
if _, err := os.Stat(fsMountPoint); os.IsNotExist(err) { if _, err := os.Stat(fsMountPoint); os.IsNotExist(err) {
if err := os.MkdirAll(fsMountPoint, 0700); err != nil { if err := os.MkdirAll(fsMountPoint, 0o700); err != nil {
return err return err
} }
defer os.RemoveAll(fsMountPoint) defer os.RemoveAll(fsMountPoint)
@ -1657,7 +1659,6 @@ func (devices *DeviceSet) loadThinPoolLoopBackInfo() error {
} }
func (devices *DeviceSet) enableDeferredRemovalDeletion() error { func (devices *DeviceSet) enableDeferredRemovalDeletion() error {
// If user asked for deferred removal then check both libdm library // If user asked for deferred removal then check both libdm library
// and kernel driver support deferred removal otherwise error out. // and kernel driver support deferred removal otherwise error out.
if enableDeferredRemoval { if enableDeferredRemoval {
@ -1695,16 +1696,19 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
} }
} }
//create the root dir of the devmapper driver ownership to match this // create the root dir of the devmapper driver ownership to match this
//daemon's remapped root uid/gid so containers can start properly // daemon's remapped root uid/gid so containers can start properly
uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps) uid, gid, err := idtools.GetRootUIDGID(devices.uidMaps, devices.gidMaps)
if err != nil { if err != nil {
return err return err
} }
if err := idtools.MkdirAs(devices.root, 0700, uid, gid); err != nil { if err := idtools.MkdirAs(devices.root, 0o700, uid, gid); err != nil {
return err return err
} }
if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil { if err := os.MkdirAll(devices.metadataDir(), 0o700); err != nil {
return err
}
if err := idtools.MkdirAs(filepath.Join(devices.root, "mnt"), 0o700, uid, gid); err != nil && !errors.Is(err, os.ErrExist) {
return err return err
} }
@ -1811,7 +1815,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
devices.dataLoopFile = data devices.dataLoopFile = data
devices.dataDevice = dataFile.Name() devices.dataDevice = dataFile.Name()
} else { } else {
dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0600) dataFile, err = os.OpenFile(devices.dataDevice, os.O_RDWR, 0o600)
if err != nil { if err != nil {
return err return err
} }
@ -1844,7 +1848,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
devices.metadataLoopFile = metadata devices.metadataLoopFile = metadata
devices.metadataDevice = metadataFile.Name() devices.metadataDevice = metadataFile.Name()
} else { } else {
metadataFile, err = os.OpenFile(devices.metadataDevice, os.O_RDWR, 0600) metadataFile, err = os.OpenFile(devices.metadataDevice, os.O_RDWR, 0o600)
if err != nil { if err != nil {
return err return err
} }
@ -1966,7 +1970,6 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string, storageOpt map[string
} }
func (devices *DeviceSet) parseStorageOpt(storageOpt map[string]string) (uint64, error) { func (devices *DeviceSet) parseStorageOpt(storageOpt map[string]string) (uint64, error) {
// Read size to change the block device size per container. // Read size to change the block device size per container.
for key, val := range storageOpt { for key, val := range storageOpt {
key := strings.ToLower(key) key := strings.ToLower(key)
@ -2317,7 +2320,7 @@ func (devices *DeviceSet) Shutdown(home string) error {
info.lock.Lock() info.lock.Lock()
devices.Lock() devices.Lock()
if err := devices.deactivateDevice(info); err != nil { if err := devices.deactivateDevice(info); err != nil {
logrus.Debugf("devmapper: Shutdown deactivate base , error: %s", err) logrus.Debugf("devmapper: Shutdown deactivate base, error: %s", err)
} }
devices.Unlock() devices.Unlock()
info.lock.Unlock() info.lock.Unlock()
@ -2326,7 +2329,7 @@ func (devices *DeviceSet) Shutdown(home string) error {
devices.Lock() devices.Lock()
if devices.thinPoolDevice == "" { if devices.thinPoolDevice == "" {
if err := devices.deactivatePool(); err != nil { if err := devices.deactivatePool(); err != nil {
logrus.Debugf("devmapper: Shutdown deactivate pool , error: %s", err) logrus.Debugf("devmapper: Shutdown deactivate pool, error: %s", err)
} }
} }
devices.Unlock() devices.Unlock()
@ -2483,6 +2486,26 @@ func (devices *DeviceSet) List() []string {
return ids return ids
} }
// ListLayers returns a list of device IDs, omitting the ""/"base" device and
// any which have been marked as deleted.
func (devices *DeviceSet) ListLayers() ([]string, error) {
if err := devices.cleanupDeletedDevices(); err != nil {
return nil, err
}
devices.Lock()
defer devices.Unlock()
ids := make([]string, 0, len(devices.Devices))
for k, d := range devices.Devices {
if k == "" || d.Deleted {
continue
}
ids = append(ids, k)
}
return ids, nil
}
func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) { func (devices *DeviceSet) deviceStatus(devName string) (sizeInSectors, mappedSectors, highestMappedSector uint64, err error) {
var params string var params string
_, sizeInSectors, _, params, err = devicemapper.GetStatus(devName) _, sizeInSectors, _, params, err = devicemapper.GetStatus(devName)
@ -2520,7 +2543,6 @@ func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) {
} }
sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName()) sizeInSectors, mappedSectors, highestMappedSector, err := devices.deviceStatus(info.DevName())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -20,7 +20,7 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
const defaultPerms = os.FileMode(0555) const defaultPerms = os.FileMode(0o555)
func init() { func init() {
graphdriver.MustRegister("devicemapper", Init) graphdriver.MustRegister("devicemapper", Init)
@ -55,7 +55,6 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()), ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
locker: locker.New(), locker: locker.New(),
} }
return graphdriver.NewNaiveDiffDriver(d, graphdriver.NewNaiveLayerIDMapUpdater(d)), nil return graphdriver.NewNaiveDiffDriver(d, graphdriver.NewNaiveLayerIDMapUpdater(d)), nil
} }
@ -103,7 +102,6 @@ func (d *Driver) Status() [][2]string {
// Metadata returns a map of information about the device. // Metadata returns a map of information about the device.
func (d *Driver) Metadata(id string) (map[string]string, error) { func (d *Driver) Metadata(id string) (map[string]string, error) {
m, err := d.DeviceSet.exportDeviceMetadata(id) m, err := d.DeviceSet.exportDeviceMetadata(id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -202,11 +200,11 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
} }
// Create the target directories if they don't exist // Create the target directories if they don't exist
if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0755, uid, gid); err != nil { if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0o755, uid, gid); err != nil {
d.ctr.Decrement(mp) d.ctr.Decrement(mp)
return "", err return "", err
} }
if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) { if err := idtools.MkdirAs(mp, 0o755, uid, gid); err != nil && !os.IsExist(err) {
d.ctr.Decrement(mp) d.ctr.Decrement(mp)
return "", err return "", err
} }
@ -227,7 +225,7 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
if _, err := os.Stat(idFile); err != nil && os.IsNotExist(err) { if _, err := os.Stat(idFile); err != nil && os.IsNotExist(err) {
// Create an "id" file with the container/image id in it to help reconstruct this in case // Create an "id" file with the container/image id in it to help reconstruct this in case
// of later problems // of later problems
if err := os.WriteFile(idFile, []byte(id), 0600); err != nil { if err := os.WriteFile(idFile, []byte(id), 0o600); err != nil {
d.ctr.Decrement(mp) d.ctr.Decrement(mp)
d.DeviceSet.UnmountDevice(id, mp) d.DeviceSet.UnmountDevice(id, mp)
return "", err return "", err
@ -267,11 +265,6 @@ func (d *Driver) Exists(id string) bool {
return d.DeviceSet.HasDevice(id) return d.DeviceSet.HasDevice(id)
} }
// List layers (not including additional image stores)
func (d *Driver) ListLayers() ([]string, error) {
return nil, graphdriver.ErrNotSupported
}
// AdditionalImageStores returns additional image stores supported by the driver // AdditionalImageStores returns additional image stores supported by the driver
func (d *Driver) AdditionalImageStores() []string { func (d *Driver) AdditionalImageStores() []string {
return nil return nil

View File

@ -111,6 +111,10 @@ type ProtoDriver interface {
Exists(id string) bool Exists(id string) bool
// Returns a list of layer ids that exist on this driver (does not include // Returns a list of layer ids that exist on this driver (does not include
// additional storage layers). Not supported by all backends. // additional storage layers). Not supported by all backends.
// If the driver requires that layers be removed in a particular order,
// usually due to parent-child relationships that it cares about, The
// list should be sorted well enough so that if all layers need to be
// removed, they can be removed in the order in which they're returned.
ListLayers() ([]string, error) ListLayers() ([]string, error)
// Status returns a set of key-value pairs which give low // Status returns a set of key-value pairs which give low
// level diagnostic status about this driver. // level diagnostic status about this driver.
@ -322,6 +326,7 @@ func getBuiltinDriver(name, home string, options Options) (Driver, error) {
type Options struct { type Options struct {
Root string Root string
RunRoot string RunRoot string
ImageStore string
DriverPriority []string DriverPriority []string
DriverOptions []string DriverOptions []string
UIDMaps []idtools.IDMap UIDMaps []idtools.IDMap
@ -337,12 +342,12 @@ func New(name string, config Options) (Driver, error) {
} }
// Guess for prior driver // Guess for prior driver
driversMap := scanPriorDrivers(config.Root) driversMap := ScanPriorDrivers(config.Root)
// use the supplied priority list unless it is empty // use the supplied priority list unless it is empty
prioList := config.DriverPriority prioList := config.DriverPriority
if len(prioList) == 0 { if len(prioList) == 0 {
prioList = priority prioList = Priority
} }
for _, name := range prioList { for _, name := range prioList {
@ -414,12 +419,12 @@ func isDriverNotSupported(err error) bool {
} }
// scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers // scanPriorDrivers returns an un-ordered scan of directories of prior storage drivers
func scanPriorDrivers(root string) map[string]bool { func ScanPriorDrivers(root string) map[string]bool {
driversMap := make(map[string]bool) driversMap := make(map[string]bool)
for driver := range drivers { for driver := range drivers {
p := filepath.Join(root, driver) p := filepath.Join(root, driver)
if _, err := os.Stat(p); err == nil && driver != "vfs" { if _, err := os.Stat(p); err == nil {
driversMap[driver] = true driversMap[driver] = true
} }
} }

View File

@ -1,11 +1,9 @@
package graphdriver package graphdriver
var ( // Slice of drivers that should be used in order
// Slice of drivers that should be used in order var Priority = []string{
priority = []string{
"vfs", "vfs",
} }
)
// GetFSMagic returns the filesystem id given the path. // GetFSMagic returns the filesystem id given the path.
func GetFSMagic(rootpath string) (FsMagic, error) { func GetFSMagic(rootpath string) (FsMagic, error) {

View File

@ -13,7 +13,7 @@ const (
var ( var (
// Slice of drivers that should be used in an order // Slice of drivers that should be used in an order
priority = []string{ Priority = []string{
"zfs", "zfs",
"vfs", "vfs",
} }
@ -31,8 +31,7 @@ func NewDefaultChecker() Checker {
return &defaultChecker{} return &defaultChecker{}
} }
type defaultChecker struct { type defaultChecker struct{}
}
func (c *defaultChecker) IsMounted(path string) bool { func (c *defaultChecker) IsMounted(path string) bool {
m, _ := mount.Mounted(path) m, _ := mount.Mounted(path)

View File

@ -90,7 +90,7 @@ const (
var ( var (
// Slice of drivers that should be used in an order // Slice of drivers that should be used in an order
priority = []string{ Priority = []string{
"overlay", "overlay",
// We don't support devicemapper without configuration // We don't support devicemapper without configuration
// "devicemapper", // "devicemapper",
@ -161,8 +161,7 @@ func NewDefaultChecker() Checker {
return &defaultChecker{} return &defaultChecker{}
} }
type defaultChecker struct { type defaultChecker struct{}
}
func (c *defaultChecker) IsMounted(path string) bool { func (c *defaultChecker) IsMounted(path string) bool {
m, _ := mount.Mounted(path) m, _ := mount.Mounted(path)

View File

@ -16,6 +16,7 @@ static inline struct statvfs *getstatfs(char *s) {
} }
*/ */
import "C" import "C"
import ( import (
"path/filepath" "path/filepath"
"unsafe" "unsafe"
@ -31,7 +32,7 @@ const (
var ( var (
// Slice of drivers that should be used in an order // Slice of drivers that should be used in an order
priority = []string{ Priority = []string{
"zfs", "zfs",
} }
@ -69,8 +70,7 @@ func NewDefaultChecker() Checker {
return &defaultChecker{} return &defaultChecker{}
} }
type defaultChecker struct { type defaultChecker struct{}
}
func (c *defaultChecker) IsMounted(path string) bool { func (c *defaultChecker) IsMounted(path string) bool {
m, _ := mount.Mounted(path) m, _ := mount.Mounted(path)
@ -80,7 +80,6 @@ func (c *defaultChecker) IsMounted(path string) bool {
// Mounted checks if the given path is mounted as the fs type // Mounted checks if the given path is mounted as the fs type
// Solaris supports only ZFS for now // Solaris supports only ZFS for now
func Mounted(fsType FsMagic, mountPath string) (bool, error) { func Mounted(fsType FsMagic, mountPath string) (bool, error) {
cs := C.CString(filepath.Dir(mountPath)) cs := C.CString(filepath.Dir(mountPath))
defer C.free(unsafe.Pointer(cs)) defer C.free(unsafe.Pointer(cs))
buf := C.getstatfs(cs) buf := C.getstatfs(cs)

View File

@ -3,12 +3,10 @@
package graphdriver package graphdriver
var ( // Slice of drivers that should be used in an order
// Slice of drivers that should be used in an order var Priority = []string{
priority = []string{
"unsupported", "unsupported",
} }
)
// GetFSMagic returns the filesystem id given the path. // GetFSMagic returns the filesystem id given the path.
func GetFSMagic(rootpath string) (FsMagic, error) { func GetFSMagic(rootpath string) (FsMagic, error) {

View File

@ -1,11 +1,9 @@
package graphdriver package graphdriver
var ( // Slice of drivers that should be used in order
// Slice of drivers that should be used in order var Priority = []string{
priority = []string{
"windowsfilter", "windowsfilter",
} }
)
// GetFSMagic returns the filesystem id given the path. // GetFSMagic returns the filesystem id given the path.
func GetFSMagic(rootpath string) (FsMagic, error) { func GetFSMagic(rootpath string) (FsMagic, error) {

View File

@ -14,11 +14,9 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
var ( // ApplyUncompressedLayer defines the unpack method used by the graph
// ApplyUncompressedLayer defines the unpack method used by the graph // driver.
// driver. var ApplyUncompressedLayer = chrootarchive.ApplyUncompressedLayer
ApplyUncompressedLayer = chrootarchive.ApplyUncompressedLayer
)
// NaiveDiffDriver takes a ProtoDriver and adds the // NaiveDiffDriver takes a ProtoDriver and adds the
// capability of the Diffing methods which it may or may not // capability of the Diffing methods which it may or may not
@ -173,7 +171,7 @@ func (gdw *NaiveDiffDriver) ApplyDiff(id, parent string, options ApplyDiffOpts)
} }
defer driverPut(driver, id, &err) defer driverPut(driver, id, &err)
defaultForceMask := os.FileMode(0700) defaultForceMask := os.FileMode(0o700)
var forceMask *os.FileMode // = nil var forceMask *os.FileMode // = nil
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
forceMask = &defaultForceMask forceMask = &defaultForceMask

View File

@ -38,22 +38,22 @@ func doesSupportNativeDiff(d, mountOpts string) error {
}() }()
// Make directories l1/d, l1/d1, l2/d, l3, work, merged // Make directories l1/d, l1/d1, l2/d, l3, work, merged
if err := os.MkdirAll(filepath.Join(td, "l1", "d"), 0755); err != nil { if err := os.MkdirAll(filepath.Join(td, "l1", "d"), 0o755); err != nil {
return err return err
} }
if err := os.MkdirAll(filepath.Join(td, "l1", "d1"), 0755); err != nil { if err := os.MkdirAll(filepath.Join(td, "l1", "d1"), 0o755); err != nil {
return err return err
} }
if err := os.MkdirAll(filepath.Join(td, "l2", "d"), 0755); err != nil { if err := os.MkdirAll(filepath.Join(td, "l2", "d"), 0o755); err != nil {
return err return err
} }
if err := os.Mkdir(filepath.Join(td, "l3"), 0755); err != nil { if err := os.Mkdir(filepath.Join(td, "l3"), 0o755); err != nil {
return err return err
} }
if err := os.Mkdir(filepath.Join(td, "work"), 0755); err != nil { if err := os.Mkdir(filepath.Join(td, "work"), 0o755); err != nil {
return err return err
} }
if err := os.Mkdir(filepath.Join(td, "merged"), 0755); err != nil { if err := os.Mkdir(filepath.Join(td, "merged"), 0o755); err != nil {
return err return err
} }
@ -82,7 +82,7 @@ func doesSupportNativeDiff(d, mountOpts string) error {
}() }()
// Touch file in d to force copy up of opaque directory "d" from "l2" to "l3" // Touch file in d to force copy up of opaque directory "d" from "l2" to "l3"
if err := os.WriteFile(filepath.Join(td, "merged", "d", "f"), []byte{}, 0644); err != nil { if err := os.WriteFile(filepath.Join(td, "merged", "d", "f"), []byte{}, 0o644); err != nil {
return fmt.Errorf("failed to write to merged directory: %w", err) return fmt.Errorf("failed to write to merged directory: %w", err)
} }
@ -132,19 +132,19 @@ func doesMetacopy(d, mountOpts string) (bool, error) {
}() }()
// Make directories l1, l2, work, merged // Make directories l1, l2, work, merged
if err := os.MkdirAll(filepath.Join(td, "l1"), 0755); err != nil { if err := os.MkdirAll(filepath.Join(td, "l1"), 0o755); err != nil {
return false, err return false, err
} }
if err := ioutils.AtomicWriteFile(filepath.Join(td, "l1", "f"), []byte{0xff}, 0700); err != nil { if err := ioutils.AtomicWriteFile(filepath.Join(td, "l1", "f"), []byte{0xff}, 0o700); err != nil {
return false, err return false, err
} }
if err := os.MkdirAll(filepath.Join(td, "l2"), 0755); err != nil { if err := os.MkdirAll(filepath.Join(td, "l2"), 0o755); err != nil {
return false, err return false, err
} }
if err := os.Mkdir(filepath.Join(td, "work"), 0755); err != nil { if err := os.Mkdir(filepath.Join(td, "work"), 0o755); err != nil {
return false, err return false, err
} }
if err := os.Mkdir(filepath.Join(td, "merged"), 0755); err != nil { if err := os.Mkdir(filepath.Join(td, "merged"), 0o755); err != nil {
return false, err return false, err
} }
// Mount using the mandatory options and configured options // Mount using the mandatory options and configured options
@ -170,7 +170,7 @@ func doesMetacopy(d, mountOpts string) (bool, error) {
}() }()
// Make a change that only impacts the inode, and check if the pulled-up copy is marked // Make a change that only impacts the inode, and check if the pulled-up copy is marked
// as a metadata-only copy // as a metadata-only copy
if err := os.Chmod(filepath.Join(td, "merged", "f"), 0600); err != nil { if err := os.Chmod(filepath.Join(td, "merged", "f"), 0o600); err != nil {
return false, fmt.Errorf("changing permissions on file for metacopy check: %w", err) return false, fmt.Errorf("changing permissions on file for metacopy check: %w", err)
} }
metacopy, err := system.Lgetxattr(filepath.Join(td, "l2", "f"), archive.GetOverlayXattrName("metacopy")) metacopy, err := system.Lgetxattr(filepath.Join(td, "l2", "f"), archive.GetOverlayXattrName("metacopy"))
@ -196,20 +196,23 @@ func doesVolatile(d string) (bool, error) {
} }
}() }()
if err := os.MkdirAll(filepath.Join(td, "lower"), 0755); err != nil { if err := os.MkdirAll(filepath.Join(td, "lower"), 0o755); err != nil {
return false, err return false, err
} }
if err := os.MkdirAll(filepath.Join(td, "upper"), 0755); err != nil { if err := os.MkdirAll(filepath.Join(td, "upper"), 0o755); err != nil {
return false, err return false, err
} }
if err := os.Mkdir(filepath.Join(td, "work"), 0755); err != nil { if err := os.Mkdir(filepath.Join(td, "work"), 0o755); err != nil {
return false, err return false, err
} }
if err := os.Mkdir(filepath.Join(td, "merged"), 0755); err != nil { if err := os.Mkdir(filepath.Join(td, "merged"), 0o755); err != nil {
return false, err return false, err
} }
// Mount using the mandatory options and configured options // Mount using the mandatory options and configured options
opts := fmt.Sprintf("volatile,lowerdir=%s,upperdir=%s,workdir=%s", path.Join(td, "lower"), path.Join(td, "upper"), path.Join(td, "work")) opts := fmt.Sprintf("volatile,lowerdir=%s,upperdir=%s,workdir=%s", path.Join(td, "lower"), path.Join(td, "upper"), path.Join(td, "work"))
if unshare.IsRootless() {
opts = fmt.Sprintf("%s,userxattr", opts)
}
if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil { if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil {
return false, fmt.Errorf("failed to mount overlay for volatile check: %w", err) return false, fmt.Errorf("failed to mount overlay for volatile check: %w", err)
} }
@ -238,11 +241,11 @@ func supportsIdmappedLowerLayers(home string) (bool, error) {
upperDir := filepath.Join(layerDir, "upper") upperDir := filepath.Join(layerDir, "upper")
workDir := filepath.Join(layerDir, "work") workDir := filepath.Join(layerDir, "work")
_ = idtools.MkdirAs(mergedDir, 0700, 0, 0) _ = idtools.MkdirAs(mergedDir, 0o700, 0, 0)
_ = idtools.MkdirAs(lowerDir, 0700, 0, 0) _ = idtools.MkdirAs(lowerDir, 0o700, 0, 0)
_ = idtools.MkdirAs(lowerMappedDir, 0700, 0, 0) _ = idtools.MkdirAs(lowerMappedDir, 0o700, 0, 0)
_ = idtools.MkdirAs(upperDir, 0700, 0, 0) _ = idtools.MkdirAs(upperDir, 0o700, 0, 0)
_ = idtools.MkdirAs(workDir, 0700, 0, 0) _ = idtools.MkdirAs(workDir, 0o700, 0, 0)
mapping := []idtools.IDMap{ mapping := []idtools.IDMap{
{ {

View File

@ -55,7 +55,7 @@ func mountOverlayFrom(dir, device, target, mType string, flags uintptr, label st
w.Close() w.Close()
return fmt.Errorf("mountfrom error on re-exec cmd: %w", err) return fmt.Errorf("mountfrom error on re-exec cmd: %w", err)
} }
//write the options to the pipe for the untar exec to read // write the options to the pipe for the untar exec to read
if err := json.NewEncoder(w).Encode(options); err != nil { if err := json.NewEncoder(w).Encode(options); err != nil {
w.Close() w.Close()
return fmt.Errorf("mountfrom json encode to pipe failed: %w", err) return fmt.Errorf("mountfrom json encode to pipe failed: %w", err)

View File

@ -29,7 +29,6 @@ import (
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/mount" "github.com/containers/storage/pkg/mount"
"github.com/containers/storage/pkg/parsers" "github.com/containers/storage/pkg/parsers"
"github.com/containers/storage/pkg/stringid"
"github.com/containers/storage/pkg/system" "github.com/containers/storage/pkg/system"
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
units "github.com/docker/go-units" units "github.com/docker/go-units"
@ -41,13 +40,13 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
var ( // untar defines the untar method
// untar defines the untar method var untar = chrootarchive.UntarUncompressed
untar = chrootarchive.UntarUncompressed
)
const ( const (
defaultPerms = os.FileMode(0555) defaultPerms = os.FileMode(0o555)
selinuxLabelTest = "system_u:object_r:container_file_t:s0"
mountProgramFlagFile = ".has-mount-program"
) )
// This backend uses the overlay union filesystem for containers // This backend uses the overlay union filesystem for containers
@ -79,6 +78,7 @@ const (
const ( const (
linkDir = "l" linkDir = "l"
stagingDir = "staging"
lowerFile = "lower" lowerFile = "lower"
maxDepth = 500 maxDepth = 500
@ -110,6 +110,7 @@ type Driver struct {
name string name string
home string home string
runhome string runhome string
imageStore string
uidMaps []idtools.IDMap uidMaps []idtools.IDMap
gidMaps []idtools.IDMap gidMaps []idtools.IDMap
ctr *graphdriver.RefCounter ctr *graphdriver.RefCounter
@ -124,7 +125,6 @@ type Driver struct {
} }
type additionalLayerStore struct { type additionalLayerStore struct {
// path is the directory where this store is available on the host. // path is the directory where this store is available on the host.
path string path string
@ -175,11 +175,11 @@ func hasVolatileOption(opts []string) bool {
} }
func getMountProgramFlagFile(path string) string { func getMountProgramFlagFile(path string) string {
return filepath.Join(path, ".has-mount-program") return filepath.Join(path, mountProgramFlagFile)
} }
func checkSupportVolatile(home, runhome string) (bool, error) { func checkSupportVolatile(home, runhome string) (bool, error) {
feature := fmt.Sprintf("volatile") const feature = "volatile"
volatileCacheResult, _, err := cachedFeatureCheck(runhome, feature) volatileCacheResult, _, err := cachedFeatureCheck(runhome, feature)
var usingVolatile bool var usingVolatile bool
if err == nil { if err == nil {
@ -200,6 +200,8 @@ func checkSupportVolatile(home, runhome string) (bool, error) {
if err = cachedFeatureRecord(runhome, feature, usingVolatile, ""); err != nil { if err = cachedFeatureRecord(runhome, feature, usingVolatile, ""); err != nil {
return false, fmt.Errorf("recording volatile-being-used status: %w", err) return false, fmt.Errorf("recording volatile-being-used status: %w", err)
} }
} else {
usingVolatile = false
} }
} }
return usingVolatile, nil return usingVolatile, nil
@ -303,6 +305,16 @@ func isNetworkFileSystem(fsMagic graphdriver.FsMagic) bool {
// If overlay filesystem is not supported on the host, a wrapped graphdriver.ErrNotSupported is returned as error. // If overlay filesystem is not supported on the host, a wrapped graphdriver.ErrNotSupported is returned as error.
// If an overlay filesystem is not supported over an existing filesystem then a wrapped graphdriver.ErrIncompatibleFS is returned. // If an overlay filesystem is not supported over an existing filesystem then a wrapped graphdriver.ErrIncompatibleFS is returned.
func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) { func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) {
// If custom --imagestore is selected never
// ditch the original graphRoot, instead add it as
// additionalImageStore so its images can still be
// read and used.
if options.ImageStore != "" {
graphRootAsAdditionalStore := fmt.Sprintf("AdditionalImageStore=%s", options.ImageStore)
options.DriverOptions = append(options.DriverOptions, graphRootAsAdditionalStore)
// complete base name with driver name included
options.ImageStore = filepath.Join(options.ImageStore, "overlay")
}
opts, err := parseOptions(options.DriverOptions) opts, err := parseOptions(options.DriverOptions)
if err != nil { if err != nil {
return nil, err return nil, err
@ -325,11 +337,17 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
} }
// Create the driver home dir // Create the driver home dir
if err := idtools.MkdirAllAs(path.Join(home, linkDir), 0755, 0, 0); err != nil { if err := idtools.MkdirAllAs(path.Join(home, linkDir), 0o755, 0, 0); err != nil {
return nil, err return nil, err
} }
if err := idtools.MkdirAllAs(runhome, 0700, rootUID, rootGID); err != nil { if options.ImageStore != "" {
if err := idtools.MkdirAllAs(path.Join(options.ImageStore, linkDir), 0o755, 0, 0); err != nil {
return nil, err
}
}
if err := idtools.MkdirAllAs(runhome, 0o700, rootUID, rootGID); err != nil {
return nil, err return nil, err
} }
@ -345,12 +363,12 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
if opts.mountProgram != "" { if opts.mountProgram != "" {
if unshare.IsRootless() && isNetworkFileSystem(fsMagic) && opts.forceMask == nil { if unshare.IsRootless() && isNetworkFileSystem(fsMagic) && opts.forceMask == nil {
m := os.FileMode(0700) m := os.FileMode(0o700)
opts.forceMask = &m opts.forceMask = &m
logrus.Warnf("Network file system detected as backing store. Enforcing overlay option `force_mask=\"%o\"`. Add it to storage.conf to silence this warning", m) logrus.Warnf("Network file system detected as backing store. Enforcing overlay option `force_mask=\"%o\"`. Add it to storage.conf to silence this warning", m)
} }
if err := os.WriteFile(getMountProgramFlagFile(home), []byte("true"), 0600); err != nil { if err := os.WriteFile(getMountProgramFlagFile(home), []byte("true"), 0o600); err != nil {
return nil, err return nil, err
} }
} else { } else {
@ -420,6 +438,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
d := &Driver{ d := &Driver{
name: "overlay", name: "overlay",
home: home, home: home,
imageStore: options.ImageStore,
runhome: runhome, runhome: runhome,
uidMaps: options.UIDMaps, uidMaps: options.UIDMaps,
gidMaps: options.GIDMaps, gidMaps: options.GIDMaps,
@ -560,9 +579,9 @@ func parseOptions(options []string) (*overlayOptions, error) {
var mask int64 var mask int64
switch val { switch val {
case "shared": case "shared":
mask = 0755 mask = 0o755
case "private": case "private":
mask = 0700 mask = 0o700
default: default:
mask, err = strconv.ParseInt(val, 8, 32) mask, err = strconv.ParseInt(val, 8, 32)
if err != nil { if err != nil {
@ -627,7 +646,7 @@ func SupportsNativeOverlay(home, runhome string) (bool, error) {
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return false, err return false, err
} }
if err := os.WriteFile(getMountProgramFlagFile(home), []byte(fmt.Sprintf("%t", needsMountProgram)), 0600); err != nil && !os.IsNotExist(err) { if err := os.WriteFile(getMountProgramFlagFile(home), []byte(fmt.Sprintf("%t", needsMountProgram)), 0o600); err != nil && !os.IsNotExist(err) {
return false, err return false, err
} }
if needsMountProgram { if needsMountProgram {
@ -640,7 +659,7 @@ func SupportsNativeOverlay(home, runhome string) (bool, error) {
for _, dir := range []string{home, runhome} { for _, dir := range []string{home, runhome} {
if _, err := os.Stat(dir); err != nil { if _, err := os.Stat(dir); err != nil {
_ = idtools.MkdirAllAs(dir, 0700, 0, 0) _ = idtools.MkdirAllAs(dir, 0o700, 0, 0)
} }
} }
@ -700,12 +719,12 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI
_ = os.RemoveAll(layerDir) _ = os.RemoveAll(layerDir)
_ = os.Remove(home) _ = os.Remove(home)
}() }()
_ = idtools.MkdirAs(mergedDir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(mergedDir, 0o700, rootUID, rootGID)
_ = idtools.MkdirAs(lower1Dir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(lower1Dir, 0o700, rootUID, rootGID)
_ = idtools.MkdirAs(lower2Dir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(lower2Dir, 0o700, rootUID, rootGID)
_ = idtools.MkdirAs(lower2Subdir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(lower2Subdir, 0o700, rootUID, rootGID)
_ = idtools.MkdirAs(upperDir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(upperDir, 0o700, rootUID, rootGID)
_ = idtools.MkdirAs(workDir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(workDir, 0o700, rootUID, rootGID)
f, err := os.Create(lower2SubdirFile) f, err := os.Create(lower2SubdirFile)
if err != nil { if err != nil {
logrus.Debugf("Unable to create test file: %v", err) logrus.Debugf("Unable to create test file: %v", err)
@ -723,7 +742,7 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI
if unshare.IsRootless() { if unshare.IsRootless() {
flags = fmt.Sprintf("%s,userxattr", flags) flags = fmt.Sprintf("%s,userxattr", flags)
} }
if err := syscall.Mknod(filepath.Join(upperDir, "whiteout"), syscall.S_IFCHR|0600, int(unix.Mkdev(0, 0))); err != nil { if err := syscall.Mknod(filepath.Join(upperDir, "whiteout"), syscall.S_IFCHR|0o600, int(unix.Mkdev(0, 0))); err != nil {
logrus.Debugf("Unable to create kernel-style whiteout: %v", err) logrus.Debugf("Unable to create kernel-style whiteout: %v", err)
return supportsDType, fmt.Errorf("unable to create kernel-style whiteout: %w", err) return supportsDType, fmt.Errorf("unable to create kernel-style whiteout: %w", err)
} }
@ -806,15 +825,22 @@ func (d *Driver) Status() [][2]string {
// Metadata returns meta data about the overlay driver such as // Metadata returns meta data about the overlay driver such as
// LowerDir, UpperDir, WorkDir and MergeDir used to store data. // LowerDir, UpperDir, WorkDir and MergeDir used to store data.
func (d *Driver) Metadata(id string) (map[string]string, error) { func (d *Driver) Metadata(id string) (map[string]string, error) {
dir := d.dir(id) dir, imagestore, _ := d.dir2(id)
if _, err := os.Stat(dir); err != nil { if _, err := os.Stat(dir); err != nil {
return nil, err return nil, err
} }
workDirBase := dir
if imagestore != "" {
if _, err := os.Stat(dir); err != nil {
return nil, err
}
workDirBase = imagestore
}
metadata := map[string]string{ metadata := map[string]string{
"WorkDir": path.Join(dir, "work"), "WorkDir": path.Join(workDirBase, "work"),
"MergedDir": path.Join(dir, "merged"), "MergedDir": path.Join(workDirBase, "merged"),
"UpperDir": path.Join(dir, "diff"), "UpperDir": path.Join(workDirBase, "diff"),
} }
lowerDirs, err := d.getLowerDirs(id) lowerDirs, err := d.getLowerDirs(id)
@ -929,7 +955,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
} }
func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disableQuota bool) (retErr error) { func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disableQuota bool) (retErr error) {
dir := d.dir(id) dir, imageStore, _ := d.dir2(id)
uidMaps := d.uidMaps uidMaps := d.uidMaps
gidMaps := d.gidMaps gidMaps := d.gidMaps
@ -940,7 +966,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable
} }
// Make the link directory if it does not exist // Make the link directory if it does not exist
if err := idtools.MkdirAllAs(path.Join(d.home, linkDir), 0755, 0, 0); err != nil { if err := idtools.MkdirAllAs(path.Join(d.home, linkDir), 0o755, 0, 0); err != nil {
return err return err
} }
@ -954,11 +980,22 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable
GID: rootGID, GID: rootGID,
} }
if err := idtools.MkdirAllAndChownNew(path.Dir(dir), 0755, idPair); err != nil { if err := idtools.MkdirAllAndChownNew(path.Dir(dir), 0o755, idPair); err != nil {
return err return err
} }
workDirBase := dir
if imageStore != "" {
workDirBase = imageStore
if err := idtools.MkdirAllAndChownNew(path.Dir(imageStore), 0o755, idPair); err != nil {
return err
}
}
if parent != "" { if parent != "" {
st, err := system.Stat(d.dir(parent)) parentBase, parentImageStore, _ := d.dir2(parent)
if parentImageStore != "" {
parentBase = parentImageStore
}
st, err := system.Stat(filepath.Join(parentBase, "diff"))
if err != nil { if err != nil {
return err return err
} }
@ -975,9 +1012,14 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable
} }
} }
if err := idtools.MkdirAllAndChownNew(dir, 0700, idPair); err != nil { if err := idtools.MkdirAllAndChownNew(dir, 0o700, idPair); err != nil {
return err return err
} }
if imageStore != "" {
if err := idtools.MkdirAllAndChownNew(imageStore, 0o700, idPair); err != nil {
return err
}
}
defer func() { defer func() {
// Clean up on failure // Clean up on failure
@ -985,6 +1027,11 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable
if err2 := os.RemoveAll(dir); err2 != nil { if err2 := os.RemoveAll(dir); err2 != nil {
logrus.Errorf("While recovering from a failure creating a layer, error deleting %#v: %v", dir, err2) logrus.Errorf("While recovering from a failure creating a layer, error deleting %#v: %v", dir, err2)
} }
if imageStore != "" {
if err2 := os.RemoveAll(workDirBase); err2 != nil {
logrus.Errorf("While recovering from a failure creating a layer, error deleting %#v: %v", dir, err2)
}
}
} }
}() }()
@ -1007,44 +1054,60 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable
if err := d.quotaCtl.SetQuota(dir, quota); err != nil { if err := d.quotaCtl.SetQuota(dir, quota); err != nil {
return err return err
} }
if imageStore != "" {
if err := d.quotaCtl.SetQuota(imageStore, quota); err != nil {
return err
}
}
} }
perms := defaultPerms perms := defaultPerms
if d.options.forceMask != nil { if d.options.forceMask != nil {
perms = *d.options.forceMask perms = *d.options.forceMask
} }
if parent != "" { if parent != "" {
st, err := system.Stat(filepath.Join(d.dir(parent), "diff")) parentDir, parentImageStore, _ := d.dir2(parent)
base := parentDir
if parentImageStore != "" {
base = parentImageStore
}
st, err := system.Stat(filepath.Join(base, "diff"))
if err != nil { if err != nil {
return err return err
} }
perms = os.FileMode(st.Mode()) perms = os.FileMode(st.Mode())
} }
if err := idtools.MkdirAs(path.Join(dir, "diff"), perms, rootUID, rootGID); err != nil { if err := idtools.MkdirAs(path.Join(workDirBase, "diff"), perms, rootUID, rootGID); err != nil {
return err return err
} }
lid := generateID(idLength) lid := generateID(idLength)
if err := os.Symlink(path.Join("..", id, "diff"), path.Join(d.home, linkDir, lid)); err != nil {
linkBase := path.Join("..", id, "diff")
if imageStore != "" {
linkBase = path.Join(imageStore, "diff")
}
if err := os.Symlink(linkBase, path.Join(d.home, linkDir, lid)); err != nil {
return err return err
} }
// Write link id to link file // Write link id to link file
if err := os.WriteFile(path.Join(dir, "link"), []byte(lid), 0644); err != nil { if err := os.WriteFile(path.Join(dir, "link"), []byte(lid), 0o644); err != nil {
return err return err
} }
if err := idtools.MkdirAs(path.Join(dir, "work"), 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAs(path.Join(workDirBase, "work"), 0o700, rootUID, rootGID); err != nil {
return err return err
} }
if err := idtools.MkdirAs(path.Join(dir, "merged"), 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAs(path.Join(dir, "merged"), 0o700, rootUID, rootGID); err != nil {
return err return err
} }
// if no parent directory, create a dummy lower directory and skip writing a "lowers" file // if no parent directory, create a dummy lower directory and skip writing a "lowers" file
if parent == "" { if parent == "" {
return idtools.MkdirAs(path.Join(dir, "empty"), 0700, rootUID, rootGID) return idtools.MkdirAs(path.Join(dir, "empty"), 0o700, rootUID, rootGID)
} }
lower, err := d.getLower(parent) lower, err := d.getLower(parent)
@ -1052,7 +1115,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, disable
return err return err
} }
if lower != "" { if lower != "" {
if err := os.WriteFile(path.Join(dir, lowerFile), []byte(lower), 0666); err != nil { if err := os.WriteFile(path.Join(dir, lowerFile), []byte(lower), 0o666); err != nil {
return err return err
} }
} }
@ -1120,22 +1183,26 @@ func (d *Driver) getLower(parent string) (string, error) {
} }
func (d *Driver) dir(id string) string { func (d *Driver) dir(id string) string {
p, _ := d.dir2(id) p, _, _ := d.dir2(id)
return p return p
} }
func (d *Driver) dir2(id string) (string, bool) { func (d *Driver) dir2(id string) (string, string, bool) {
newpath := path.Join(d.home, id) newpath := path.Join(d.home, id)
imageStore := ""
if d.imageStore != "" {
imageStore = path.Join(d.imageStore, id)
}
if _, err := os.Stat(newpath); err != nil { if _, err := os.Stat(newpath); err != nil {
for _, p := range d.AdditionalImageStores() { for _, p := range d.AdditionalImageStores() {
l := path.Join(p, d.name, id) l := path.Join(p, d.name, id)
_, err = os.Stat(l) _, err = os.Stat(l)
if err == nil { if err == nil {
return l, true return l, imageStore, true
} }
} }
} }
return newpath, false return newpath, imageStore, false
} }
func (d *Driver) getLowerDirs(id string) ([]string, error) { func (d *Driver) getLowerDirs(id string) ([]string, error) {
@ -1223,6 +1290,9 @@ func (d *Driver) Remove(id string) error {
} }
if d.quotaCtl != nil { if d.quotaCtl != nil {
d.quotaCtl.ClearQuota(dir) d.quotaCtl.ClearQuota(dir)
if d.imageStore != "" {
d.quotaCtl.ClearQuota(d.imageStore)
}
} }
return nil return nil
} }
@ -1240,7 +1310,7 @@ func (d *Driver) recreateSymlinks() error {
return fmt.Errorf("reading driver home directory %q: %w", d.home, err) return fmt.Errorf("reading driver home directory %q: %w", d.home, err)
} }
// This makes the link directory if it doesn't exist // This makes the link directory if it doesn't exist
if err := idtools.MkdirAllAs(path.Join(d.home, linkDir), 0755, 0, 0); err != nil { if err := idtools.MkdirAllAs(path.Join(d.home, linkDir), 0o755, 0, 0); err != nil {
return err return err
} }
// Keep looping as long as we take some corrective action in each iteration // Keep looping as long as we take some corrective action in each iteration
@ -1317,7 +1387,7 @@ func (d *Driver) recreateSymlinks() error {
if err != nil || string(data) != link.Name() { if err != nil || string(data) != link.Name() {
// NOTE: If two or more links point to the same target, we will update linkFile // NOTE: If two or more links point to the same target, we will update linkFile
// with every value of link.Name(), and set madeProgress = true every time. // with every value of link.Name(), and set madeProgress = true every time.
if err := os.WriteFile(linkFile, []byte(link.Name()), 0644); err != nil { if err := os.WriteFile(linkFile, []byte(link.Name()), 0o644); err != nil {
errs = multierror.Append(errs, fmt.Errorf("correcting link for layer %s: %w", targetID, err)) errs = multierror.Append(errs, fmt.Errorf("correcting link for layer %s: %w", targetID, err))
continue continue
} }
@ -1342,10 +1412,14 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
} }
func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountOpts) (_ string, retErr error) { func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountOpts) (_ string, retErr error) {
dir, inAdditionalStore := d.dir2(id) dir, imageStore, inAdditionalStore := d.dir2(id)
if _, err := os.Stat(dir); err != nil { if _, err := os.Stat(dir); err != nil {
return "", err return "", err
} }
workDirBase := dir
if imageStore != "" {
workDirBase = imageStore
}
readWrite := !inAdditionalStore readWrite := !inAdditionalStore
if !d.SupportsShifting() || options.DisableShifting { if !d.SupportsShifting() || options.DisableShifting {
@ -1478,18 +1552,18 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
absLowers = append(absLowers, path.Join(dir, "empty")) absLowers = append(absLowers, path.Join(dir, "empty"))
} }
// user namespace requires this to move a directory from lower to upper. // user namespace requires this to move a directory from lower to upper.
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) rootUID, rootGID, err := idtools.GetRootUIDGID(options.UidMaps, options.GidMaps)
if err != nil { if err != nil {
return "", err return "", err
} }
diffDir := path.Join(dir, "diff") diffDir := path.Join(workDirBase, "diff")
if err := idtools.MkdirAllAs(diffDir, perms, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(diffDir, perms, rootUID, rootGID); err != nil {
return "", err return "", err
} }
mergedDir := path.Join(dir, "merged") mergedDir := path.Join(dir, "merged")
// Create the driver merged dir // Create the driver merged dir
if err := idtools.MkdirAs(mergedDir, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { if err := idtools.MkdirAs(mergedDir, 0o700, rootUID, rootGID); err != nil && !os.IsExist(err) {
return "", err return "", err
} }
if count := d.ctr.Increment(mergedDir); count > 1 { if count := d.ctr.Increment(mergedDir); count > 1 {
@ -1505,7 +1579,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
} }
}() }()
workdir := path.Join(dir, "work") workdir := path.Join(workDirBase, "work")
if d.options.mountProgram == "" && unshare.IsRootless() { if d.options.mountProgram == "" && unshare.IsRootless() {
optsList = append(optsList, "userxattr") optsList = append(optsList, "userxattr")
@ -1525,7 +1599,7 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
if !disableShifting && len(options.UidMaps) > 0 && len(options.GidMaps) > 0 && d.options.mountProgram == "" { if !disableShifting && len(options.UidMaps) > 0 && len(options.GidMaps) > 0 && d.options.mountProgram == "" {
var newAbsDir []string var newAbsDir []string
mappedRoot := filepath.Join(d.home, id, "mapped") mappedRoot := filepath.Join(d.home, id, "mapped")
if err := os.MkdirAll(mappedRoot, 0700); err != nil { if err := os.MkdirAll(mappedRoot, 0o700); err != nil {
return "", err return "", err
} }
@ -1612,16 +1686,15 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
// Use mountFrom when the mount data has exceeded the page size. The mount syscall fails if // Use mountFrom when the mount data has exceeded the page size. The mount syscall fails if
// the mount data cannot fit within a page and relative links make the mount data much // the mount data cannot fit within a page and relative links make the mount data much
// smaller at the expense of requiring a fork exec to chdir(). // smaller at the expense of requiring a fork exec to chdir().
workdir = path.Join(id, "work")
if readWrite { if readWrite {
diffDir := path.Join(id, "diff") diffDir := path.Join(id, "diff")
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, workdir) workDir := path.Join(id, "work")
opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, workDir)
} else { } else {
opts = fmt.Sprintf("lowerdir=%s:%s", diffDir, strings.Join(absLowers, ":")) opts = fmt.Sprintf("lowerdir=%s:%s", diffDir, strings.Join(absLowers, ":"))
} }
if len(optsList) > 0 { if len(optsList) > 0 {
opts = fmt.Sprintf("%s,%s", opts, strings.Join(optsList, ",")) opts = strings.Join(append([]string{opts}, optsList...), ",")
} }
mountData = label.FormatMountLabel(opts, options.MountLabel) mountData = label.FormatMountLabel(opts, options.MountLabel)
mountFunc = func(source string, target string, mType string, flags uintptr, label string) error { mountFunc = func(source string, target string, mType string, flags uintptr, label string) error {
@ -1631,9 +1704,9 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
} }
// overlay has a check in place to prevent mounting the same file system twice // overlay has a check in place to prevent mounting the same file system twice
// if volatile was already specified. // if volatile was already specified. Yes, the kernel repeats the "work" component.
err = os.RemoveAll(filepath.Join(workdir, "work/incompat/volatile")) err = os.RemoveAll(filepath.Join(workdir, "work", "incompat", "volatile"))
if err != nil && !os.IsNotExist(err) { if err != nil && !errors.Is(err, os.ErrNotExist) {
return "", err return "", err
} }
@ -1703,11 +1776,13 @@ func (d *Driver) Put(id string) error {
if !unmounted { if !unmounted {
if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil && !os.IsNotExist(err) { if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil && !os.IsNotExist(err) {
logrus.Debugf("Failed to unmount %s overlay: %s - %v", id, mountpoint, err) logrus.Debugf("Failed to unmount %s overlay: %s - %v", id, mountpoint, err)
return fmt.Errorf("unmounting %q: %w", mountpoint, err)
} }
} }
if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) { if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) {
logrus.Debugf("Failed to remove mountpoint %s overlay: %s - %v", id, mountpoint, err) logrus.Debugf("Failed to remove mountpoint %s overlay: %s - %v", id, mountpoint, err)
return fmt.Errorf("removing mount point %q: %w", mountpoint, err)
} }
return nil return nil
@ -1725,20 +1800,23 @@ func (d *Driver) ListLayers() ([]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
layers := make([]string, 0) layers := make([]string, 0)
for _, entry := range entries { for _, entry := range entries {
id := entry.Name() id := entry.Name()
switch id {
case linkDir, stagingDir, quota.BackingFsBlockDeviceLink, mountProgramFlagFile:
// expected, but not a layer. skip it
continue
default:
// Does it look like a datadir directory? // Does it look like a datadir directory?
if !entry.IsDir() || stringid.ValidateID(id) != nil { if !entry.IsDir() {
continue continue
} }
layers = append(layers, id) layers = append(layers, id)
} }
}
return layers, err return layers, nil
} }
// isParent returns if the passed in parent is the direct parent of the passed in layer // isParent returns if the passed in parent is the direct parent of the passed in layer
@ -1795,7 +1873,7 @@ func (g *overlayFileGetter) Close() error {
} }
func (d *Driver) getStagingDir() string { func (d *Driver) getStagingDir() string {
return filepath.Join(d.home, "staging") return filepath.Join(d.home, stagingDir)
} }
// DiffGetter returns a FileGetCloser that can read files from the directory that // DiffGetter returns a FileGetCloser that can read files from the directory that
@ -1831,7 +1909,7 @@ func (d *Driver) ApplyDiffWithDiffer(id, parent string, options *graphdriver.App
var applyDir string var applyDir string
if id == "" { if id == "" {
err := os.MkdirAll(d.getStagingDir(), 0700) err := os.MkdirAll(d.getStagingDir(), 0o700)
if err != nil && !os.IsExist(err) { if err != nil && !os.IsExist(err) {
return graphdriver.DriverWithDifferOutput{}, err return graphdriver.DriverWithDifferOutput{}, err
} }
@ -1884,7 +1962,6 @@ func (d *Driver) DifferTarget(id string) (string, error) {
// ApplyDiff applies the new layer into a root // ApplyDiff applies the new layer into a root
func (d *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts) (size int64, err error) { func (d *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts) (size int64, err error) {
if !d.isParent(id, parent) { if !d.isParent(id, parent) {
if d.options.ignoreChownErrors { if d.options.ignoreChownErrors {
options.IgnoreChownErrors = d.options.ignoreChownErrors options.IgnoreChownErrors = d.options.ignoreChownErrors
@ -1922,8 +1999,12 @@ func (d *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts)
} }
func (d *Driver) getDiffPath(id string) (string, error) { func (d *Driver) getDiffPath(id string) (string, error) {
dir := d.dir(id) dir, imagestore, _ := d.dir2(id)
return redirectDiffIfAdditionalLayer(path.Join(dir, "diff")) base := dir
if imagestore != "" {
base = imagestore
}
return redirectDiffIfAdditionalLayer(path.Join(base, "diff"))
} }
func (d *Driver) getLowerDiffPaths(id string) ([]string, error) { func (d *Driver) getLowerDiffPaths(id string) ([]string, error) {
@ -2014,8 +2095,12 @@ func (d *Driver) AdditionalImageStores() []string {
// by toContainer to those specified by toHost. // by toContainer to those specified by toHost.
func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMappings, mountLabel string) error { func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMappings, mountLabel string) error {
var err error var err error
dir := d.dir(id) dir, imagestore, _ := d.dir2(id)
diffDir := filepath.Join(dir, "diff") base := dir
if imagestore != "" {
base = imagestore
}
diffDir := filepath.Join(base, "diff")
rootUID, rootGID := 0, 0 rootUID, rootGID := 0, 0
if toHost != nil { if toHost != nil {
@ -2196,7 +2281,7 @@ func (al *additionalLayer) CreateAs(id, parent string) error {
} }
// tell the additional layer store that we use this layer. // tell the additional layer store that we use this layer.
// mark this layer as "additional layer" // mark this layer as "additional layer"
if err := os.WriteFile(path.Join(dir, "additionallayer"), []byte(al.path), 0644); err != nil { if err := os.WriteFile(path.Join(dir, "additionallayer"), []byte(al.path), 0o644); err != nil {
return err return err
} }
notifyUseAdditionalLayer(al.path) notifyUseAdditionalLayer(al.path)

View File

@ -50,6 +50,7 @@ struct fsxattr {
#endif #endif
*/ */
import "C" import "C"
import ( import (
"errors" "errors"
"fmt" "fmt"
@ -67,6 +68,10 @@ import (
const projectIDsAllocatedPerQuotaHome = 10000 const projectIDsAllocatedPerQuotaHome = 10000
// BackingFsBlockDeviceLink is the name of a file that we place in
// the home directory of a driver that uses this package.
const BackingFsBlockDeviceLink = "backingFsBlockDev"
// Quota limit params - currently we only control blocks hard limit and inodes // Quota limit params - currently we only control blocks hard limit and inodes
type Quota struct { type Quota struct {
Size uint64 Size uint64
@ -94,7 +99,6 @@ func generateUniqueProjectID(path string) (uint32, error) {
stat, ok := fileinfo.Sys().(*syscall.Stat_t) stat, ok := fileinfo.Sys().(*syscall.Stat_t)
if !ok { if !ok {
return 0, fmt.Errorf("not a syscall.Stat_t %s", path) return 0, fmt.Errorf("not a syscall.Stat_t %s", path)
} }
projectID := projectIDsAllocatedPerQuotaHome + (stat.Ino*projectIDsAllocatedPerQuotaHome)%(math.MaxUint32-projectIDsAllocatedPerQuotaHome) projectID := projectIDsAllocatedPerQuotaHome + (stat.Ino*projectIDsAllocatedPerQuotaHome)%(math.MaxUint32-projectIDsAllocatedPerQuotaHome)
return uint32(projectID), nil return uint32(projectID), nil
@ -187,7 +191,6 @@ func NewControl(basePath string) (*Control, error) {
// SetQuota - assign a unique project id to directory and set the quota limits // SetQuota - assign a unique project id to directory and set the quota limits
// for that project id // for that project id
func (q *Control) SetQuota(targetPath string, quota Quota) error { func (q *Control) SetQuota(targetPath string, quota Quota) error {
projectID, ok := q.quotas[targetPath] projectID, ok := q.quotas[targetPath]
if !ok { if !ok {
projectID = q.nextProjectID projectID = q.nextProjectID
@ -235,7 +238,7 @@ func (q *Control) setProjectQuota(projectID uint32, quota Quota) error {
d.d_ino_softlimit = d.d_ino_hardlimit d.d_ino_softlimit = d.d_ino_hardlimit
} }
var cs = C.CString(q.backingFsBlockDev) cs := C.CString(q.backingFsBlockDev)
defer C.free(unsafe.Pointer(cs)) defer C.free(unsafe.Pointer(cs))
runQuotactl := func() syscall.Errno { runQuotactl := func() syscall.Errno {
@ -303,7 +306,7 @@ func (q *Control) fsDiskQuotaFromPath(targetPath string) (C.fs_disk_quota_t, err
// //
// get the quota limit for the container's project id // get the quota limit for the container's project id
// //
var cs = C.CString(q.backingFsBlockDev) cs := C.CString(q.backingFsBlockDev)
defer C.free(unsafe.Pointer(cs)) defer C.free(unsafe.Pointer(cs))
_, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XGETPQUOTA, _, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XGETPQUOTA,
@ -395,9 +398,9 @@ func openDir(path string) (*C.DIR, error) {
Cpath := C.CString(path) Cpath := C.CString(path)
defer free(Cpath) defer free(Cpath)
dir := C.opendir(Cpath) dir, errno := C.opendir(Cpath)
if dir == nil { if dir == nil {
return nil, fmt.Errorf("can't open dir %v", Cpath) return nil, fmt.Errorf("can't open dir %v: %w", Cpath, errno)
} }
return dir, nil return dir, nil
} }
@ -421,10 +424,10 @@ func makeBackingFsDev(home string) (string, error) {
return "", err return "", err
} }
backingFsBlockDev := path.Join(home, "backingFsBlockDev") backingFsBlockDev := path.Join(home, BackingFsBlockDeviceLink)
backingFsBlockDevTmp := backingFsBlockDev + ".tmp" backingFsBlockDevTmp := backingFsBlockDev + ".tmp"
// Re-create just in case someone copied the home directory over to a new device // Re-create just in case someone copied the home directory over to a new device
if err := unix.Mknod(backingFsBlockDevTmp, unix.S_IFBLK|0600, int(stat.Dev)); err != nil { if err := unix.Mknod(backingFsBlockDevTmp, unix.S_IFBLK|0o600, int(stat.Dev)); err != nil {
return "", fmt.Errorf("failed to mknod %s: %w", backingFsBlockDevTmp, err) return "", fmt.Errorf("failed to mknod %s: %w", backingFsBlockDevTmp, err)
} }
if err := unix.Rename(backingFsBlockDevTmp, backingFsBlockDev); err != nil { if err := unix.Rename(backingFsBlockDevTmp, backingFsBlockDev); err != nil {

View File

@ -15,8 +15,7 @@ type Quota struct {
// Control - Context to be used by storage driver (e.g. overlay) // Control - Context to be used by storage driver (e.g. overlay)
// who wants to apply project quotas to container dirs // who wants to apply project quotas to container dirs
type Control struct { type Control struct{}
}
func NewControl(basePath string) (*Control, error) { func NewControl(basePath string) (*Control, error) {
return nil, errors.New("filesystem does not support, or has not enabled quotas") return nil, errors.New("filesystem does not support, or has not enabled quotas")

View File

@ -34,6 +34,7 @@ func NaiveCreateFromTemplate(d TemplateDriver, id, template string, templateIDMa
} }
return err return err
} }
defer diff.Close()
applyOptions := ApplyDiffOpts{ applyOptions := ApplyDiffOpts{
Diff: diff, Diff: diff,

View File

@ -14,19 +14,13 @@ import (
"github.com/containers/storage/pkg/directory" "github.com/containers/storage/pkg/directory"
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/parsers" "github.com/containers/storage/pkg/parsers"
"github.com/containers/storage/pkg/stringid"
"github.com/containers/storage/pkg/system" "github.com/containers/storage/pkg/system"
"github.com/opencontainers/selinux/go-selinux/label" "github.com/opencontainers/selinux/go-selinux/label"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/vbatts/tar-split/tar/storage" "github.com/vbatts/tar-split/tar/storage"
) )
var ( const defaultPerms = os.FileMode(0o555)
// CopyDir defines the copy method to use.
CopyDir = dirCopy
)
const defaultPerms = os.FileMode(0555)
func init() { func init() {
graphdriver.MustRegister("vfs", Init) graphdriver.MustRegister("vfs", Init)
@ -42,11 +36,10 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
} }
rootIDs := d.idMappings.RootPair() rootIDs := d.idMappings.RootPair()
if err := idtools.MkdirAllAndChown(home, 0700, rootIDs); err != nil { if err := idtools.MkdirAllAndChown(filepath.Join(home, "dir"), 0o700, rootIDs); err != nil {
return nil, err return nil, err
} }
for _, option := range options.DriverOptions { for _, option := range options.DriverOptions {
key, val, err := parsers.ParseKeyValueOpt(option) key, val, err := parsers.ParseKeyValueOpt(option)
if err != nil { if err != nil {
return nil, err return nil, err
@ -69,6 +62,12 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error)
return nil, fmt.Errorf("vfs driver does not support %s options", key) return nil, fmt.Errorf("vfs driver does not support %s options", key)
} }
} }
// If --imagestore is provided, lets add writable graphRoot
// to vfs's additional image store, as it is done for
// `overlay` driver.
if options.ImageStore != "" {
d.homes = append(d.homes, options.ImageStore)
}
d.updater = graphdriver.NewNaiveLayerIDMapUpdater(d) d.updater = graphdriver.NewNaiveLayerIDMapUpdater(d)
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, d.updater) d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, d.updater)
@ -161,7 +160,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, ro bool
dir := d.dir(id) dir := d.dir(id)
rootIDs := idMappings.RootPair() rootIDs := idMappings.RootPair()
if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0700, rootIDs); err != nil { if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0o700, rootIDs); err != nil {
return err return err
} }
@ -173,7 +172,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, ro bool
rootPerms := defaultPerms rootPerms := defaultPerms
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
rootPerms = os.FileMode(0700) rootPerms = os.FileMode(0o700)
} }
if parent != "" { if parent != "" {
@ -203,7 +202,6 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, ro bool
} }
return nil return nil
} }
func (d *Driver) dir(id string) string { func (d *Driver) dir(id string) string {
@ -268,7 +266,7 @@ func (d *Driver) Exists(id string) bool {
// List layers (not including additional image stores) // List layers (not including additional image stores)
func (d *Driver) ListLayers() ([]string, error) { func (d *Driver) ListLayers() ([]string, error) {
entries, err := os.ReadDir(d.homes[0]) entries, err := os.ReadDir(filepath.Join(d.homes[0], "dir"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -278,7 +276,7 @@ func (d *Driver) ListLayers() ([]string, error) {
for _, entry := range entries { for _, entry := range entries {
id := entry.Name() id := entry.Name()
// Does it look like a datadir directory? // Does it look like a datadir directory?
if !entry.IsDir() || stringid.ValidateID(id) != nil { if !entry.IsDir() {
continue continue
} }
@ -304,7 +302,15 @@ func (d *Driver) SupportsShifting() bool {
// UpdateLayerIDMap updates ID mappings in a from matching the ones specified // UpdateLayerIDMap updates ID mappings in a from matching the ones specified
// by toContainer to those specified by toHost. // by toContainer to those specified by toHost.
func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMappings, mountLabel string) error { func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMappings, mountLabel string) error {
return d.updater.UpdateLayerIDMap(id, toContainer, toHost, mountLabel) if err := d.updater.UpdateLayerIDMap(id, toContainer, toHost, mountLabel); err != nil {
return err
}
dir := d.dir(id)
rootIDs, err := toHost.ToHost(idtools.IDPair{UID: 0, GID: 0})
if err != nil {
return err
}
return os.Chown(dir, rootIDs.UID, rootIDs.GID)
} }
// Changes produces a list of changes between the specified layer // Changes produces a list of changes between the specified layer

View File

@ -64,8 +64,7 @@ func init() {
} }
} }
type checker struct { type checker struct{}
}
func (c *checker) IsMounted(path string) bool { func (c *checker) IsMounted(path string) bool {
return false return false
@ -102,7 +101,7 @@ func InitFilter(home string, options graphdriver.Options) (graphdriver.Driver, e
return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home) return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home)
} }
if err := idtools.MkdirAllAs(home, 0700, 0, 0); err != nil { if err := idtools.MkdirAllAs(home, 0o700, 0, 0); err != nil {
return nil, fmt.Errorf("windowsfilter failed to create '%s': %w", home, err) return nil, fmt.Errorf("windowsfilter failed to create '%s': %w", home, err)
} }
@ -885,7 +884,7 @@ func (d *Driver) resolveID(id string) (string, error) {
// setID stores the layerId in disk. // setID stores the layerId in disk.
func (d *Driver) setID(id, altID string) error { func (d *Driver) setID(id, altID string) error {
return os.WriteFile(filepath.Join(d.dir(id), "layerId"), []byte(altID), 0600) return os.WriteFile(filepath.Join(d.dir(id), "layerId"), []byte(altID), 0o600)
} }
// getLayerChain returns the layer chain information. // getLayerChain returns the layer chain information.
@ -915,7 +914,7 @@ func (d *Driver) setLayerChain(id string, chain []string) error {
} }
jPath := filepath.Join(d.dir(id), "layerchain.json") jPath := filepath.Join(d.dir(id), "layerchain.json")
err = os.WriteFile(jPath, content, 0600) err = os.WriteFile(jPath, content, 0o600)
if err != nil { if err != nil {
return fmt.Errorf("unable to write layerchain file - %s", err) return fmt.Errorf("unable to write layerchain file - %s", err)
} }

View File

@ -30,7 +30,7 @@ type zfsOptions struct {
mountOptions string mountOptions string
} }
const defaultPerms = os.FileMode(0555) const defaultPerms = os.FileMode(0o555)
func init() { func init() {
graphdriver.MustRegister("zfs", Init) graphdriver.MustRegister("zfs", Init)
@ -57,7 +57,7 @@ func Init(base string, opt graphdriver.Options) (graphdriver.Driver, error) {
return nil, fmt.Errorf("the 'zfs' command is not available: %w", graphdriver.ErrPrerequisites) return nil, fmt.Errorf("the 'zfs' command is not available: %w", graphdriver.ErrPrerequisites)
} }
file, err := unix.Open("/dev/zfs", unix.O_RDWR, 0600) file, err := unix.Open("/dev/zfs", unix.O_RDWR, 0o600)
if err != nil { if err != nil {
logger.Debugf("cannot open /dev/zfs: %v", err) logger.Debugf("cannot open /dev/zfs: %v", err)
return nil, fmt.Errorf("could not open /dev/zfs: %v: %w", err, graphdriver.ErrPrerequisites) return nil, fmt.Errorf("could not open /dev/zfs: %v: %w", err, graphdriver.ErrPrerequisites)
@ -110,7 +110,7 @@ func Init(base string, opt graphdriver.Options) (graphdriver.Driver, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get root uid/gid: %w", err) return nil, fmt.Errorf("failed to get root uid/gid: %w", err)
} }
if err := idtools.MkdirAllAs(base, 0700, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(base, 0o700, rootUID, rootGID); err != nil {
return nil, fmt.Errorf("failed to create '%s': %w", base, err) return nil, fmt.Errorf("failed to create '%s': %w", base, err)
} }
@ -409,7 +409,6 @@ func (d *Driver) Remove(id string) error {
// Get returns the mountpoint for the given id after creating the target directories if necessary. // Get returns the mountpoint for the given id after creating the target directories if necessary.
func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) { func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) {
mountpoint := d.mountPath(id) mountpoint := d.mountPath(id)
if count := d.ctr.Increment(mountpoint); count > 1 { if count := d.ctr.Increment(mountpoint); count > 1 {
return mountpoint, nil return mountpoint, nil
@ -454,7 +453,7 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr
return "", err return "", err
} }
// Create the target directories if they don't exist // Create the target directories if they don't exist
if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil { if err := idtools.MkdirAllAs(mountpoint, 0o755, rootUID, rootGID); err != nil {
return "", err return "", err
} }
@ -506,7 +505,9 @@ func (d *Driver) Exists(id string) bool {
return d.filesystemsCache[d.zfsPath(id)] return d.filesystemsCache[d.zfsPath(id)]
} }
// List layers (not including additional image stores) // List layers (not including additional image stores). Our layers aren't all
// dependent on a single well-known dataset, so we can't reliably tell which
// datasets are ours and which ones just look like they could be ours.
func (d *Driver) ListLayers() ([]string, error) { func (d *Driver) ListLayers() ([]string, error) {
return nil, graphdriver.ErrNotSupported return nil, graphdriver.ErrNotSupported
} }

View File

@ -568,26 +568,28 @@ func (r *imageStore) Save() error {
} }
r.lockfile.AssertLockedForWriting() r.lockfile.AssertLockedForWriting()
rpath := r.imagespath() rpath := r.imagespath()
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(rpath), 0o700); err != nil {
return err return err
} }
jdata, err := json.Marshal(&r.images) jdata, err := json.Marshal(&r.images)
if err != nil { if err != nil {
return err return err
} }
if err := ioutils.AtomicWriteFile(rpath, jdata, 0600); err != nil { // This must be done before we write the file, because the process could be terminated
return err // after the file is written but before the lock file is updated.
}
lw, err := r.lockfile.RecordWrite() lw, err := r.lockfile.RecordWrite()
if err != nil { if err != nil {
return err return err
} }
r.lastWrite = lw r.lastWrite = lw
if err := ioutils.AtomicWriteFile(rpath, jdata, 0o600); err != nil {
return err
}
return nil return nil
} }
func newImageStore(dir string) (rwImageStore, error) { func newImageStore(dir string) (rwImageStore, error) {
if err := os.MkdirAll(dir, 0700); err != nil { if err := os.MkdirAll(dir, 0o700); err != nil {
return nil, err return nil, err
} }
lockfile, err := lockfile.GetLockFile(filepath.Join(dir, "images.lock")) lockfile, err := lockfile.GetLockFile(filepath.Join(dir, "images.lock"))
@ -1015,11 +1017,11 @@ func (r *imageStore) setBigData(image *Image, key string, data []byte, newDigest
if key == "" { if key == "" {
return fmt.Errorf("can't set empty name for image big data item: %w", ErrInvalidBigDataName) return fmt.Errorf("can't set empty name for image big data item: %w", ErrInvalidBigDataName)
} }
err := os.MkdirAll(r.datadir(image.ID), 0700) err := os.MkdirAll(r.datadir(image.ID), 0o700)
if err != nil { if err != nil {
return err return err
} }
err = ioutils.AtomicWriteFile(r.datapath(image.ID, key), data, 0600) err = ioutils.AtomicWriteFile(r.datapath(image.ID, key), data, 0o600)
if err == nil { if err == nil {
save := false save := false
if image.BigDataSizes == nil { if image.BigDataSizes == nil {

View File

@ -657,7 +657,6 @@ func (r *layerStore) Layers() ([]Layer, error) {
// Requires startWriting. // Requires startWriting.
func (r *layerStore) GarbageCollect() error { func (r *layerStore) GarbageCollect() error {
layers, err := r.driver.ListLayers() layers, err := r.driver.ListLayers()
if err != nil { if err != nil {
if errors.Is(err, drivers.ErrNotSupported) { if errors.Is(err, drivers.ErrNotSupported) {
return nil return nil
@ -864,7 +863,11 @@ func (r *layerStore) loadMounts() error {
return err return err
} }
layerMounts := []layerMountPoint{} layerMounts := []layerMountPoint{}
if err = json.Unmarshal(data, &layerMounts); len(data) == 0 || err == nil { if len(data) != 0 {
if err := json.Unmarshal(data, &layerMounts); err != nil {
return err
}
}
// Clear all of our mount information. If another process // Clear all of our mount information. If another process
// unmounted something, it (along with its zero count) won't // unmounted something, it (along with its zero count) won't
// have been encoded into the version of mountpoints.json that // have been encoded into the version of mountpoints.json that
@ -887,10 +890,8 @@ func (r *layerStore) loadMounts() error {
} }
} }
} }
err = nil
}
r.bymount = mounts r.bymount = mounts
return err return nil
} }
// save saves the contents of the store to disk. // save saves the contents of the store to disk.
@ -920,13 +921,21 @@ func (r *layerStore) saveLayers(saveLocations layerLocations) error {
} }
r.lockfile.AssertLockedForWriting() r.lockfile.AssertLockedForWriting()
// This must be done before we write the file, because the process could be terminated
// after the file is written but before the lock file is updated.
lw, err := r.lockfile.RecordWrite()
if err != nil {
return err
}
r.lastWrite = lw
for locationIndex := 0; locationIndex < numLayerLocationIndex; locationIndex++ { for locationIndex := 0; locationIndex < numLayerLocationIndex; locationIndex++ {
location := layerLocationFromIndex(locationIndex) location := layerLocationFromIndex(locationIndex)
if location&saveLocations == 0 { if location&saveLocations == 0 {
continue continue
} }
rpath := r.jsonPath[locationIndex] rpath := r.jsonPath[locationIndex]
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(rpath), 0o700); err != nil {
return err return err
} }
subsetLayers := make([]*Layer, 0, len(r.layers)) subsetLayers := make([]*Layer, 0, len(r.layers))
@ -944,16 +953,11 @@ func (r *layerStore) saveLayers(saveLocations layerLocations) error {
if location == volatileLayerLocation { if location == volatileLayerLocation {
opts.NoSync = true opts.NoSync = true
} }
if err := ioutils.AtomicWriteFileWithOpts(rpath, jldata, 0600, &opts); err != nil { if err := ioutils.AtomicWriteFileWithOpts(rpath, jldata, 0o600, &opts); err != nil {
return err return err
} }
r.layerspathsModified[locationIndex] = opts.ModTime r.layerspathsModified[locationIndex] = opts.ModTime
} }
lw, err := r.lockfile.RecordWrite()
if err != nil {
return err
}
r.lastWrite = lw
return nil return nil
} }
@ -965,7 +969,7 @@ func (r *layerStore) saveMounts() error {
} }
r.mountsLockfile.AssertLockedForWriting() r.mountsLockfile.AssertLockedForWriting()
mpath := r.mountspath() mpath := r.mountspath()
if err := os.MkdirAll(filepath.Dir(mpath), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(mpath), 0o700); err != nil {
return err return err
} }
mounts := make([]layerMountPoint, 0, len(r.layers)) mounts := make([]layerMountPoint, 0, len(r.layers))
@ -982,22 +986,26 @@ func (r *layerStore) saveMounts() error {
if err != nil { if err != nil {
return err return err
} }
if err = ioutils.AtomicWriteFile(mpath, jmdata, 0600); err != nil {
return err // This must be done before we write the file, because the process could be terminated
} // after the file is written but before the lock file is updated.
lw, err := r.mountsLockfile.RecordWrite() lw, err := r.mountsLockfile.RecordWrite()
if err != nil { if err != nil {
return err return err
} }
r.mountsLastWrite = lw r.mountsLastWrite = lw
if err = ioutils.AtomicWriteFile(mpath, jmdata, 0o600); err != nil {
return err
}
return r.loadMounts() return r.loadMounts()
} }
func (s *store) newLayerStore(rundir string, layerdir string, driver drivers.Driver, transient bool) (rwLayerStore, error) { func (s *store) newLayerStore(rundir string, layerdir string, driver drivers.Driver, transient bool) (rwLayerStore, error) {
if err := os.MkdirAll(rundir, 0700); err != nil { if err := os.MkdirAll(rundir, 0o700); err != nil {
return nil, err return nil, err
} }
if err := os.MkdirAll(layerdir, 0700); err != nil { if err := os.MkdirAll(layerdir, 0o700); err != nil {
return nil, err return nil, err
} }
// Note: While the containers.lock file is in rundir for transient stores // Note: While the containers.lock file is in rundir for transient stores
@ -1213,10 +1221,10 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
if !r.lockfile.IsReadWrite() { if !r.lockfile.IsReadWrite() {
return nil, -1, fmt.Errorf("not allowed to create new layers at %q: %w", r.layerdir, ErrStoreIsReadOnly) return nil, -1, fmt.Errorf("not allowed to create new layers at %q: %w", r.layerdir, ErrStoreIsReadOnly)
} }
if err := os.MkdirAll(r.rundir, 0700); err != nil { if err := os.MkdirAll(r.rundir, 0o700); err != nil {
return nil, -1, err return nil, -1, err
} }
if err := os.MkdirAll(r.layerdir, 0700); err != nil { if err := os.MkdirAll(r.layerdir, 0o700); err != nil {
return nil, -1, err return nil, -1, err
} }
if id == "" { if id == "" {
@ -1690,7 +1698,7 @@ func (r *layerStore) setBigData(layer *Layer, key string, data io.Reader) error
if key == "" { if key == "" {
return fmt.Errorf("can't set empty name for layer big data item: %w", ErrInvalidBigDataName) return fmt.Errorf("can't set empty name for layer big data item: %w", ErrInvalidBigDataName)
} }
err := os.MkdirAll(r.datadir(layer.ID), 0700) err := os.MkdirAll(r.datadir(layer.ID), 0o700)
if err != nil { if err != nil {
return err return err
} }
@ -1698,7 +1706,7 @@ func (r *layerStore) setBigData(layer *Layer, key string, data io.Reader) error
// NewAtomicFileWriter doesn't overwrite/truncate the existing inode. // NewAtomicFileWriter doesn't overwrite/truncate the existing inode.
// BigData() relies on this behaviour when opening the file for read // BigData() relies on this behaviour when opening the file for read
// so that it is either accessing the old data or the new one. // so that it is either accessing the old data or the new one.
writer, err := ioutils.NewAtomicFileWriter(r.datapath(layer.ID, key), 0600) writer, err := ioutils.NewAtomicFileWriter(r.datapath(layer.ID, key), 0o600)
if err != nil { if err != nil {
return fmt.Errorf("opening bigdata file: %w", err) return fmt.Errorf("opening bigdata file: %w", err)
} }
@ -1922,6 +1930,18 @@ func (r *layerStore) Wipe() error {
return err return err
} }
} }
ids, err := r.driver.ListLayers()
if err != nil {
if !errors.Is(err, drivers.ErrNotSupported) {
return err
}
ids = nil
}
for _, id := range ids {
if err := r.driver.Remove(id); err != nil {
return err
}
}
return nil return nil
} }
@ -2198,7 +2218,7 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
return -1, err return -1, err
} }
compression := archive.DetectCompression(header[:n]) compression := archive.DetectCompression(header[:n])
defragmented := io.MultiReader(bytes.NewBuffer(header[:n]), diff) defragmented := io.MultiReader(bytes.NewReader(header[:n]), diff)
// Decide if we need to compute digests // Decide if we need to compute digests
var compressedDigest, uncompressedDigest digest.Digest // = "" var compressedDigest, uncompressedDigest digest.Digest // = ""
@ -2270,10 +2290,10 @@ func (r *layerStore) applyDiffWithOptions(to string, layerOptions *LayerOptions,
return -1, err return -1, err
} }
compressor.Close() compressor.Close()
if err := os.MkdirAll(filepath.Dir(r.tspath(layer.ID)), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(r.tspath(layer.ID)), 0o700); err != nil {
return -1, err return -1, err
} }
if err := ioutils.AtomicWriteFile(r.tspath(layer.ID), tsdata.Bytes(), 0600); err != nil { if err := ioutils.AtomicWriteFile(r.tspath(layer.ID), tsdata.Bytes(), 0o600); err != nil {
return -1, err return -1, err
} }
if compressedDigester != nil { if compressedDigester != nil {

View File

@ -132,13 +132,13 @@ const (
) )
const ( const (
modeISDIR = 040000 // Directory modeISDIR = 0o40000 // Directory
modeISFIFO = 010000 // FIFO modeISFIFO = 0o10000 // FIFO
modeISREG = 0100000 // Regular file modeISREG = 0o100000 // Regular file
modeISLNK = 0120000 // Symbolic link modeISLNK = 0o120000 // Symbolic link
modeISBLK = 060000 // Block special file modeISBLK = 0o60000 // Block special file
modeISCHR = 020000 // Character special file modeISCHR = 0o20000 // Character special file
modeISSOCK = 0140000 // Socket modeISSOCK = 0o140000 // Socket
) )
// IsArchivePath checks if the (possibly compressed) file at the given path // IsArchivePath checks if the (possibly compressed) file at the given path
@ -328,7 +328,6 @@ func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModi
} }
pipeWriter.Close() pipeWriter.Close()
}() }()
return pipeReader return pipeReader
} }
@ -552,9 +551,9 @@ func (ta *tarAppender) addTarFile(path, name string) error {
} }
} }
//handle re-mapping container ID mappings back to host ID mappings before // handle re-mapping container ID mappings back to host ID mappings before
//writing tar headers/files. We skip whiteout files because they were written // writing tar headers/files. We skip whiteout files because they were written
//by the kernel and already have proper ownership relative to the host // by the kernel and already have proper ownership relative to the host
if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IDMappings.Empty() { if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IDMappings.Empty() {
fileIDPair, err := getFileUIDGID(fi.Sys()) fileIDPair, err := getFileUIDGID(fi.Sys())
if err != nil { if err != nil {
@ -702,7 +701,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
} }
if forceMask != nil && (hdr.Typeflag != tar.TypeSymlink || runtime.GOOS == "darwin") { if forceMask != nil && (hdr.Typeflag != tar.TypeSymlink || runtime.GOOS == "darwin") {
value := fmt.Sprintf("%d:%d:0%o", hdr.Uid, hdr.Gid, hdrInfo.Mode()&07777) value := fmt.Sprintf("%d:%d:0%o", hdr.Uid, hdr.Gid, hdrInfo.Mode()&0o7777)
if err := system.Lsetxattr(path, idtools.ContainersOverrideXattr, []byte(value), 0); err != nil { if err := system.Lsetxattr(path, idtools.ContainersOverrideXattr, []byte(value), 0); err != nil {
return err return err
} }
@ -800,7 +799,6 @@ func Tar(path string, compression Compression) (io.ReadCloser, error) {
// TarWithOptions creates an archive from the directory at `path`, only including files whose relative // TarWithOptions creates an archive from the directory at `path`, only including files whose relative
// paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`. // paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`.
func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) { func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
// Fix the source path to work with long path names. This is a no-op // Fix the source path to work with long path names. This is a no-op
// on platforms other than Windows. // on platforms other than Windows.
srcPath = fixVolumePathPrefix(srcPath) srcPath = fixVolumePathPrefix(srcPath)
@ -1032,7 +1030,7 @@ loop:
parent := filepath.Dir(hdr.Name) parent := filepath.Dir(hdr.Name)
parentPath := filepath.Join(dest, parent) parentPath := filepath.Join(dest, parent)
if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
err = idtools.MkdirAllAndChownNew(parentPath, 0777, rootIDs) err = idtools.MkdirAllAndChownNew(parentPath, 0o777, rootIDs)
if err != nil { if err != nil {
return err return err
} }
@ -1239,7 +1237,7 @@ func (archiver *Archiver) CopyWithTar(src, dst string) error {
} }
// Create dst, copy src's content into it // Create dst, copy src's content into it
logrus.Debugf("Creating dest directory: %s", dst) logrus.Debugf("Creating dest directory: %s", dst)
if err := idtools.MkdirAllAndChownNew(dst, 0755, rootIDs); err != nil { if err := idtools.MkdirAllAndChownNew(dst, 0o755, rootIDs); err != nil {
return err return err
} }
logrus.Debugf("Calling TarUntar(%s, %s)", src, dst) logrus.Debugf("Calling TarUntar(%s, %s)", src, dst)
@ -1266,7 +1264,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
dst = filepath.Join(dst, filepath.Base(src)) dst = filepath.Join(dst, filepath.Base(src))
} }
// Create the holding directory if necessary // Create the holding directory if necessary
if err := os.MkdirAll(filepath.Dir(dst), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(dst), 0o700); err != nil {
return err return err
} }
@ -1422,7 +1420,7 @@ func IsArchive(header []byte) bool {
if compression != Uncompressed { if compression != Uncompressed {
return true return true
} }
r := tar.NewReader(bytes.NewBuffer(header)) r := tar.NewReader(bytes.NewReader(header))
_, err := r.Next() _, err := r.Next()
return err == nil return err == nil
} }

View File

@ -153,8 +153,7 @@ func (overlayWhiteoutConverter) ConvertReadWithHandler(hdr *tar.Header, path str
return true, nil return true, nil
} }
type directHandler struct { type directHandler struct{}
}
func (d directHandler) Setxattr(path, name string, value []byte) error { func (d directHandler) Setxattr(path, name string, value []byte) error {
return unix.Setxattr(path, name, value, 0) return unix.Setxattr(path, name, value, 0)
@ -185,7 +184,7 @@ func GetFileOwner(path string) (uint32, uint32, uint32, error) {
} }
s, ok := f.Sys().(*syscall.Stat_t) s, ok := f.Sys().(*syscall.Stat_t)
if ok { if ok {
return s.Uid, s.Gid, s.Mode & 07777, nil return s.Uid, s.Gid, s.Mode & 0o7777, nil
} }
return 0, 0, uint32(f.Mode()), nil return 0, 0, uint32(f.Mode()), nil
} }

View File

@ -88,7 +88,7 @@ func minor(device uint64) uint64 {
// handleTarTypeBlockCharFifo is an OS-specific helper function used by // handleTarTypeBlockCharFifo is an OS-specific helper function used by
// createTarFile to handle the following types of header: Block; Char; Fifo // createTarFile to handle the following types of header: Block; Char; Fifo
func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
mode := uint32(hdr.Mode & 07777) mode := uint32(hdr.Mode & 0o7777)
switch hdr.Typeflag { switch hdr.Typeflag {
case tar.TypeBlock: case tar.TypeBlock:
mode |= unix.S_IFBLK mode |= unix.S_IFBLK

View File

@ -38,18 +38,17 @@ func CanonicalTarNameForPath(p string) (string, error) {
return "", fmt.Errorf("windows path contains forward slash: %s", p) return "", fmt.Errorf("windows path contains forward slash: %s", p)
} }
return strings.Replace(p, string(os.PathSeparator), "/", -1), nil return strings.Replace(p, string(os.PathSeparator), "/", -1), nil
} }
// chmodTarEntry is used to adjust the file permissions used in tar header based // chmodTarEntry is used to adjust the file permissions used in tar header based
// on the platform the archival is done. // on the platform the archival is done.
func chmodTarEntry(perm os.FileMode) os.FileMode { func chmodTarEntry(perm os.FileMode) os.FileMode {
//perm &= 0755 // this 0-ed out tar flags (like link, regular file, directory marker etc.) // perm &= 0755 // this 0-ed out tar flags (like link, regular file, directory marker etc.)
permPart := perm & os.ModePerm permPart := perm & os.ModePerm
noPermPart := perm &^ os.ModePerm noPermPart := perm &^ os.ModePerm
// Add the x bit: make everything +x from windows // Add the x bit: make everything +x from windows
permPart |= 0111 permPart |= 0o111
permPart &= 0755 permPart &= 0o755
return noPermPart | permPart return noPermPart | permPart
} }

View File

@ -131,9 +131,11 @@ func isENOTDIR(err error) bool {
return false return false
} }
type skipChange func(string) (bool, error) type (
type deleteChange func(string, string, os.FileInfo) (string, error) skipChange func(string) (bool, error)
type whiteoutChange func(string, string) (bool, error) deleteChange func(string, string, os.FileInfo) (string, error)
whiteoutChange func(string, string) (bool, error)
)
func changes(layers []string, rw string, dc deleteChange, sc skipChange, wc whiteoutChange) ([]Change, error) { func changes(layers []string, rw string, dc deleteChange, sc skipChange, wc whiteoutChange) ([]Change, error) {
var ( var (
@ -299,7 +301,6 @@ func (info *FileInfo) path() string {
} }
func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) { func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
sizeAtEntry := len(*changes) sizeAtEntry := len(*changes)
if oldInfo == nil { if oldInfo == nil {
@ -373,7 +374,6 @@ func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
copy((*changes)[sizeAtEntry+1:], (*changes)[sizeAtEntry:]) copy((*changes)[sizeAtEntry+1:], (*changes)[sizeAtEntry:])
(*changes)[sizeAtEntry] = change (*changes)[sizeAtEntry] = change
} }
} }
// Changes add changes to file information. // Changes add changes to file information.
@ -398,9 +398,7 @@ func newRootFileInfo(idMappings *idtools.IDMappings) *FileInfo {
// ChangesDirs compares two directories and generates an array of Change objects describing the changes. // ChangesDirs compares two directories and generates an array of Change objects describing the changes.
// If oldDir is "", then all files in newDir will be Add-Changes. // If oldDir is "", then all files in newDir will be Add-Changes.
func ChangesDirs(newDir string, newMappings *idtools.IDMappings, oldDir string, oldMappings *idtools.IDMappings) ([]Change, error) { func ChangesDirs(newDir string, newMappings *idtools.IDMappings, oldDir string, oldMappings *idtools.IDMappings) ([]Change, error) {
var ( var oldRoot, newRoot *FileInfo
oldRoot, newRoot *FileInfo
)
if oldDir == "" { if oldDir == "" {
emptyDir, err := os.MkdirTemp("", "empty") emptyDir, err := os.MkdirTemp("", "empty")
if err != nil { if err != nil {

View File

@ -397,5 +397,4 @@ func overlayDeletedFile(layers []string, root, path string, fi os.FileInfo) (str
// We didn't find the same path in any older layers, so it was new in this one. // We didn't find the same path in any older layers, so it was new in this one.
return "", nil return "", nil
} }

View File

@ -7,7 +7,6 @@ import (
) )
func statDifferent(oldStat *system.StatT, oldInfo *FileInfo, newStat *system.StatT, newInfo *FileInfo) bool { func statDifferent(oldStat *system.StatT, oldInfo *FileInfo, newStat *system.StatT, newInfo *FileInfo) bool {
// Don't look at size for dirs, its not a good measure of change // Don't look at size for dirs, its not a good measure of change
if oldStat.Mtim() != newStat.Mtim() || if oldStat.Mtim() != newStat.Mtim() ||
oldStat.Mode() != newStat.Mode() || oldStat.Mode() != newStat.Mode() ||

View File

@ -297,7 +297,6 @@ func PrepareArchiveCopy(srcContent io.Reader, srcInfo, dstInfo CopyInfo) (dstDir
} }
return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil
} }
} }
// RebaseArchiveEntries rewrites the given srcContent archive replacing // RebaseArchiveEntries rewrites the given srcContent archive replacing

View File

@ -85,7 +85,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
parentPath := filepath.Join(dest, parent) parentPath := filepath.Join(dest, parent)
if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) { if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
err = os.MkdirAll(parentPath, 0755) err = os.MkdirAll(parentPath, 0o755)
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@ -98,7 +98,7 @@ func parseFileFlags(fflags string) (uint32, uint32, error) {
} }
func formatFileFlags(fflags uint32) (string, error) { func formatFileFlags(fflags uint32) (string, error) {
var res = []string{} res := []string{}
for fflags != 0 { for fflags != 0 {
// Extract lowest set bit // Extract lowest set bit
fflag := uint32(1) << bits.TrailingZeros32(fflags) fflag := uint32(1) << bits.TrailingZeros32(fflags)

View File

@ -77,7 +77,7 @@ func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions
dest = filepath.Clean(dest) dest = filepath.Clean(dest)
if _, err := os.Stat(dest); os.IsNotExist(err) { if _, err := os.Stat(dest); os.IsNotExist(err) {
if err := idtools.MkdirAllAndChownNew(dest, 0755, rootIDs); err != nil { if err := idtools.MkdirAllAndChownNew(dest, 0o755, rootIDs); err != nil {
return err return err
} }
} }

View File

@ -8,7 +8,8 @@ import (
func invokeUnpack(decompressedArchive io.Reader, func invokeUnpack(decompressedArchive io.Reader,
dest string, dest string,
options *archive.TarOptions, root string) error { options *archive.TarOptions, root string,
) error {
return archive.Unpack(decompressedArchive, dest, options) return archive.Unpack(decompressedArchive, dest, options)
} }

View File

@ -27,7 +27,7 @@ func untar() {
var options archive.TarOptions var options archive.TarOptions
//read the options from the pipe "ExtraFiles" // read the options from the pipe "ExtraFiles"
if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil { if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil {
fatal(err) fatal(err)
} }
@ -99,7 +99,7 @@ func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.T
return fmt.Errorf("untar error on re-exec cmd: %w", err) return fmt.Errorf("untar error on re-exec cmd: %w", err)
} }
//write the options to the pipe for the untar exec to read // write the options to the pipe for the untar exec to read
if err := json.NewEncoder(w).Encode(options); err != nil { if err := json.NewEncoder(w).Encode(options); err != nil {
w.Close() w.Close()
return fmt.Errorf("untar json encode to pipe failed: %w", err) return fmt.Errorf("untar json encode to pipe failed: %w", err)

View File

@ -14,7 +14,8 @@ func chroot(path string) error {
func invokeUnpack(decompressedArchive io.Reader, func invokeUnpack(decompressedArchive io.Reader,
dest string, dest string,
options *archive.TarOptions, root string) error { options *archive.TarOptions, root string,
) error {
// Windows is different to Linux here because Windows does not support // Windows is different to Linux here because Windows does not support
// chroot. Hence there is no point sandboxing a chrooted process to // chroot. Hence there is no point sandboxing a chrooted process to
// do the unpack. We call inline instead within the daemon process. // do the unpack. We call inline instead within the daemon process.

View File

@ -26,7 +26,6 @@ type applyLayerResponse struct {
// used on Windows as it does not support chroot, hence no point sandboxing // used on Windows as it does not support chroot, hence no point sandboxing
// through chroot and rexec. // through chroot and rexec.
func applyLayer() { func applyLayer() {
var ( var (
tmpDir string tmpDir string
err error err error

View File

@ -48,8 +48,10 @@ type layersCache struct {
created time.Time created time.Time
} }
var cacheMutex sync.Mutex var (
var cache *layersCache cacheMutex sync.Mutex
cache *layersCache
)
func (c *layersCache) release() { func (c *layersCache) release() {
cacheMutex.Lock() cacheMutex.Lock()

View File

@ -15,8 +15,10 @@ import (
"github.com/vbatts/tar-split/archive/tar" "github.com/vbatts/tar-split/archive/tar"
) )
const RollsumBits = 16 const (
const holesThreshold = int64(1 << 10) RollsumBits = 16
holesThreshold = int64(1 << 10)
)
type holesFinder struct { type holesFinder struct {
reader *bufio.Reader reader *bufio.Reader

View File

@ -25,11 +25,15 @@ import (
"math/bits" "math/bits"
) )
const windowSize = 64 // Roll assumes windowSize is a power of 2 const (
const charOffset = 31 windowSize = 64 // Roll assumes windowSize is a power of 2
charOffset = 31
)
const blobBits = 13 const (
const blobSize = 1 << blobBits // 8k blobBits = 13
blobSize = 1 << blobBits // 8k
)
type RollSum struct { type RollSum struct {
s1, s2 uint32 s1, s2 uint32

View File

@ -134,7 +134,7 @@ func WriteZstdChunkedManifest(dest io.Writer, outMetadata map[string]string, off
Entries: metadata, Entries: metadata,
} }
var json = jsoniter.ConfigCompatibleWithStandardLibrary json := jsoniter.ConfigCompatibleWithStandardLibrary
// Generate the manifest // Generate the manifest
manifest, err := json.Marshal(toc) manifest, err := json.Marshal(toc)
if err != nil { if err != nil {

View File

@ -558,7 +558,7 @@ func openFileUnderRootFallback(dirfd int, name string, flags uint64, mode os.Fil
func openFileUnderRootOpenat2(dirfd int, name string, flags uint64, mode os.FileMode) (int, error) { func openFileUnderRootOpenat2(dirfd int, name string, flags uint64, mode os.FileMode) (int, error) {
how := unix.OpenHow{ how := unix.OpenHow{
Flags: flags, Flags: flags,
Mode: uint64(mode & 07777), Mode: uint64(mode & 0o7777),
Resolve: unix.RESOLVE_IN_ROOT, Resolve: unix.RESOLVE_IN_ROOT,
} }
return unix.Openat2(dirfd, name, &how) return unix.Openat2(dirfd, name, &how)
@ -636,7 +636,7 @@ func openOrCreateDirUnderRoot(name string, dirfd int, mode os.FileMode) (*os.Fil
baseName := filepath.Base(name) baseName := filepath.Base(name)
if err2 := unix.Mkdirat(int(pDir.Fd()), baseName, 0755); err2 != nil { if err2 := unix.Mkdirat(int(pDir.Fd()), baseName, 0o755); err2 != nil {
return nil, err return nil, err
} }
@ -1384,7 +1384,7 @@ func (c *chunkedDiffer) ApplyDiff(dest string, options *archive.TarOptions) (gra
filesToWaitFor := 0 filesToWaitFor := 0
for i, r := range mergedEntries { for i, r := range mergedEntries {
if options.ForceMask != nil { if options.ForceMask != nil {
value := fmt.Sprintf("%d:%d:0%o", r.UID, r.GID, r.Mode&07777) value := fmt.Sprintf("%d:%d:0%o", r.UID, r.GID, r.Mode&0o7777)
r.Xattrs[containersOverrideXattr] = base64.StdEncoding.EncodeToString([]byte(value)) r.Xattrs[containersOverrideXattr] = base64.StdEncoding.EncodeToString([]byte(value))
r.Mode = int64(*options.ForceMask) r.Mode = int64(*options.ForceMask)
} }

View File

@ -124,6 +124,11 @@ type OptionsConfig struct {
// for shared image content // for shared image content
AdditionalImageStores []string `toml:"additionalimagestores,omitempty"` AdditionalImageStores []string `toml:"additionalimagestores,omitempty"`
// ImageStore is the location of image store which is separated from the
// container store. Usually this is not recommended unless users wants
// separate store for image and containers.
ImageStore string `toml:"imagestore,omitempty"`
// AdditionalLayerStores is the location of additional read/only // AdditionalLayerStores is the location of additional read/only
// Layer stores. Usually used to access Networked File System // Layer stores. Usually used to access Networked File System
// for shared image content // for shared image content

View File

@ -239,8 +239,8 @@ func (t *Task) getDriverVersion() (string, error) {
} }
func (t *Task) getNextTarget(next unsafe.Pointer) (nextPtr unsafe.Pointer, start uint64, func (t *Task) getNextTarget(next unsafe.Pointer) (nextPtr unsafe.Pointer, start uint64,
length uint64, targetType string, params string) { length uint64, targetType string, params string,
) {
return DmGetNextTarget(t.unmanaged, next, &start, &length, return DmGetNextTarget(t.unmanaged, next, &start, &length,
&targetType, &params), &targetType, &params),
start, length, targetType, params start, length, targetType, params
@ -345,8 +345,7 @@ func RemoveDeviceDeferred(name string) error {
// disable udev dm rules and delete the symlink under /dev/mapper by itself, // disable udev dm rules and delete the symlink under /dev/mapper by itself,
// even if the removal is deferred by the kernel. // even if the removal is deferred by the kernel.
cookie := new(uint) cookie := new(uint)
var flags uint16 flags := uint16(DmUdevDisableLibraryFallback)
flags = DmUdevDisableLibraryFallback
if err := task.setCookie(cookie, flags); err != nil { if err := task.setCookie(cookie, flags); err != nil {
return fmt.Errorf("devicemapper: Can not set cookie: %s", err) return fmt.Errorf("devicemapper: Can not set cookie: %s", err)
} }
@ -384,7 +383,7 @@ func CancelDeferredRemove(deviceName string) error {
return fmt.Errorf("devicemapper: Can't set sector %s", err) return fmt.Errorf("devicemapper: Can't set sector %s", err)
} }
if err := task.setMessage(fmt.Sprintf("@cancel_deferred_remove")); err != nil { if err := task.setMessage("@cancel_deferred_remove"); err != nil {
return fmt.Errorf("devicemapper: Can't set message %s", err) return fmt.Errorf("devicemapper: Can't set message %s", err)
} }
@ -459,8 +458,7 @@ func CreatePool(poolName string, dataFile, metadataFile *os.File, poolBlockSize
} }
cookie := new(uint) cookie := new(uint)
var flags uint16 flags := uint16(DmUdevDisableSubsystemRulesFlag | DmUdevDisableDiskRulesFlag | DmUdevDisableOtherRulesFlag)
flags = DmUdevDisableSubsystemRulesFlag | DmUdevDisableDiskRulesFlag | DmUdevDisableOtherRulesFlag
if err := task.setCookie(cookie, flags); err != nil { if err := task.setCookie(cookie, flags); err != nil {
return fmt.Errorf("devicemapper: Can't set cookie %s", err) return fmt.Errorf("devicemapper: Can't set cookie %s", err)
} }

View File

@ -138,8 +138,8 @@ func dmTaskSetRoFct(task *cdmTask) int {
} }
func dmTaskAddTargetFct(task *cdmTask, func dmTaskAddTargetFct(task *cdmTask,
start, size uint64, ttype, params string) int { start, size uint64, ttype, params string,
) int {
Cttype := C.CString(ttype) Cttype := C.CString(ttype)
defer free(Cttype) defer free(Cttype)
@ -156,12 +156,11 @@ func dmTaskGetDepsFct(task *cdmTask) *Deps {
} }
// golang issue: https://github.com/golang/go/issues/11925 // golang issue: https://github.com/golang/go/issues/11925
hdr := reflect.SliceHeader{ var devices []C.uint64_t
Data: uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps))), devicesHdr := (*reflect.SliceHeader)(unsafe.Pointer(&devices))
Len: int(Cdeps.count), devicesHdr.Data = uintptr(unsafe.Pointer(uintptr(unsafe.Pointer(Cdeps)) + unsafe.Sizeof(*Cdeps)))
Cap: int(Cdeps.count), devicesHdr.Len = int(Cdeps.count)
} devicesHdr.Cap = int(Cdeps.count)
devices := *(*[]C.uint64_t)(unsafe.Pointer(&hdr))
deps := &Deps{ deps := &Deps{
Count: uint32(Cdeps.count), Count: uint32(Cdeps.count),

View File

@ -183,7 +183,6 @@ func (p *Pattern) Exclusion() bool {
} }
func (p *Pattern) match(path string) (bool, error) { func (p *Pattern) match(path string) (bool, error) {
if p.regexp == nil { if p.regexp == nil {
if err := p.compile(); err != nil { if err := p.compile(); err != nil {
return false, filepath.ErrBadPattern return false, filepath.ErrBadPattern
@ -356,12 +355,12 @@ func CreateIfNotExists(path string, isDir bool) error {
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
if isDir { if isDir {
return os.MkdirAll(path, 0755) return os.MkdirAll(path, 0o755)
} }
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return err return err
} }
f, err := os.OpenFile(path, os.O_CREATE, 0755) f, err := os.OpenFile(path, os.O_CREATE, 0o755)
if err != nil { if err != nil {
return err return err
} }

View File

@ -104,7 +104,7 @@ func CreateIDMappedMount(source, target string, pid int) error {
&attr, uint(unsafe.Sizeof(attr))); err != nil { &attr, uint(unsafe.Sizeof(attr))); err != nil {
return err return err
} }
if err := os.Mkdir(target, 0700); err != nil && !os.IsExist(err) { if err := os.Mkdir(target, 0o700); err != nil && !os.IsExist(err) {
return err return err
} }
return moveMount(targetDirFd, target) return moveMount(targetDirFd, target)
@ -140,7 +140,7 @@ func CreateUsernsProcess(uidMaps []idtools.IDMap, gidMaps []idtools.IDMap) (int,
for _, m := range idmap { for _, m := range idmap {
mappings = mappings + fmt.Sprintf("%d %d %d\n", m.ContainerID, m.HostID, m.Size) mappings = mappings + fmt.Sprintf("%d %d %d\n", m.ContainerID, m.HostID, m.Size)
} }
return os.WriteFile(fmt.Sprintf("/proc/%d/%s", pid, fname), []byte(mappings), 0600) return os.WriteFile(fmt.Sprintf("/proc/%d/%s", pid, fname), []byte(mappings), 0o600)
} }
if err := writeMappings("uid_map", uidMaps); err != nil { if err := writeMappings("uid_map", uidMaps); err != nil {
cleanupFunc() cleanupFunc()

View File

@ -91,13 +91,13 @@ func CanAccess(path string, pair IDPair) bool {
} }
func accessible(isOwner, isGroup bool, perms os.FileMode) bool { func accessible(isOwner, isGroup bool, perms os.FileMode) bool {
if isOwner && (perms&0100 == 0100) { if isOwner && (perms&0o100 == 0o100) {
return true return true
} }
if isGroup && (perms&0010 == 0010) { if isGroup && (perms&0o010 == 0o010) {
return true return true
} }
if perms&0001 == 0001 { if perms&0o001 == 0o001 {
return true return true
} }
return false return false

View File

@ -89,7 +89,6 @@ func addUser(userName string) error {
} }
func createSubordinateRanges(name string) error { func createSubordinateRanges(name string) error {
// first, we should verify that ranges weren't automatically created // first, we should verify that ranges weren't automatically created
// by the distro tooling // by the distro tooling
ranges, err := readSubuid(name) ranges, err := readSubuid(name)

View File

@ -19,8 +19,8 @@ func resolveBinary(binname string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
//only return no error if the final resolved binary basename // only return no error if the final resolved binary basename
//matches what was searched for // matches what was searched for
if filepath.Base(resolvedPath) == binname { if filepath.Base(resolvedPath) == binname {
return resolvedPath, nil return resolvedPath, nil
} }

View File

@ -135,7 +135,7 @@ func openLock(path string, ro bool) (fd int, err error) {
// the directory of the lockfile seems to be removed, try to create it // the directory of the lockfile seems to be removed, try to create it
if os.IsNotExist(err) { if os.IsNotExist(err) {
if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
return fd, fmt.Errorf("creating lock file directory: %w", err) return fd, fmt.Errorf("creating lock file directory: %w", err)
} }

View File

@ -138,6 +138,7 @@ func (l *LockFile) Modified() (bool, error) {
func (l *LockFile) Touch() error { func (l *LockFile) Touch() error {
return nil return nil
} }
func (l *LockFile) IsReadWrite() bool { func (l *LockFile) IsReadWrite() bool {
return false return false
} }

Some files were not shown because too many files have changed in this diff Show More