mirror of https://github.com/k3s-io/k3s
Update containerd to fix AppArmor on SLES
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>pull/2954/head
parent
c61245bdfa
commit
8c9608b26f
3
go.mod
3
go.mod
|
@ -7,7 +7,7 @@ replace (
|
||||||
github.com/containerd/btrfs => github.com/containerd/btrfs v0.0.0-20181101203652-af5082808c83
|
github.com/containerd/btrfs => github.com/containerd/btrfs v0.0.0-20181101203652-af5082808c83
|
||||||
github.com/containerd/cgroups => github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601
|
github.com/containerd/cgroups => github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601
|
||||||
github.com/containerd/console => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
|
github.com/containerd/console => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
|
||||||
github.com/containerd/containerd => github.com/k3s-io/containerd v1.3.9-k3s1
|
github.com/containerd/containerd => github.com/k3s-io/containerd v1.3.9-k3s2
|
||||||
github.com/containerd/continuity => github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02
|
github.com/containerd/continuity => github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02
|
||||||
github.com/containerd/cri => github.com/k3s-io/cri v1.3.0-k3s.9 // k3s-release/1.3
|
github.com/containerd/cri => github.com/k3s-io/cri v1.3.0-k3s.9 // k3s-release/1.3
|
||||||
github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c
|
github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c
|
||||||
|
@ -115,6 +115,7 @@ require (
|
||||||
google.golang.org/grpc v1.26.0
|
google.golang.org/grpc v1.26.0
|
||||||
gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5 // indirect
|
gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
|
gotest.tools/v3 v3.0.3 // indirect
|
||||||
k8s.io/api v0.18.0
|
k8s.io/api v0.18.0
|
||||||
k8s.io/apimachinery v0.18.0
|
k8s.io/apimachinery v0.18.0
|
||||||
k8s.io/apiserver v0.0.0
|
k8s.io/apiserver v0.0.0
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -364,6 +364,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-containerregistry v0.0.0-20190617215043-876b8855d23c/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk=
|
github.com/google/go-containerregistry v0.0.0-20190617215043-876b8855d23c/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk=
|
||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
@ -450,8 +452,8 @@ github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVE
|
||||||
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||||
github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||||
github.com/k3s-io/containerd v1.3.9-k3s1 h1:VeMMmcojFZDJlLkgtIr7GAmDUgtGS7ME3KvLo9g/6+s=
|
github.com/k3s-io/containerd v1.3.9-k3s2 h1:lv8cL/0Lw7OnR05+IFOB2zisAXP2wvgI4kWTAvMA684=
|
||||||
github.com/k3s-io/containerd v1.3.9-k3s1/go.mod h1:eMCLnqhZCzg+cZuvfMLStYPsrx5cWGpdZL6krPhK8RI=
|
github.com/k3s-io/containerd v1.3.9-k3s2/go.mod h1:eMCLnqhZCzg+cZuvfMLStYPsrx5cWGpdZL6krPhK8RI=
|
||||||
github.com/k3s-io/cri v1.3.0-k3s.9 h1:1PUJysV7YQElM5JEjnHdOQ2kgwtTiSJ5fpx1j4/WjzU=
|
github.com/k3s-io/cri v1.3.0-k3s.9 h1:1PUJysV7YQElM5JEjnHdOQ2kgwtTiSJ5fpx1j4/WjzU=
|
||||||
github.com/k3s-io/cri v1.3.0-k3s.9/go.mod h1:fGPUUHMKQik/vIegSe05DtX/m4miovdtvVLqRUFAkK0=
|
github.com/k3s-io/cri v1.3.0-k3s.9/go.mod h1:fGPUUHMKQik/vIegSe05DtX/m4miovdtvVLqRUFAkK0=
|
||||||
github.com/k3s-io/helm-controller v0.8.3 h1:GWxavyMz7Bw2ClxH5okkeOL8o5U6IBK7uauc44SDCjU=
|
github.com/k3s-io/helm-controller v0.8.3 h1:GWxavyMz7Bw2ClxH5okkeOL8o5U6IBK7uauc44SDCjU=
|
||||||
|
@ -960,11 +962,14 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
|
||||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190909030654-5b82db07426d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191017205301-920acffc3e65 h1:GwXwgmbrvlcHLDsENMqrQTTIC2C0kIPszsq929NruKI=
|
golang.org/x/tools v0.0.0-20191017205301-920acffc3e65 h1:GwXwgmbrvlcHLDsENMqrQTTIC2C0kIPszsq929NruKI=
|
||||||
golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
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-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||||
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
|
||||||
gonum.org/v1/gonum v0.6.2 h1:4r+yNT0+8SWcOkXP+63H2zQbN+USnC73cjGUxnDF94Q=
|
gonum.org/v1/gonum v0.6.2 h1:4r+yNT0+8SWcOkXP+63H2zQbN+USnC73cjGUxnDF94Q=
|
||||||
|
@ -1032,6 +1037,8 @@ gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/gotestsum v0.3.5/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY=
|
gotest.tools/gotestsum v0.3.5/go.mod h1:Mnf3e5FUzXbkCfynWBGOwLssY7gTQgCHObK9tMpAriY=
|
||||||
|
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||||
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Copyright The docker Authors.
|
||||||
|
Copyright The Moby Authors.
|
||||||
Copyright The containerd Authors.
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -22,6 +24,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
@ -32,6 +35,10 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NOTE: This code is copied from <github.com/docker/docker/profiles/apparmor>.
|
||||||
|
// If you plan to make any changes, please make sure they are also sent
|
||||||
|
// upstream.
|
||||||
|
|
||||||
const dir = "/etc/apparmor.d"
|
const dir = "/etc/apparmor.d"
|
||||||
|
|
||||||
const defaultTemplate = `
|
const defaultTemplate = `
|
||||||
|
@ -48,6 +55,14 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
|
||||||
capability,
|
capability,
|
||||||
file,
|
file,
|
||||||
umount,
|
umount,
|
||||||
|
{{if ge .Version 208096}}
|
||||||
|
# Host (privileged) processes may send signals to container processes.
|
||||||
|
signal (receive) peer=unconfined,
|
||||||
|
# Manager may send signals to container processes.
|
||||||
|
signal (receive) peer={{.DaemonProfile}},
|
||||||
|
# Container processes may send signals amongst themselves.
|
||||||
|
signal (send,receive) peer={{.Name}},
|
||||||
|
{{end}}
|
||||||
|
|
||||||
deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir)
|
deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir)
|
||||||
# deny write to files not in /proc/<number>/** or /proc/sys/**
|
# deny write to files not in /proc/<number>/** or /proc/sys/**
|
||||||
|
@ -79,9 +94,22 @@ type data struct {
|
||||||
Name string
|
Name string
|
||||||
Imports []string
|
Imports []string
|
||||||
InnerImports []string
|
InnerImports []string
|
||||||
|
DaemonProfile string
|
||||||
Version int
|
Version int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cleanProfileName(profile string) string {
|
||||||
|
// Normally profiles are suffixed by " (enforce)". AppArmor profiles cannot
|
||||||
|
// contain spaces so this doesn't restrict daemon profile names.
|
||||||
|
if parts := strings.SplitN(profile, " ", 2); len(parts) >= 1 {
|
||||||
|
profile = parts[0]
|
||||||
|
}
|
||||||
|
if profile == "" {
|
||||||
|
profile = "unconfined"
|
||||||
|
}
|
||||||
|
return profile
|
||||||
|
}
|
||||||
|
|
||||||
func loadData(name string) (*data, error) {
|
func loadData(name string) (*data, error) {
|
||||||
p := data{
|
p := data{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -100,6 +128,16 @@ func loadData(name string) (*data, error) {
|
||||||
return nil, errors.Wrap(err, "get apparmor_parser version")
|
return nil, errors.Wrap(err, "get apparmor_parser version")
|
||||||
}
|
}
|
||||||
p.Version = ver
|
p.Version = ver
|
||||||
|
|
||||||
|
// Figure out the daemon profile.
|
||||||
|
currentProfile, err := ioutil.ReadFile("/proc/self/attr/current")
|
||||||
|
if err != nil {
|
||||||
|
// If we couldn't get the daemon profile, assume we are running
|
||||||
|
// unconfined which is generally the default.
|
||||||
|
currentProfile = nil
|
||||||
|
}
|
||||||
|
p.DaemonProfile = cleanProfileName(string(currentProfile))
|
||||||
|
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
// equality is determined by recursively comparing the primitive kinds on both
|
// equality is determined by recursively comparing the primitive kinds on both
|
||||||
// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported
|
// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported
|
||||||
// fields are not compared by default; they result in panics unless suppressed
|
// fields are not compared by default; they result in panics unless suppressed
|
||||||
// by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly compared
|
// by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly
|
||||||
// using the AllowUnexported option.
|
// compared using the Exporter option.
|
||||||
package cmp
|
package cmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -62,8 +62,8 @@ import (
|
||||||
//
|
//
|
||||||
// Structs are equal if recursively calling Equal on all fields report equal.
|
// Structs are equal if recursively calling Equal on all fields report equal.
|
||||||
// If a struct contains unexported fields, Equal panics unless an Ignore option
|
// If a struct contains unexported fields, Equal panics unless an Ignore option
|
||||||
// (e.g., cmpopts.IgnoreUnexported) ignores that field or the AllowUnexported
|
// (e.g., cmpopts.IgnoreUnexported) ignores that field or the Exporter option
|
||||||
// option explicitly permits comparing the unexported field.
|
// explicitly permits comparing the unexported field.
|
||||||
//
|
//
|
||||||
// Slices are equal if they are both nil or both non-nil, where recursively
|
// Slices are equal if they are both nil or both non-nil, where recursively
|
||||||
// calling Equal on all non-ignored slice or array elements report equal.
|
// calling Equal on all non-ignored slice or array elements report equal.
|
||||||
|
@ -80,6 +80,11 @@ import (
|
||||||
// Pointers and interfaces are equal if they are both nil or both non-nil,
|
// Pointers and interfaces are equal if they are both nil or both non-nil,
|
||||||
// where they have the same underlying concrete type and recursively
|
// where they have the same underlying concrete type and recursively
|
||||||
// calling Equal on the underlying values reports equal.
|
// calling Equal on the underlying values reports equal.
|
||||||
|
//
|
||||||
|
// Before recursing into a pointer, slice element, or map, the current path
|
||||||
|
// is checked to detect whether the address has already been visited.
|
||||||
|
// If there is a cycle, then the pointed at values are considered equal
|
||||||
|
// only if both addresses were previously visited in the same path step.
|
||||||
func Equal(x, y interface{}, opts ...Option) bool {
|
func Equal(x, y interface{}, opts ...Option) bool {
|
||||||
vx := reflect.ValueOf(x)
|
vx := reflect.ValueOf(x)
|
||||||
vy := reflect.ValueOf(y)
|
vy := reflect.ValueOf(y)
|
||||||
|
@ -137,6 +142,7 @@ type state struct {
|
||||||
// Calling statelessCompare must not result in observable changes to these.
|
// Calling statelessCompare must not result in observable changes to these.
|
||||||
result diff.Result // The current result of comparison
|
result diff.Result // The current result of comparison
|
||||||
curPath Path // The current path in the value tree
|
curPath Path // The current path in the value tree
|
||||||
|
curPtrs pointerPath // The current set of visited pointers
|
||||||
reporters []reporter // Optional reporters
|
reporters []reporter // Optional reporters
|
||||||
|
|
||||||
// recChecker checks for infinite cycles applying the same set of
|
// recChecker checks for infinite cycles applying the same set of
|
||||||
|
@ -148,13 +154,14 @@ type state struct {
|
||||||
dynChecker dynChecker
|
dynChecker dynChecker
|
||||||
|
|
||||||
// These fields, once set by processOption, will not change.
|
// These fields, once set by processOption, will not change.
|
||||||
exporters map[reflect.Type]bool // Set of structs with unexported field visibility
|
exporters []exporter // List of exporters for structs with unexported fields
|
||||||
opts Options // List of all fundamental and filter options
|
opts Options // List of all fundamental and filter options
|
||||||
}
|
}
|
||||||
|
|
||||||
func newState(opts []Option) *state {
|
func newState(opts []Option) *state {
|
||||||
// Always ensure a validator option exists to validate the inputs.
|
// Always ensure a validator option exists to validate the inputs.
|
||||||
s := &state{opts: Options{validator{}}}
|
s := &state{opts: Options{validator{}}}
|
||||||
|
s.curPtrs.Init()
|
||||||
s.processOption(Options(opts))
|
s.processOption(Options(opts))
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -174,13 +181,8 @@ func (s *state) processOption(opt Option) {
|
||||||
panic(fmt.Sprintf("cannot use an unfiltered option: %v", opt))
|
panic(fmt.Sprintf("cannot use an unfiltered option: %v", opt))
|
||||||
}
|
}
|
||||||
s.opts = append(s.opts, opt)
|
s.opts = append(s.opts, opt)
|
||||||
case visibleStructs:
|
case exporter:
|
||||||
if s.exporters == nil {
|
s.exporters = append(s.exporters, opt)
|
||||||
s.exporters = make(map[reflect.Type]bool)
|
|
||||||
}
|
|
||||||
for t := range opt {
|
|
||||||
s.exporters[t] = true
|
|
||||||
}
|
|
||||||
case reporter:
|
case reporter:
|
||||||
s.reporters = append(s.reporters, opt)
|
s.reporters = append(s.reporters, opt)
|
||||||
default:
|
default:
|
||||||
|
@ -192,9 +194,9 @@ func (s *state) processOption(opt Option) {
|
||||||
// This function is stateless in that it does not alter the current result,
|
// This function is stateless in that it does not alter the current result,
|
||||||
// or output to any registered reporters.
|
// or output to any registered reporters.
|
||||||
func (s *state) statelessCompare(step PathStep) diff.Result {
|
func (s *state) statelessCompare(step PathStep) diff.Result {
|
||||||
// We do not save and restore the curPath because all of the compareX
|
// We do not save and restore curPath and curPtrs because all of the
|
||||||
// methods should properly push and pop from the path.
|
// compareX methods should properly push and pop from them.
|
||||||
// It is an implementation bug if the contents of curPath differs from
|
// It is an implementation bug if the contents of the paths differ from
|
||||||
// when calling this function to when returning from it.
|
// when calling this function to when returning from it.
|
||||||
|
|
||||||
oldResult, oldReporters := s.result, s.reporters
|
oldResult, oldReporters := s.result, s.reporters
|
||||||
|
@ -216,9 +218,17 @@ func (s *state) compareAny(step PathStep) {
|
||||||
}
|
}
|
||||||
s.recChecker.Check(s.curPath)
|
s.recChecker.Check(s.curPath)
|
||||||
|
|
||||||
// Obtain the current type and values.
|
// Cycle-detection for slice elements (see NOTE in compareSlice).
|
||||||
t := step.Type()
|
t := step.Type()
|
||||||
vx, vy := step.Values()
|
vx, vy := step.Values()
|
||||||
|
if si, ok := step.(SliceIndex); ok && si.isSlice && vx.IsValid() && vy.IsValid() {
|
||||||
|
px, py := vx.Addr(), vy.Addr()
|
||||||
|
if eq, visited := s.curPtrs.Push(px, py); visited {
|
||||||
|
s.report(eq, reportByCycle)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer s.curPtrs.Pop(px, py)
|
||||||
|
}
|
||||||
|
|
||||||
// Rule 1: Check whether an option applies on this node in the value tree.
|
// Rule 1: Check whether an option applies on this node in the value tree.
|
||||||
if s.tryOptions(t, vx, vy) {
|
if s.tryOptions(t, vx, vy) {
|
||||||
|
@ -354,6 +364,7 @@ func sanitizeValue(v reflect.Value, t reflect.Type) reflect.Value {
|
||||||
func (s *state) compareStruct(t reflect.Type, vx, vy reflect.Value) {
|
func (s *state) compareStruct(t reflect.Type, vx, vy reflect.Value) {
|
||||||
var vax, vay reflect.Value // Addressable versions of vx and vy
|
var vax, vay reflect.Value // Addressable versions of vx and vy
|
||||||
|
|
||||||
|
var mayForce, mayForceInit bool
|
||||||
step := StructField{&structField{}}
|
step := StructField{&structField{}}
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
step.typ = t.Field(i).Type
|
step.typ = t.Field(i).Type
|
||||||
|
@ -375,7 +386,13 @@ func (s *state) compareStruct(t reflect.Type, vx, vy reflect.Value) {
|
||||||
vax = makeAddressable(vx)
|
vax = makeAddressable(vx)
|
||||||
vay = makeAddressable(vy)
|
vay = makeAddressable(vy)
|
||||||
}
|
}
|
||||||
step.mayForce = s.exporters[t]
|
if !mayForceInit {
|
||||||
|
for _, xf := range s.exporters {
|
||||||
|
mayForce = mayForce || xf(t)
|
||||||
|
}
|
||||||
|
mayForceInit = true
|
||||||
|
}
|
||||||
|
step.mayForce = mayForce
|
||||||
step.pvx = vax
|
step.pvx = vax
|
||||||
step.pvy = vay
|
step.pvy = vay
|
||||||
step.field = t.Field(i)
|
step.field = t.Field(i)
|
||||||
|
@ -391,9 +408,21 @@ func (s *state) compareSlice(t reflect.Type, vx, vy reflect.Value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support cyclic data structures.
|
// NOTE: It is incorrect to call curPtrs.Push on the slice header pointer
|
||||||
|
// since slices represents a list of pointers, rather than a single pointer.
|
||||||
|
// The pointer checking logic must be handled on a per-element basis
|
||||||
|
// in compareAny.
|
||||||
|
//
|
||||||
|
// A slice header (see reflect.SliceHeader) in Go is a tuple of a starting
|
||||||
|
// pointer P, a length N, and a capacity C. Supposing each slice element has
|
||||||
|
// a memory size of M, then the slice is equivalent to the list of pointers:
|
||||||
|
// [P+i*M for i in range(N)]
|
||||||
|
//
|
||||||
|
// For example, v[:0] and v[:1] are slices with the same starting pointer,
|
||||||
|
// but they are clearly different values. Using the slice pointer alone
|
||||||
|
// violates the assumption that equal pointers implies equal values.
|
||||||
|
|
||||||
step := SliceIndex{&sliceIndex{pathStep: pathStep{typ: t.Elem()}}}
|
step := SliceIndex{&sliceIndex{pathStep: pathStep{typ: t.Elem()}, isSlice: isSlice}}
|
||||||
withIndexes := func(ix, iy int) SliceIndex {
|
withIndexes := func(ix, iy int) SliceIndex {
|
||||||
if ix >= 0 {
|
if ix >= 0 {
|
||||||
step.vx, step.xkey = vx.Index(ix), ix
|
step.vx, step.xkey = vx.Index(ix), ix
|
||||||
|
@ -470,7 +499,12 @@ func (s *state) compareMap(t reflect.Type, vx, vy reflect.Value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support cyclic data structures.
|
// Cycle-detection for maps.
|
||||||
|
if eq, visited := s.curPtrs.Push(vx, vy); visited {
|
||||||
|
s.report(eq, reportByCycle)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer s.curPtrs.Pop(vx, vy)
|
||||||
|
|
||||||
// We combine and sort the two map keys so that we can perform the
|
// We combine and sort the two map keys so that we can perform the
|
||||||
// comparisons in a deterministic order.
|
// comparisons in a deterministic order.
|
||||||
|
@ -507,7 +541,12 @@ func (s *state) comparePtr(t reflect.Type, vx, vy reflect.Value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support cyclic data structures.
|
// Cycle-detection for pointers.
|
||||||
|
if eq, visited := s.curPtrs.Push(vx, vy); visited {
|
||||||
|
s.report(eq, reportByCycle)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer s.curPtrs.Pop(vx, vy)
|
||||||
|
|
||||||
vx, vy = vx.Elem(), vy.Elem()
|
vx, vy = vx.Elem(), vy.Elem()
|
||||||
s.compareAny(Indirect{&indirect{pathStep{t.Elem(), vx, vy}}})
|
s.compareAny(Indirect{&indirect{pathStep{t.Elem(), vx, vy}}})
|
||||||
|
|
|
@ -8,8 +8,8 @@ package cmp
|
||||||
|
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
const supportAllowUnexported = false
|
const supportExporters = false
|
||||||
|
|
||||||
func retrieveUnexportedField(reflect.Value, reflect.StructField) reflect.Value {
|
func retrieveUnexportedField(reflect.Value, reflect.StructField) reflect.Value {
|
||||||
panic("retrieveUnexportedField is not implemented")
|
panic("no support for forcibly accessing unexported fields")
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const supportAllowUnexported = true
|
const supportExporters = true
|
||||||
|
|
||||||
// retrieveUnexportedField uses unsafe to forcibly retrieve any field from
|
// retrieveUnexportedField uses unsafe to forcibly retrieve any field from
|
||||||
// a struct such that the value has read-write permissions.
|
// a struct such that the value has read-write permissions.
|
||||||
|
@ -19,5 +19,7 @@ const supportAllowUnexported = true
|
||||||
// The parent struct, v, must be addressable, while f must be a StructField
|
// The parent struct, v, must be addressable, while f must be a StructField
|
||||||
// describing the field to retrieve.
|
// describing the field to retrieve.
|
||||||
func retrieveUnexportedField(v reflect.Value, f reflect.StructField) reflect.Value {
|
func retrieveUnexportedField(v reflect.Value, f reflect.StructField) reflect.Value {
|
||||||
return reflect.NewAt(f.Type, unsafe.Pointer(v.UnsafeAddr()+f.Offset)).Elem()
|
// See https://github.com/google/go-cmp/issues/167 for discussion of the
|
||||||
|
// following expression.
|
||||||
|
return reflect.NewAt(f.Type, unsafe.Pointer(uintptr(unsafe.Pointer(v.UnsafeAddr()))+f.Offset)).Elem()
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,8 +225,20 @@ func (validator) apply(s *state, vx, vy reflect.Value) {
|
||||||
|
|
||||||
// Unable to Interface implies unexported field without visibility access.
|
// Unable to Interface implies unexported field without visibility access.
|
||||||
if !vx.CanInterface() || !vy.CanInterface() {
|
if !vx.CanInterface() || !vy.CanInterface() {
|
||||||
const help = "consider using a custom Comparer; if you control the implementation of type, you can also consider AllowUnexported or cmpopts.IgnoreUnexported"
|
const help = "consider using a custom Comparer; if you control the implementation of type, you can also consider using an Exporter, AllowUnexported, or cmpopts.IgnoreUnexported"
|
||||||
panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help))
|
var name string
|
||||||
|
if t := s.curPath.Index(-2).Type(); t.Name() != "" {
|
||||||
|
// Named type with unexported fields.
|
||||||
|
name = fmt.Sprintf("%q.%v", t.PkgPath(), t.Name()) // e.g., "path/to/package".MyType
|
||||||
|
} else {
|
||||||
|
// Unnamed type with unexported fields. Derive PkgPath from field.
|
||||||
|
var pkgPath string
|
||||||
|
for i := 0; i < t.NumField() && pkgPath == ""; i++ {
|
||||||
|
pkgPath = t.Field(i).PkgPath
|
||||||
|
}
|
||||||
|
name = fmt.Sprintf("%q.(%v)", pkgPath, t.String()) // e.g., "path/to/package".(struct { a int })
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("cannot handle unexported field at %#v:\n\t%v\n%s", s.curPath, name, help))
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("not reachable")
|
panic("not reachable")
|
||||||
|
@ -360,9 +372,8 @@ func (cm comparer) String() string {
|
||||||
return fmt.Sprintf("Comparer(%s)", function.NameOf(cm.fnc))
|
return fmt.Sprintf("Comparer(%s)", function.NameOf(cm.fnc))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllowUnexported returns an Option that forcibly allows operations on
|
// Exporter returns an Option that specifies whether Equal is allowed to
|
||||||
// unexported fields in certain structs, which are specified by passing in a
|
// introspect into the unexported fields of certain struct types.
|
||||||
// value of each struct type.
|
|
||||||
//
|
//
|
||||||
// Users of this option must understand that comparing on unexported fields
|
// Users of this option must understand that comparing on unexported fields
|
||||||
// from external packages is not safe since changes in the internal
|
// from external packages is not safe since changes in the internal
|
||||||
|
@ -386,10 +397,24 @@ func (cm comparer) String() string {
|
||||||
//
|
//
|
||||||
// In other cases, the cmpopts.IgnoreUnexported option can be used to ignore
|
// In other cases, the cmpopts.IgnoreUnexported option can be used to ignore
|
||||||
// all unexported fields on specified struct types.
|
// all unexported fields on specified struct types.
|
||||||
func AllowUnexported(types ...interface{}) Option {
|
func Exporter(f func(reflect.Type) bool) Option {
|
||||||
if !supportAllowUnexported {
|
if !supportExporters {
|
||||||
panic("AllowUnexported is not supported on purego builds, Google App Engine Standard, or GopherJS")
|
panic("Exporter is not supported on purego builds")
|
||||||
}
|
}
|
||||||
|
return exporter(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
type exporter func(reflect.Type) bool
|
||||||
|
|
||||||
|
func (exporter) filter(_ *state, _ reflect.Type, _, _ reflect.Value) applicableOption {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowUnexported returns an Options that allows Equal to forcibly introspect
|
||||||
|
// unexported fields of the specified struct types.
|
||||||
|
//
|
||||||
|
// See Exporter for the proper use of this option.
|
||||||
|
func AllowUnexported(types ...interface{}) Option {
|
||||||
m := make(map[reflect.Type]bool)
|
m := make(map[reflect.Type]bool)
|
||||||
for _, typ := range types {
|
for _, typ := range types {
|
||||||
t := reflect.TypeOf(typ)
|
t := reflect.TypeOf(typ)
|
||||||
|
@ -398,13 +423,7 @@ func AllowUnexported(types ...interface{}) Option {
|
||||||
}
|
}
|
||||||
m[t] = true
|
m[t] = true
|
||||||
}
|
}
|
||||||
return visibleStructs(m)
|
return exporter(func(t reflect.Type) bool { return m[t] })
|
||||||
}
|
|
||||||
|
|
||||||
type visibleStructs map[reflect.Type]bool
|
|
||||||
|
|
||||||
func (visibleStructs) filter(_ *state, _ reflect.Type, _, _ reflect.Value) applicableOption {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result represents the comparison result for a single node and
|
// Result represents the comparison result for a single node and
|
||||||
|
@ -436,6 +455,11 @@ func (r Result) ByFunc() bool {
|
||||||
return r.flags&reportByFunc != 0
|
return r.flags&reportByFunc != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByCycle reports whether a reference cycle was detected.
|
||||||
|
func (r Result) ByCycle() bool {
|
||||||
|
return r.flags&reportByCycle != 0
|
||||||
|
}
|
||||||
|
|
||||||
type resultFlags uint
|
type resultFlags uint
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -446,6 +470,7 @@ const (
|
||||||
reportByIgnore
|
reportByIgnore
|
||||||
reportByMethod
|
reportByMethod
|
||||||
reportByFunc
|
reportByFunc
|
||||||
|
reportByCycle
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reporter is an Option that can be passed to Equal. When Equal traverses
|
// Reporter is an Option that can be passed to Equal. When Equal traverses
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp/internal/value"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Path is a list of PathSteps describing the sequence of operations to get
|
// Path is a list of PathSteps describing the sequence of operations to get
|
||||||
|
@ -41,7 +43,7 @@ type PathStep interface {
|
||||||
// In some cases, one or both may be invalid or have restrictions:
|
// In some cases, one or both may be invalid or have restrictions:
|
||||||
// • For StructField, both are not interface-able if the current field
|
// • For StructField, both are not interface-able if the current field
|
||||||
// is unexported and the struct type is not explicitly permitted by
|
// is unexported and the struct type is not explicitly permitted by
|
||||||
// AllowUnexported to traverse unexported fields.
|
// an Exporter to traverse unexported fields.
|
||||||
// • For SliceIndex, one may be invalid if an element is missing from
|
// • For SliceIndex, one may be invalid if an element is missing from
|
||||||
// either the x or y slice.
|
// either the x or y slice.
|
||||||
// • For MapIndex, one may be invalid if an entry is missing from
|
// • For MapIndex, one may be invalid if an entry is missing from
|
||||||
|
@ -207,6 +209,7 @@ type SliceIndex struct{ *sliceIndex }
|
||||||
type sliceIndex struct {
|
type sliceIndex struct {
|
||||||
pathStep
|
pathStep
|
||||||
xkey, ykey int
|
xkey, ykey int
|
||||||
|
isSlice bool // False for reflect.Array
|
||||||
}
|
}
|
||||||
|
|
||||||
func (si SliceIndex) Type() reflect.Type { return si.typ }
|
func (si SliceIndex) Type() reflect.Type { return si.typ }
|
||||||
|
@ -301,6 +304,72 @@ func (tf Transform) Func() reflect.Value { return tf.trans.fnc }
|
||||||
// The == operator can be used to detect the exact option used.
|
// The == operator can be used to detect the exact option used.
|
||||||
func (tf Transform) Option() Option { return tf.trans }
|
func (tf Transform) Option() Option { return tf.trans }
|
||||||
|
|
||||||
|
// pointerPath represents a dual-stack of pointers encountered when
|
||||||
|
// recursively traversing the x and y values. This data structure supports
|
||||||
|
// detection of cycles and determining whether the cycles are equal.
|
||||||
|
// In Go, cycles can occur via pointers, slices, and maps.
|
||||||
|
//
|
||||||
|
// The pointerPath uses a map to represent a stack; where descension into a
|
||||||
|
// pointer pushes the address onto the stack, and ascension from a pointer
|
||||||
|
// pops the address from the stack. Thus, when traversing into a pointer from
|
||||||
|
// reflect.Ptr, reflect.Slice element, or reflect.Map, we can detect cycles
|
||||||
|
// by checking whether the pointer has already been visited. The cycle detection
|
||||||
|
// uses a seperate stack for the x and y values.
|
||||||
|
//
|
||||||
|
// If a cycle is detected we need to determine whether the two pointers
|
||||||
|
// should be considered equal. The definition of equality chosen by Equal
|
||||||
|
// requires two graphs to have the same structure. To determine this, both the
|
||||||
|
// x and y values must have a cycle where the previous pointers were also
|
||||||
|
// encountered together as a pair.
|
||||||
|
//
|
||||||
|
// Semantically, this is equivalent to augmenting Indirect, SliceIndex, and
|
||||||
|
// MapIndex with pointer information for the x and y values.
|
||||||
|
// Suppose px and py are two pointers to compare, we then search the
|
||||||
|
// Path for whether px was ever encountered in the Path history of x, and
|
||||||
|
// similarly so with py. If either side has a cycle, the comparison is only
|
||||||
|
// equal if both px and py have a cycle resulting from the same PathStep.
|
||||||
|
//
|
||||||
|
// Using a map as a stack is more performant as we can perform cycle detection
|
||||||
|
// in O(1) instead of O(N) where N is len(Path).
|
||||||
|
type pointerPath struct {
|
||||||
|
// mx is keyed by x pointers, where the value is the associated y pointer.
|
||||||
|
mx map[value.Pointer]value.Pointer
|
||||||
|
// my is keyed by y pointers, where the value is the associated x pointer.
|
||||||
|
my map[value.Pointer]value.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *pointerPath) Init() {
|
||||||
|
p.mx = make(map[value.Pointer]value.Pointer)
|
||||||
|
p.my = make(map[value.Pointer]value.Pointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push indicates intent to descend into pointers vx and vy where
|
||||||
|
// visited reports whether either has been seen before. If visited before,
|
||||||
|
// equal reports whether both pointers were encountered together.
|
||||||
|
// Pop must be called if and only if the pointers were never visited.
|
||||||
|
//
|
||||||
|
// The pointers vx and vy must be a reflect.Ptr, reflect.Slice, or reflect.Map
|
||||||
|
// and be non-nil.
|
||||||
|
func (p pointerPath) Push(vx, vy reflect.Value) (equal, visited bool) {
|
||||||
|
px := value.PointerOf(vx)
|
||||||
|
py := value.PointerOf(vy)
|
||||||
|
_, ok1 := p.mx[px]
|
||||||
|
_, ok2 := p.my[py]
|
||||||
|
if ok1 || ok2 {
|
||||||
|
equal = p.mx[px] == py && p.my[py] == px // Pointers paired together
|
||||||
|
return equal, true
|
||||||
|
}
|
||||||
|
p.mx[px] = py
|
||||||
|
p.my[py] = px
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop ascends from pointers vx and vy.
|
||||||
|
func (p pointerPath) Pop(vx, vy reflect.Value) {
|
||||||
|
delete(p.mx, value.PointerOf(vx))
|
||||||
|
delete(p.my, value.PointerOf(vy))
|
||||||
|
}
|
||||||
|
|
||||||
// isExported reports whether the identifier is exported.
|
// isExported reports whether the identifier is exported.
|
||||||
func isExported(id string) bool {
|
func isExported(id string) bool {
|
||||||
r, _ := utf8.DecodeRuneInString(id)
|
r, _ := utf8.DecodeRuneInString(id)
|
||||||
|
|
|
@ -160,7 +160,7 @@ github.com/container-storage-interface/spec/lib/go/csi
|
||||||
github.com/containerd/cgroups
|
github.com/containerd/cgroups
|
||||||
# github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
|
# github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
|
||||||
github.com/containerd/console
|
github.com/containerd/console
|
||||||
# github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69 => github.com/k3s-io/containerd v1.3.9-k3s1
|
# github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69 => github.com/k3s-io/containerd v1.3.9-k3s2
|
||||||
github.com/containerd/containerd
|
github.com/containerd/containerd
|
||||||
github.com/containerd/containerd/api/events
|
github.com/containerd/containerd/api/events
|
||||||
github.com/containerd/containerd/api/services/containers/v1
|
github.com/containerd/containerd/api/services/containers/v1
|
||||||
|
@ -527,7 +527,7 @@ github.com/google/cadvisor/utils/sysinfo
|
||||||
github.com/google/cadvisor/version
|
github.com/google/cadvisor/version
|
||||||
github.com/google/cadvisor/watcher
|
github.com/google/cadvisor/watcher
|
||||||
github.com/google/cadvisor/zfs
|
github.com/google/cadvisor/zfs
|
||||||
# github.com/google/go-cmp v0.3.1
|
# github.com/google/go-cmp v0.4.0
|
||||||
github.com/google/go-cmp/cmp
|
github.com/google/go-cmp/cmp
|
||||||
github.com/google/go-cmp/cmp/internal/diff
|
github.com/google/go-cmp/cmp/internal/diff
|
||||||
github.com/google/go-cmp/cmp/internal/flags
|
github.com/google/go-cmp/cmp/internal/flags
|
||||||
|
|
Loading…
Reference in New Issue