From 5c095146188ca6c87516fc9a8b40d7ac5b60c570 Mon Sep 17 00:00:00 2001 From: Tomas Nozicka Date: Thu, 1 Aug 2019 17:40:40 +0200 Subject: [PATCH] Bump (*) --- glide.lock | 14 +- vendor/github.com/containers/storage/VERSION | 2 +- .../storage/docs/containers-storage.conf.5.md | 3 + .../containers/storage/drivers/aufs/aufs.go | 6 +- .../containers/storage/drivers/driver.go | 11 +- .../containers/storage/drivers/fsdiff.go | 23 +- .../drivers/graphtest/graphbench_unix.go | 2 +- .../drivers/graphtest/graphtest_unix.go | 4 +- .../storage/drivers/overlay/overlay.go | 42 +- .../containers/storage/drivers/template.go | 9 +- .../containers/storage/drivers/vfs/driver.go | 96 +++- .../storage/drivers/windows/windows.go | 4 +- .../github.com/containers/storage/layers.go | 20 +- .../containers/storage/pkg/archive/archive.go | 30 +- .../storage/pkg/archive/archive_ffjson.go | 58 +++ .../storage/pkg/archive/archive_test.go | 2 +- .../containers/storage/pkg/archive/diff.go | 4 +- .../containers/storage/pkg/config/config.go | 3 + .../containers/storage/storage.conf | 8 + vendor/github.com/containers/storage/store.go | 3 + vendor/github.com/docker/libtrust/README.md | 4 + vendor/github.com/docker/libtrust/util.go | 2 +- vendor/github.com/google/uuid/README.md | 4 - vendor/github.com/google/uuid/go.mod | 1 + vendor/github.com/google/uuid/hash.go | 2 +- vendor/github.com/google/uuid/marshal.go | 2 - vendor/github.com/google/uuid/node.go | 30 +- vendor/github.com/google/uuid/node_js.go | 12 + vendor/github.com/google/uuid/node_net.go | 33 ++ vendor/github.com/google/uuid/seq_test.go | 2 +- vendor/github.com/google/uuid/sql_test.go | 6 +- vendor/github.com/google/uuid/time.go | 6 +- vendor/github.com/google/uuid/uuid.go | 85 ++- vendor/github.com/google/uuid/uuid_test.go | 73 ++- vendor/github.com/google/uuid/version4.go | 9 +- .../gorilla/mux/.circleci/config.yml | 87 ++++ .../github.com/gorilla/mux/.github/stale.yml | 10 +- vendor/github.com/gorilla/mux/.travis.yml | 24 - .../github.com/gorilla/mux/ISSUE_TEMPLATE.md | 11 - vendor/github.com/gorilla/mux/README.md | 160 +++++- vendor/github.com/gorilla/mux/doc.go | 2 +- .../example_cors_method_middleware_test.go | 37 ++ vendor/github.com/gorilla/mux/go.mod | 2 + vendor/github.com/gorilla/mux/middleware.go | 61 ++- .../github.com/gorilla/mux/middleware_test.go | 486 +++++++++++------- vendor/github.com/gorilla/mux/mux.go | 12 +- vendor/github.com/gorilla/mux/mux_test.go | 14 +- vendor/github.com/gorilla/mux/regexp.go | 37 +- vendor/github.com/gorilla/mux/route.go | 2 +- .../opencontainers/go-digest/.mailmap | 1 + .../opencontainers/go-digest/.travis.yml | 6 +- .../go-digest/{LICENSE.code => LICENSE} | 0 .../opencontainers/go-digest/MAINTAINERS | 2 + .../opencontainers/go-digest/README.md | 26 +- .../opencontainers/go-digest/algorithm.go | 54 +- .../go-digest/algorithm_test.go | 14 + .../opencontainers/go-digest/digest.go | 56 +- .../opencontainers/go-digest/digest_test.go | 56 +- .../opencontainers/go-digest/digester.go | 14 + .../opencontainers/go-digest/doc.go | 14 + .../opencontainers/go-digest/verifiers.go | 14 + .../go-digest/verifiers_test.go | 14 + .../make/default.example.mk | 10 +- .../make/default.example.mk.help.log | 2 +- .../make/operator.example.mk | 10 +- .../make/operator.example.mk.help.log | 2 +- .../make/targets/openshift/images.mk | 24 +- 67 files changed, 1385 insertions(+), 494 deletions(-) create mode 100644 vendor/github.com/google/uuid/go.mod create mode 100644 vendor/github.com/google/uuid/node_js.go create mode 100644 vendor/github.com/google/uuid/node_net.go create mode 100644 vendor/github.com/gorilla/mux/.circleci/config.yml delete mode 100644 vendor/github.com/gorilla/mux/.travis.yml delete mode 100644 vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md create mode 100644 vendor/github.com/gorilla/mux/example_cors_method_middleware_test.go create mode 100644 vendor/github.com/opencontainers/go-digest/.mailmap rename vendor/github.com/opencontainers/go-digest/{LICENSE.code => LICENSE} (100%) diff --git a/glide.lock b/glide.lock index b0c786f958..9fafadd2c8 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 133600678bfced8f947d0b7797aa19e87a4b7cb279eab1c96799fd17aac36ec3 -updated: 2019-07-31T14:11:30.280580035-04:00 +updated: 2019-08-01T17:39:30.516109233+02:00 imports: - name: bitbucket.org/ww/goautoneg version: 2ae31c8b6b30d2f4c8100c20d527b571e9c433bb @@ -93,7 +93,7 @@ imports: - types - version - name: github.com/containers/storage - version: 912de200380ac2fd1e90f91b78c1495ed8d5beea + version: 1b2a0dcaf4e74170644c851ff75b8637dbd2af68 subpackages: - pkg/fileutils - pkg/homedir @@ -188,7 +188,7 @@ imports: - ipamutils - ipvs - name: github.com/docker/libtrust - version: 9cbd2a1374f46905c68a4eb3694a130610adc62a + version: aabc10ec26b754e797f9028f4589c5b7bd90dc20 - name: github.com/docker/spdystream version: 449fdfce4d962303d702fec724ef0ad181c92528 subpackages: @@ -290,7 +290,7 @@ imports: - name: github.com/google/gofuzz version: 24818f796faf91cd76ec7bddd72458fbced7a6c1 - name: github.com/google/uuid - version: 8c31c18f31ede9fc8eae72290a7e7a8064e9b3e3 + version: c2e93f3ae59f2904160ceaab466009f965df46d6 - name: github.com/googleapis/gnostic version: 0c5108395e2debce0d731cf0287ddf7242066aba subpackages: @@ -298,7 +298,7 @@ imports: - compiler - extensions - name: github.com/gorilla/mux - version: 08e7f807d38d6a870193019bb439056118661505 + version: e67b3c02c7195c052acff13261f0c9fd1ba53011 - name: github.com/gregjones/httpcache version: 787624de3eb7bd915c329cba748687a3b22666a6 subpackages: @@ -366,7 +366,7 @@ imports: version: 53ca7dc85f609e8aa3af7902f189ed5dca96dbb5 repo: https://github.com/openshift/onsi-ginkgo.git - name: github.com/opencontainers/go-digest - version: a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb + version: ac19fd6e7483ff933754af248d80be865e543d22 - name: github.com/opencontainers/image-spec version: 372ad780f63454fbbbbcc7cf80e5b90245c13e13 subpackages: @@ -504,7 +504,7 @@ imports: - user/clientset/versioned/typed/user/v1 - user/clientset/versioned/typed/user/v1/fake - name: github.com/openshift/library-go - version: 950af653b51af28697df79f1406fc9d21f722db8 + version: 1810ce5f54ff4a1a4fea05e06024896a4885eb05 subpackages: - pkg/apps/appsserialization - pkg/apps/appsutil diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index 30df2362bc..0074baf69f 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.12.16-dev +1.12.17-dev diff --git a/vendor/github.com/containers/storage/docs/containers-storage.conf.5.md b/vendor/github.com/containers/storage/docs/containers-storage.conf.5.md index 4fbc88965e..1fa66e7f9a 100644 --- a/vendor/github.com/containers/storage/docs/containers-storage.conf.5.md +++ b/vendor/github.com/containers/storage/docs/containers-storage.conf.5.md @@ -49,6 +49,9 @@ The `storage.options` table supports the following options: **additionalimagestores**=[] Paths to additional container image stores. Usually these are read/only and stored on remote network shares. +**ignore_chown_errors** = "true|False" + ignore_chown_errors can be set to allow a non privileged user running with a single UID within a user namespace to run containers. The user can pull and use any image even those with multiple uids. Note multiple UIDs will be squasheddown to the default uid in the container. These images will have no separation between the users in the container. Only supported for the overlay and vfs drivers. + **mount_program**="" Specifies the path to a custom program to use instead of using kernel defaults for mounting the file system. diff --git a/vendor/github.com/containers/storage/drivers/aufs/aufs.go b/vendor/github.com/containers/storage/drivers/aufs/aufs.go index 56bb081e94..4430670a20 100644 --- a/vendor/github.com/containers/storage/drivers/aufs/aufs.go +++ b/vendor/github.com/containers/storage/drivers/aufs/aufs.go @@ -550,13 +550,13 @@ func (a *Driver) DiffSize(id string, idMappings *idtools.IDMappings, parent stri // ApplyDiff extracts the changeset from the given diff into the // layer with the specified id and parent, returning the size of the // new layer in bytes. -func (a *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent, mountLabel string, diff io.Reader) (size int64, err error) { +func (a *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts) (size int64, err error) { if !a.isParent(id, parent) { - return a.naiveDiff.ApplyDiff(id, idMappings, parent, mountLabel, diff) + return a.naiveDiff.ApplyDiff(id, parent, options) } // AUFS doesn't need the parent id to apply the diff if it is the direct parent. - if err = a.applyDiff(id, idMappings, diff); err != nil { + if err = a.applyDiff(id, options.Mappings, options.Diff); err != nil { return } diff --git a/vendor/github.com/containers/storage/drivers/driver.go b/vendor/github.com/containers/storage/drivers/driver.go index 3b56fd2e1f..8d6b2a5dcc 100644 --- a/vendor/github.com/containers/storage/drivers/driver.go +++ b/vendor/github.com/containers/storage/drivers/driver.go @@ -41,6 +41,7 @@ type CreateOpts struct { MountLabel string StorageOpt map[string]string *idtools.IDMappings + ignoreChownErrors bool } // MountOpts contains optional arguments for LayerStope.Mount() methods. @@ -53,6 +54,14 @@ type MountOpts struct { Options []string } +// ApplyDiffOpts contains optional arguments for ApplyDiff methods. +type ApplyDiffOpts struct { + Diff io.Reader + Mappings *idtools.IDMappings + MountLabel string + IgnoreChownErrors bool +} + // InitFunc initializes the storage driver. type InitFunc func(homedir string, options Options) (Driver, error) @@ -115,7 +124,7 @@ type DiffDriver interface { // layer with the specified id and parent, returning the size of the // new layer in bytes. // The io.Reader must be an uncompressed stream. - ApplyDiff(id string, idMappings *idtools.IDMappings, parent string, mountLabel string, diff io.Reader) (size int64, err error) + ApplyDiff(id string, parent string, options ApplyDiffOpts) (size int64, err error) // DiffSize calculates the changes between the specified id // and its parent and returns the size in bytes of the changes // relative to its base filesystem directory. diff --git a/vendor/github.com/containers/storage/drivers/fsdiff.go b/vendor/github.com/containers/storage/drivers/fsdiff.go index ab2c41e587..d34fdee3bc 100644 --- a/vendor/github.com/containers/storage/drivers/fsdiff.go +++ b/vendor/github.com/containers/storage/drivers/fsdiff.go @@ -33,7 +33,7 @@ type NaiveDiffDriver struct { // it may or may not support on its own: // Diff(id string, idMappings *idtools.IDMappings, parent string, parentMappings *idtools.IDMappings, mountLabel string) (io.ReadCloser, error) // Changes(id string, idMappings *idtools.IDMappings, parent string, parentMappings *idtools.IDMappings, mountLabel string) ([]archive.Change, error) -// ApplyDiff(id string, idMappings *idtools.IDMappings, parent, mountLabel string, diff io.Reader) (size int64, err error) +// ApplyDiff(id, parent string, options ApplyDiffOpts) (size int64, err error) // DiffSize(id string, idMappings *idtools.IDMappings, parent, parentMappings *idtools.IDMappings, mountLabel string) (size int64, err error) func NewNaiveDiffDriver(driver ProtoDriver, updater LayerIDMapUpdater) Driver { return &NaiveDiffDriver{ProtoDriver: driver, LayerIDMapUpdater: updater} @@ -151,16 +151,16 @@ func (gdw *NaiveDiffDriver) Changes(id string, idMappings *idtools.IDMappings, p // ApplyDiff extracts the changeset from the given diff into the // layer with the specified id and parent, returning the size of the // new layer in bytes. -func (gdw *NaiveDiffDriver) ApplyDiff(id string, applyMappings *idtools.IDMappings, parent, mountLabel string, diff io.Reader) (size int64, err error) { +func (gdw *NaiveDiffDriver) ApplyDiff(id, parent string, options ApplyDiffOpts) (size int64, err error) { driver := gdw.ProtoDriver - if applyMappings == nil { - applyMappings = &idtools.IDMappings{} + if options.Mappings == nil { + options.Mappings = &idtools.IDMappings{} } // Mount the root filesystem so we can apply the diff/layer. mountOpts := MountOpts{ - MountLabel: mountLabel, + MountLabel: options.MountLabel, } layerFs, err := driver.Get(id, mountOpts) if err != nil { @@ -168,16 +168,17 @@ func (gdw *NaiveDiffDriver) ApplyDiff(id string, applyMappings *idtools.IDMappin } defer driver.Put(id) - options := &archive.TarOptions{ - InUserNS: rsystem.RunningInUserNS(), + tarOptions := &archive.TarOptions{ + InUserNS: rsystem.RunningInUserNS(), + IgnoreChownErrors: options.IgnoreChownErrors, } - if applyMappings != nil { - options.UIDMaps = applyMappings.UIDs() - options.GIDMaps = applyMappings.GIDs() + if options.Mappings != nil { + tarOptions.UIDMaps = options.Mappings.UIDs() + tarOptions.GIDMaps = options.Mappings.GIDs() } start := time.Now().UTC() logrus.Debug("Start untar layer") - if size, err = ApplyUncompressedLayer(layerFs, diff, options); err != nil { + if size, err = ApplyUncompressedLayer(layerFs, options.Diff, tarOptions); err != nil { logrus.Errorf("Error while applying layer: %s", err) return } diff --git a/vendor/github.com/containers/storage/drivers/graphtest/graphbench_unix.go b/vendor/github.com/containers/storage/drivers/graphtest/graphbench_unix.go index 1895103760..d7343a0a4d 100644 --- a/vendor/github.com/containers/storage/drivers/graphtest/graphbench_unix.go +++ b/vendor/github.com/containers/storage/drivers/graphtest/graphbench_unix.go @@ -165,7 +165,7 @@ func DriverBenchDiffApplyN(b *testing.B, fileCount int, drivername string, drive b.Fatal(err) } - applyDiffSize, err := driver.ApplyDiff(diff, nil, "", "", arch) + applyDiffSize, err := driver.ApplyDiff(diff, "", graphdriver.ApplyDiffOpts{}) if err != nil { b.Fatal(err) } diff --git a/vendor/github.com/containers/storage/drivers/graphtest/graphtest_unix.go b/vendor/github.com/containers/storage/drivers/graphtest/graphtest_unix.go index 4c18d10a2e..4e27ae82be 100644 --- a/vendor/github.com/containers/storage/drivers/graphtest/graphtest_unix.go +++ b/vendor/github.com/containers/storage/drivers/graphtest/graphtest_unix.go @@ -14,7 +14,7 @@ import ( "testing" "unsafe" - "github.com/containers/storage/drivers" + graphdriver "github.com/containers/storage/drivers" "github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/stringid" "github.com/docker/go-units" @@ -340,7 +340,7 @@ func DriverTestDiffApply(t testing.TB, fileCount int, drivername string, driverO t.Fatal(err) } - applyDiffSize, err := driver.ApplyDiff(diff, nil, base, "", bytes.NewReader(buf.Bytes())) + applyDiffSize, err := driver.ApplyDiff(diff, base, graphdriver.ApplyDiffOpts{Diff: bytes.NewReader(buf.Bytes())}) if err != nil { t.Fatal(err) } diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index d1fbc342ea..d70487ea76 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -85,12 +85,13 @@ const ( ) type overlayOptions struct { - imageStores []string - quota quota.Quota - mountProgram string - ostreeRepo string - skipMountHome bool - mountOptions string + imageStores []string + quota quota.Quota + mountProgram string + ostreeRepo string + skipMountHome bool + mountOptions string + ignoreChownErrors bool } // Driver contains information about the home directory and the list of active mounts that are created using this driver. @@ -253,8 +254,7 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) convert: make(map[string]bool), } - d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, d) - + d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, graphdriver.NewNaiveLayerIDMapUpdater(d)) if backingFs == "xfs" { // Try to enable project quota support over xfs. if d.quotaCtl, err = quota.NewControl(home); err == nil { @@ -322,6 +322,12 @@ func parseOptions(options []string) (*overlayOptions, error) { return nil, fmt.Errorf("overlay: ostree_repo specified but support for ostree is missing") } o.ostreeRepo = val + case "overlay2.ignore_chown_errors", "overlay.ignore_chown_errors": + logrus.Debugf("overlay: ignore_chown_errors=%s", val) + o.ignoreChownErrors, err = strconv.ParseBool(val) + if err != nil { + return nil, err + } case "overlay2.skip_mount_home", "overlay.skip_mount_home", ".skip_mount_home": logrus.Debugf("overlay: skip_mount_home=%s", val) o.skipMountHome, err = strconv.ParseBool(val) @@ -1062,11 +1068,16 @@ func (d *Driver) getWhiteoutFormat() archive.WhiteoutFormat { } // ApplyDiff applies the new layer into a root -func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent string, mountLabel string, diff io.Reader) (size int64, err error) { +func (d *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts) (size int64, err error) { + if !d.isParent(id, parent) { - return d.naiveDiff.ApplyDiff(id, idMappings, parent, mountLabel, diff) + if d.options.ignoreChownErrors { + options.IgnoreChownErrors = d.options.ignoreChownErrors + } + return d.naiveDiff.ApplyDiff(id, parent, options) } + idMappings := options.Mappings if idMappings == nil { idMappings = &idtools.IDMappings{} } @@ -1075,11 +1086,12 @@ func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent str logrus.Debugf("Applying tar in %s", applyDir) // Overlay doesn't need the parent id to apply the diff - if err := untar(diff, applyDir, &archive.TarOptions{ - UIDMaps: idMappings.UIDs(), - GIDMaps: idMappings.GIDs(), - WhiteoutFormat: d.getWhiteoutFormat(), - InUserNS: rsystem.RunningInUserNS(), + if err := untar(options.Diff, applyDir, &archive.TarOptions{ + UIDMaps: idMappings.UIDs(), + GIDMaps: idMappings.GIDs(), + IgnoreChownErrors: d.options.ignoreChownErrors, + WhiteoutFormat: d.getWhiteoutFormat(), + InUserNS: rsystem.RunningInUserNS(), }); err != nil { return 0, err } diff --git a/vendor/github.com/containers/storage/drivers/template.go b/vendor/github.com/containers/storage/drivers/template.go index dfcbffb83e..5d80b88659 100644 --- a/vendor/github.com/containers/storage/drivers/template.go +++ b/vendor/github.com/containers/storage/drivers/template.go @@ -35,7 +35,14 @@ func NaiveCreateFromTemplate(d TemplateDriver, id, template string, templateIDMa } return err } - if _, err = d.ApplyDiff(id, templateIDMappings, parent, opts.MountLabel, diff); err != nil { + + applyOptions := ApplyDiffOpts{ + Diff: diff, + Mappings: templateIDMappings, + MountLabel: opts.MountLabel, + IgnoreChownErrors: opts.ignoreChownErrors, + } + if _, err = d.ApplyDiff(id, parent, applyOptions); err != nil { if err2 := d.Remove(id); err2 != nil { logrus.Errorf("error removing layer %q: %v", id, err2) } diff --git a/vendor/github.com/containers/storage/drivers/vfs/driver.go b/vendor/github.com/containers/storage/drivers/vfs/driver.go index 5218c4432a..fe02a711ee 100644 --- a/vendor/github.com/containers/storage/drivers/vfs/driver.go +++ b/vendor/github.com/containers/storage/drivers/vfs/driver.go @@ -2,15 +2,20 @@ package vfs import ( "fmt" + "io" "os" "path/filepath" + "strconv" "strings" "github.com/containers/storage/drivers" + "github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/ostree" + "github.com/containers/storage/pkg/parsers" "github.com/containers/storage/pkg/system" "github.com/opencontainers/selinux/go-selinux/label" + "github.com/sirupsen/logrus" ) var ( @@ -26,36 +31,42 @@ func init() { // This sets the home directory for the driver and returns NaiveDiffDriver. func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) { d := &Driver{ + name: "vfs", homes: []string{home}, idMappings: idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps), } + rootIDs := d.idMappings.RootPair() if err := idtools.MkdirAllAndChown(home, 0700, rootIDs); err != nil { return nil, err } for _, option := range options.DriverOptions { - if strings.HasPrefix(option, "vfs.imagestore=") { - d.homes = append(d.homes, strings.Split(option[15:], ",")...) - continue + + key, val, err := parsers.ParseKeyValueOpt(option) + if err != nil { + return nil, err } - if strings.HasPrefix(option, ".imagestore=") { - d.homes = append(d.homes, strings.Split(option[12:], ",")...) + key = strings.ToLower(key) + switch key { + case "vfs.imagestore", ".imagestore": + d.homes = append(d.homes, strings.Split(val, ",")...) continue - } - if strings.HasPrefix(option, "vfs.ostree_repo=") { + case "vfs.ostree_repo", ".ostree_repo": if !ostree.OstreeSupport() { return nil, fmt.Errorf("vfs: ostree_repo specified but support for ostree is missing") } - d.ostreeRepo = option[16:] - } - if strings.HasPrefix(option, ".ostree_repo=") { - if !ostree.OstreeSupport() { - return nil, fmt.Errorf("vfs: ostree_repo specified but support for ostree is missing") - } - d.ostreeRepo = option[13:] - } - if strings.HasPrefix(option, "vfs.mountopt=") { + d.ostreeRepo = val + case "vfs.mountopt": return nil, fmt.Errorf("vfs driver does not support mount options") + case "vfs.ignore_chown_errors": + logrus.Debugf("vfs: ignore_chown_errors=%s", val) + var err error + d.ignoreChownErrors, err = strconv.ParseBool(val) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("vfs driver does not support %s options", key) } } if d.ostreeRepo != "" { @@ -67,7 +78,10 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) return nil, err } } - return graphdriver.NewNaiveDiffDriver(d, graphdriver.NewNaiveLayerIDMapUpdater(d)), nil + d.updater = graphdriver.NewNaiveLayerIDMapUpdater(d) + d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, d.updater) + + return d, nil } // Driver holds information about the driver, home directory of the driver. @@ -75,9 +89,13 @@ func Init(home string, options graphdriver.Options) (graphdriver.Driver, error) // In order to support layering, files are copied from the parent layer into the new layer. There is no copy-on-write support. // Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver type Driver struct { - homes []string - idMappings *idtools.IDMappings - ostreeRepo string + name string + homes []string + idMappings *idtools.IDMappings + ostreeRepo string + ignoreChownErrors bool + naiveDiff graphdriver.DiffDriver + updater graphdriver.LayerIDMapUpdater } func (d *Driver) String() string { @@ -107,6 +125,14 @@ func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idt return d.Create(id, template, opts) } +// ApplyDiff applies the new layer into a root +func (d *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts) (size int64, err error) { + if d.ignoreChownErrors { + options.IgnoreChownErrors = d.ignoreChownErrors + } + return d.naiveDiff.ApplyDiff(id, parent, options) +} + // CreateReadWrite creates a layer that is writable for use as a container // file system. func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error { @@ -231,3 +257,33 @@ func (d *Driver) AdditionalImageStores() []string { } return nil } + +// SupportsShifting tells whether the driver support shifting of the UIDs/GIDs in an userNS +func (d *Driver) SupportsShifting() bool { + return d.updater.SupportsShifting() +} + +// UpdateLayerIDMap updates ID mappings in a from matching the ones specified +// by toContainer to those specified by toHost. +func (d *Driver) UpdateLayerIDMap(id string, toContainer, toHost *idtools.IDMappings, mountLabel string) error { + return d.updater.UpdateLayerIDMap(id, toContainer, toHost, mountLabel) +} + +// Changes produces a list of changes between the specified layer +// and its parent layer. If parent is "", then all changes will be ADD changes. +func (d *Driver) Changes(id string, idMappings *idtools.IDMappings, parent string, parentMappings *idtools.IDMappings, mountLabel string) ([]archive.Change, error) { + return d.naiveDiff.Changes(id, idMappings, parent, parentMappings, mountLabel) +} + +// Diff produces an archive of the changes between the specified +// layer and its parent layer which may be "". +func (d *Driver) Diff(id string, idMappings *idtools.IDMappings, parent string, parentMappings *idtools.IDMappings, mountLabel string) (io.ReadCloser, error) { + return d.naiveDiff.Diff(id, idMappings, parent, parentMappings, mountLabel) +} + +// DiffSize calculates the changes between the specified id +// and its parent and returns the size in bytes of the changes +// relative to its base filesystem directory. +func (d *Driver) DiffSize(id string, idMappings *idtools.IDMappings, parent string, parentMappings *idtools.IDMappings, mountLabel string) (size int64, err error) { + return d.naiveDiff.DiffSize(id, idMappings, parent, parentMappings, mountLabel) +} diff --git a/vendor/github.com/containers/storage/drivers/windows/windows.go b/vendor/github.com/containers/storage/drivers/windows/windows.go index f0437a275b..11f1c98b1f 100644 --- a/vendor/github.com/containers/storage/drivers/windows/windows.go +++ b/vendor/github.com/containers/storage/drivers/windows/windows.go @@ -581,7 +581,7 @@ func (d *Driver) Changes(id string, idMappings *idtools.IDMappings, parent strin // layer with the specified id and parent, returning the size of the // new layer in bytes. // The layer should not be mounted when calling this function -func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent, mountLabel string, diff io.Reader) (int64, error) { +func (d *Driver) ApplyDiff(id, parent string, options graphdriver.ApplyDiffOpts) (int64, error) { panicIfUsedByLcow() var layerChain []string if parent != "" { @@ -601,7 +601,7 @@ func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent, mo layerChain = append(layerChain, parentChain...) } - size, err := d.importLayer(id, diff, layerChain) + size, err := d.importLayer(id, options.Diff, layerChain) if err != nil { return 0, err } diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index ce5d979170..4ef5672103 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -387,6 +387,19 @@ func (r *layerStore) loadMounts() error { } layerMounts := []layerMountPoint{} if err = json.Unmarshal(data, &layerMounts); len(data) == 0 || err == nil { + // Clear all of our mount information. If another process + // unmounted something, it (along with its zero count) won't + // have been encoded into the version of mountpoints.json that + // we're loading, so our count could fall out of sync with it + // if we don't, and if we subsequently change something else, + // we'd pass that error along to other process that reloaded + // the data after we saved it. + for _, layer := range r.layers { + layer.MountPoint = "" + layer.MountCount = 0 + } + // All of the non-zero count values will have been encoded, so + // we reset the still-mounted ones based on the contents. for _, mount := range layerMounts { if mount.MountPoint != "" { if layer, ok := r.lookup(mount.ID); ok { @@ -1261,7 +1274,12 @@ func (r *layerStore) ApplyDiff(to string, diff io.Reader) (size int64, err error if err != nil { return -1, err } - size, err = r.driver.ApplyDiff(layer.ID, r.layerMappings(layer), layer.Parent, layer.MountLabel, payload) + options := drivers.ApplyDiffOpts{ + Diff: payload, + Mappings: r.layerMappings(layer), + MountLabel: layer.MountLabel, + } + size, err = r.driver.ApplyDiff(layer.ID, layer.Parent, options) if err != nil { return -1, err } diff --git a/vendor/github.com/containers/storage/pkg/archive/archive.go b/vendor/github.com/containers/storage/pkg/archive/archive.go index a90ae1e9e9..20f017e64a 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive.go @@ -36,14 +36,15 @@ type ( // TarOptions wraps the tar options. TarOptions struct { - IncludeFiles []string - ExcludePatterns []string - Compression Compression - NoLchown bool - UIDMaps []idtools.IDMap - GIDMaps []idtools.IDMap - ChownOpts *idtools.IDPair - IncludeSourceDir bool + IncludeFiles []string + ExcludePatterns []string + Compression Compression + NoLchown bool + UIDMaps []idtools.IDMap + GIDMaps []idtools.IDMap + IgnoreChownErrors bool + ChownOpts *idtools.IDPair + IncludeSourceDir bool // WhiteoutFormat is the expected on disk format for whiteout files. // This format will be converted to the standard format on pack // and from the standard format on unpack. @@ -563,7 +564,7 @@ func (ta *tarAppender) addTarFile(path, name string) error { return nil } -func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.IDPair, inUserns bool) error { +func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.IDPair, inUserns, ignoreChownErrors bool) error { // hdr.Mode is in linux format, which we can use for sycalls, // but for os.Foo() calls we need the mode converted to os.FileMode, // so use hdrInfo.Mode() (they differ for e.g. setuid bits) @@ -645,8 +646,13 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L if chownOpts == nil { chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid} } - if err := idtools.SafeLchown(path, chownOpts.UID, chownOpts.GID); err != nil { - return err + err := idtools.SafeLchown(path, chownOpts.UID, chownOpts.GID) + if err != nil { + if ignoreChownErrors { + fmt.Fprintf(os.Stderr, "Chown error detected. Ignoring due to ignoreChownErrors flag: %v\n", err) + } else { + return err + } } } @@ -993,7 +999,7 @@ loop: chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid} } - if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, chownOpts, options.InUserNS); err != nil { + if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, chownOpts, options.InUserNS, options.IgnoreChownErrors); err != nil { return err } diff --git a/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go b/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go index 9b8103e4da..05aae4c136 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive_ffjson.go @@ -445,6 +445,11 @@ func (j *TarOptions) MarshalJSONBuf(buf fflib.EncodingBuffer) error { } else { buf.WriteString(`null`) } + if j.IgnoreChownErrors { + buf.WriteString(`,"IgnoreChownErrors":true`) + } else { + buf.WriteString(`,"IgnoreChownErrors":false`) + } if j.ChownOpts != nil { /* Struct fall back. type=idtools.IDPair kind=struct */ buf.WriteString(`,"ChownOpts":`) @@ -516,6 +521,8 @@ const ( ffjtTarOptionsGIDMaps + ffjtTarOptionsIgnoreChownErrors + ffjtTarOptionsChownOpts ffjtTarOptionsIncludeSourceDir @@ -545,6 +552,8 @@ var ffjKeyTarOptionsUIDMaps = []byte("UIDMaps") var ffjKeyTarOptionsGIDMaps = []byte("GIDMaps") +var ffjKeyTarOptionsIgnoreChownErrors = []byte("IgnoreChownErrors") + var ffjKeyTarOptionsChownOpts = []byte("ChownOpts") var ffjKeyTarOptionsIncludeSourceDir = []byte("IncludeSourceDir") @@ -663,6 +672,11 @@ mainparse: state = fflib.FFParse_want_colon goto mainparse + } else if bytes.Equal(ffjKeyTarOptionsIgnoreChownErrors, kn) { + currentKey = ffjtTarOptionsIgnoreChownErrors + state = fflib.FFParse_want_colon + goto mainparse + } else if bytes.Equal(ffjKeyTarOptionsIncludeSourceDir, kn) { currentKey = ffjtTarOptionsIncludeSourceDir state = fflib.FFParse_want_colon @@ -766,6 +780,12 @@ mainparse: goto mainparse } + if fflib.EqualFoldRight(ffjKeyTarOptionsIgnoreChownErrors, kn) { + currentKey = ffjtTarOptionsIgnoreChownErrors + state = fflib.FFParse_want_colon + goto mainparse + } + if fflib.EqualFoldRight(ffjKeyTarOptionsGIDMaps, kn) { currentKey = ffjtTarOptionsGIDMaps state = fflib.FFParse_want_colon @@ -837,6 +857,9 @@ mainparse: case ffjtTarOptionsGIDMaps: goto handle_GIDMaps + case ffjtTarOptionsIgnoreChownErrors: + goto handle_IgnoreChownErrors + case ffjtTarOptionsChownOpts: goto handle_ChownOpts @@ -1224,6 +1247,41 @@ handle_GIDMaps: state = fflib.FFParse_after_value goto mainparse +handle_IgnoreChownErrors: + + /* handler: j.IgnoreChownErrors type=bool kind=bool quoted=false*/ + + { + if tok != fflib.FFTok_bool && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for bool", tok)) + } + } + + { + if tok == fflib.FFTok_null { + + } else { + tmpb := fs.Output.Bytes() + + if bytes.Compare([]byte{'t', 'r', 'u', 'e'}, tmpb) == 0 { + + j.IgnoreChownErrors = true + + } else if bytes.Compare([]byte{'f', 'a', 'l', 's', 'e'}, tmpb) == 0 { + + j.IgnoreChownErrors = false + + } else { + err = errors.New("unexpected bytes for true/false value") + return fs.WrapErr(err) + } + + } + } + + state = fflib.FFParse_after_value + goto mainparse + handle_ChownOpts: /* handler: j.ChownOpts type=idtools.IDPair kind=struct quoted=false*/ diff --git a/vendor/github.com/containers/storage/pkg/archive/archive_test.go b/vendor/github.com/containers/storage/pkg/archive/archive_test.go index 8f7fb7ec24..dd35be1d8b 100644 --- a/vendor/github.com/containers/storage/pkg/archive/archive_test.go +++ b/vendor/github.com/containers/storage/pkg/archive/archive_test.go @@ -828,7 +828,7 @@ func TestTypeXGlobalHeaderDoesNotFail(t *testing.T) { t.Fatal(err) } defer os.RemoveAll(tmpDir) - err = createTarFile(filepath.Join(tmpDir, "pax_global_header"), tmpDir, &hdr, nil, true, nil, false) + err = createTarFile(filepath.Join(tmpDir, "pax_global_header"), tmpDir, &hdr, nil, true, nil, false, false) if err != nil { t.Fatal(err) } diff --git a/vendor/github.com/containers/storage/pkg/archive/diff.go b/vendor/github.com/containers/storage/pkg/archive/diff.go index eb1f2b4c80..b8ec876dd2 100644 --- a/vendor/github.com/containers/storage/pkg/archive/diff.go +++ b/vendor/github.com/containers/storage/pkg/archive/diff.go @@ -105,7 +105,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, } defer os.RemoveAll(aufsTempdir) } - if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil, options.InUserNS); err != nil { + if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil, options.InUserNS, options.IgnoreChownErrors); err != nil { return 0, err } } @@ -196,7 +196,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, return 0, err } - if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS); err != nil { + if err := createTarFile(path, dest, srcHdr, srcData, true, nil, options.InUserNS, options.IgnoreChownErrors); err != nil { return 0, err } diff --git a/vendor/github.com/containers/storage/pkg/config/config.go b/vendor/github.com/containers/storage/pkg/config/config.go index bdb5fbcb84..c53f704219 100644 --- a/vendor/github.com/containers/storage/pkg/config/config.go +++ b/vendor/github.com/containers/storage/pkg/config/config.go @@ -73,6 +73,9 @@ type OptionsConfig struct { RemapUIDs string `toml:"remap-uids"` // RemapGIDs is a list of default GID mappings to use for layers. RemapGIDs string `toml:"remap-gids"` + // IgnoreChownErrors is a flag for whether chown errors should be + // ignored when building an image. + IgnoreChownErrors string `toml:"ignore_chown_errors"` // RemapUser is the name of one or more entries in /etc/subuid which // should be used to set up default UID mappings. diff --git a/vendor/github.com/containers/storage/storage.conf b/vendor/github.com/containers/storage/storage.conf index 8b63e3ea81..3e7bf62f06 100644 --- a/vendor/github.com/containers/storage/storage.conf +++ b/vendor/github.com/containers/storage/storage.conf @@ -32,6 +32,14 @@ size = "" # mountopt specifies comma separated list of extra mount options mountopt = "nodev" +# ignore_chown_errors can be set to allow a non privileged user running with +# a single UID within a user namespace to run containers. The user can pull +# and use any image even those with multiple uids. Note multiple UIDs will be +# squasheddown to the default uid in the container. These images will have no +# separation between the users in the container. Only supported for the overlay +# and vfs drivers. +#ignore_chown_errors = false + # Remap-UIDs/GIDs is the mapping from UIDs/GIDs as they should appear inside of # a container, to the UIDs/GIDs as they should appear outside of the container, # and the length of the range of UIDs/GIDs. Additional mapped sets can be diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index 46076e07e5..74275482b7 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -3357,6 +3357,9 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) { if config.Storage.Options.MountProgram != "" { storeOptions.GraphDriverOptions = append(storeOptions.GraphDriverOptions, fmt.Sprintf("%s.mount_program=%s", config.Storage.Driver, config.Storage.Options.MountProgram)) } + if config.Storage.Options.IgnoreChownErrors != "" { + storeOptions.GraphDriverOptions = append(storeOptions.GraphDriverOptions, fmt.Sprintf("%s.ignore_chown_errors=%s", config.Storage.Driver, config.Storage.Options.IgnoreChownErrors)) + } if config.Storage.Options.MountOpt != "" { storeOptions.GraphDriverOptions = append(storeOptions.GraphDriverOptions, fmt.Sprintf("%s.mountopt=%s", config.Storage.Driver, config.Storage.Options.MountOpt)) } diff --git a/vendor/github.com/docker/libtrust/README.md b/vendor/github.com/docker/libtrust/README.md index 8e7db38186..dcffb31ae4 100644 --- a/vendor/github.com/docker/libtrust/README.md +++ b/vendor/github.com/docker/libtrust/README.md @@ -1,5 +1,9 @@ # libtrust +> **WARNING** this library is no longer actively developed, and will be integrated +> in the [docker/distribution][https://www.github.com/docker/distribution] +> repository in future. + Libtrust is library for managing authentication and authorization using public key cryptography. Authentication is handled using the identity attached to the public key. diff --git a/vendor/github.com/docker/libtrust/util.go b/vendor/github.com/docker/libtrust/util.go index d88176cc3d..a5a101d3f1 100644 --- a/vendor/github.com/docker/libtrust/util.go +++ b/vendor/github.com/docker/libtrust/util.go @@ -152,7 +152,7 @@ func NewIdentityAuthTLSClientConfig(dockerUrl string, trustUnknownHosts bool, ro } // joseBase64UrlEncode encodes the given data using the standard base64 url -// encoding format but with all trailing '=' characters ommitted in accordance +// encoding format but with all trailing '=' characters omitted in accordance // with the jose specification. // http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2 func joseBase64UrlEncode(b []byte) string { diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md index 21205eaeb5..9d92c11f16 100644 --- a/vendor/github.com/google/uuid/README.md +++ b/vendor/github.com/google/uuid/README.md @@ -1,7 +1,3 @@ -**This package is currently in development and the API may not be stable.** - -The API will become stable with v1. - # uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) diff --git a/vendor/github.com/google/uuid/go.mod b/vendor/github.com/google/uuid/go.mod new file mode 100644 index 0000000000..fc84cd79d4 --- /dev/null +++ b/vendor/github.com/google/uuid/go.mod @@ -0,0 +1 @@ +module github.com/google/uuid diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go index 4fc5a77df5..b174616315 100644 --- a/vendor/github.com/google/uuid/hash.go +++ b/vendor/github.com/google/uuid/hash.go @@ -27,7 +27,7 @@ var ( func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { h.Reset() h.Write(space[:]) - h.Write([]byte(data)) + h.Write(data) s := h.Sum(nil) var uuid UUID copy(uuid[:], s) diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go index 84bbc5880b..7f9e0c6c0e 100644 --- a/vendor/github.com/google/uuid/marshal.go +++ b/vendor/github.com/google/uuid/marshal.go @@ -15,8 +15,6 @@ func (uuid UUID) MarshalText() ([]byte, error) { // UnmarshalText implements encoding.TextUnmarshaler. func (uuid *UUID) UnmarshalText(data []byte) error { - // See comment in ParseBytes why we do this. - // id, err := ParseBytes(data) id, err := ParseBytes(data) if err == nil { *uuid = id diff --git a/vendor/github.com/google/uuid/node.go b/vendor/github.com/google/uuid/node.go index f2c2765b22..d651a2b061 100644 --- a/vendor/github.com/google/uuid/node.go +++ b/vendor/github.com/google/uuid/node.go @@ -5,16 +5,14 @@ package uuid import ( - "net" "sync" ) var ( - nodeMu sync.Mutex - interfaces []net.Interface // cached list of interfaces - ifname string // name of interface being used - nodeID [6]byte // hardware for version 1 UUIDs - zeroID [6]byte // nodeID with only 0's + nodeMu sync.Mutex + ifname string // name of interface being used + nodeID [6]byte // hardware for version 1 UUIDs + zeroID [6]byte // nodeID with only 0's ) // NodeInterface returns the name of the interface from which the NodeID was @@ -39,26 +37,18 @@ func SetNodeInterface(name string) bool { } func setNodeInterface(name string) bool { - if interfaces == nil { - var err error - interfaces, err = net.Interfaces() - if err != nil && name != "" { - return false - } - } - - for _, ifs := range interfaces { - if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { - copy(nodeID[:], ifs.HardwareAddr) - ifname = ifs.Name - return true - } + iname, addr := getHardwareInterface(name) // null implementation for js + if iname != "" && addr != nil { + ifname = iname + copy(nodeID[:], addr) + return true } // We found no interfaces with a valid hardware address. If name // does not specify a specific interface generate a random Node ID // (section 4.1.6) if name == "" { + ifname = "random" randomBits(nodeID[:]) return true } diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go new file mode 100644 index 0000000000..24b78edc90 --- /dev/null +++ b/vendor/github.com/google/uuid/node_js.go @@ -0,0 +1,12 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build js + +package uuid + +// getHardwareInterface returns nil values for the JS version of the code. +// This remvoves the "net" dependency, because it is not used in the browser. +// Using the "net" library inflates the size of the transpiled JS code by 673k bytes. +func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/vendor/github.com/google/uuid/node_net.go b/vendor/github.com/google/uuid/node_net.go new file mode 100644 index 0000000000..0cbbcddbd6 --- /dev/null +++ b/vendor/github.com/google/uuid/node_net.go @@ -0,0 +1,33 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !js + +package uuid + +import "net" + +var interfaces []net.Interface // cached list of interfaces + +// getHardwareInterface returns the name and hardware address of interface name. +// If name is "" then the name and hardware address of one of the system's +// interfaces is returned. If no interfaces are found (name does not exist or +// there are no interfaces) then "", nil is returned. +// +// Only addresses of at least 6 bytes are returned. +func getHardwareInterface(name string) (string, []byte) { + if interfaces == nil { + var err error + interfaces, err = net.Interfaces() + if err != nil { + return "", nil + } + } + for _, ifs := range interfaces { + if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { + return ifs.Name, ifs.HardwareAddr + } + } + return "", nil +} diff --git a/vendor/github.com/google/uuid/seq_test.go b/vendor/github.com/google/uuid/seq_test.go index 853a4aa3f3..4f6c549125 100644 --- a/vendor/github.com/google/uuid/seq_test.go +++ b/vendor/github.com/google/uuid/seq_test.go @@ -16,7 +16,7 @@ var regressions = flag.Bool("regressions", false, "run uuid regression tests") // TestClockSeqRace tests for a particular race condition of returning two // identical Version1 UUIDs. The duration of 1 minute was chosen as the race -// condition, before being fixed, nearly always occured in under 30 seconds. +// condition, before being fixed, nearly always occurred in under 30 seconds. func TestClockSeqRace(t *testing.T) { if !*regressions { t.Skip("skipping regression tests") diff --git a/vendor/github.com/google/uuid/sql_test.go b/vendor/github.com/google/uuid/sql_test.go index 4fbd01bd7d..1803dfd879 100644 --- a/vendor/github.com/google/uuid/sql_test.go +++ b/vendor/github.com/google/uuid/sql_test.go @@ -10,9 +10,9 @@ import ( ) func TestScan(t *testing.T) { - var stringTest string = "f47ac10b-58cc-0372-8567-0e02b2c3d479" - var badTypeTest int = 6 - var invalidTest string = "f47ac10b-58cc-0372-8567-0e02b2c3d4" + stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479" + badTypeTest := 6 + invalidTest := "f47ac10b-58cc-0372-8567-0e02b2c3d4" byteTest := make([]byte, 16) byteTestUUID := Must(Parse(stringTest)) diff --git a/vendor/github.com/google/uuid/time.go b/vendor/github.com/google/uuid/time.go index fd7fe0ac46..e6ef06cdc8 100644 --- a/vendor/github.com/google/uuid/time.go +++ b/vendor/github.com/google/uuid/time.go @@ -86,7 +86,7 @@ func clockSequence() int { return int(clockSeq & 0x3fff) } -// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to +// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to // -1 causes a new sequence to be generated. func SetClockSequence(seq int) { defer timeMu.Unlock() @@ -100,9 +100,9 @@ func setClockSequence(seq int) { randomBits(b[:]) // clock sequence seq = int(b[0])<<8 | int(b[1]) } - old_seq := clockSeq + oldSeq := clockSeq clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant - if old_seq != clockSeq { + if oldSeq != clockSeq { lasttime = 0 } } diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go index 1320d60d80..524404cc52 100644 --- a/vendor/github.com/google/uuid/uuid.go +++ b/vendor/github.com/google/uuid/uuid.go @@ -1,4 +1,4 @@ -// Copyright 2016 Google Inc. All rights reserved. +// Copyright 2018 Google Inc. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -35,20 +35,43 @@ const ( var rander = rand.Reader // random function -// Parse decodes s into a UUID or returns an error. Both the UUID form of -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded. +// Parse decodes s into a UUID or returns an error. Both the standard UUID +// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the +// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex +// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. func Parse(s string) (UUID, error) { var uuid UUID - if len(s) != 36 { - if len(s) != 36+9 { - return uuid, fmt.Errorf("invalid UUID length: %d", len(s)) - } + switch len(s) { + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36: + + // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: if strings.ToLower(s[:9]) != "urn:uuid:" { return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) } s = s[9:] + + // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + case 36 + 2: + s = s[1:] + + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + case 32: + var ok bool + for i := range uuid { + uuid[i], ok = xtob(s[i*2], s[i*2+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, fmt.Errorf("invalid UUID length: %d", len(s)) } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { return uuid, errors.New("invalid UUID format") } @@ -58,11 +81,11 @@ func Parse(s string) (UUID, error) { 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} { - if v, ok := xtob(s[x], s[x+1]); !ok { + v, ok := xtob(s[x], s[x+1]) + if !ok { return uuid, errors.New("invalid UUID format") - } else { - uuid[i] = v } + uuid[i] = v } return uuid, nil } @@ -70,15 +93,29 @@ func Parse(s string) (UUID, error) { // ParseBytes is like Parse, except it parses a byte slice instead of a string. func ParseBytes(b []byte) (UUID, error) { var uuid UUID - if len(b) != 36 { - if len(b) != 36+9 { - return uuid, fmt.Errorf("invalid UUID length: %d", len(b)) - } + switch len(b) { + case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) } b = b[9:] + case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + b = b[1:] + case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + var ok bool + for i := 0; i < 32; i += 2 { + uuid[i/2], ok = xtob(b[i], b[i+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, fmt.Errorf("invalid UUID length: %d", len(b)) } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { return uuid, errors.New("invalid UUID format") } @@ -88,15 +125,25 @@ func ParseBytes(b []byte) (UUID, error) { 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} { - if v, ok := xtob(b[x], b[x+1]); !ok { + v, ok := xtob(b[x], b[x+1]) + if !ok { return uuid, errors.New("invalid UUID format") - } else { - uuid[i] = v } + uuid[i] = v } return uuid, nil } +// MustParse is like Parse but panics if the string cannot be parsed. +// It simplifies safe initialization of global variables holding compiled UUIDs. +func MustParse(s string) UUID { + uuid, err := Parse(s) + if err != nil { + panic(`uuid: Parse(` + s + `): ` + err.Error()) + } + return uuid +} + // FromBytes creates a new UUID from a byte slice. Returns an error if the slice // does not have a length of 16. The bytes are copied from the slice. func FromBytes(b []byte) (uuid UUID, err error) { @@ -130,7 +177,7 @@ func (uuid UUID) URN() string { } func encodeHex(dst []byte, uuid UUID) { - hex.Encode(dst[:], uuid[:4]) + hex.Encode(dst, uuid[:4]) dst[8] = '-' hex.Encode(dst[9:13], uuid[4:6]) dst[13] = '-' diff --git a/vendor/github.com/google/uuid/uuid_test.go b/vendor/github.com/google/uuid/uuid_test.go index 3ecd8c2369..2a43fb13f0 100644 --- a/vendor/github.com/google/uuid/uuid_test.go +++ b/vendor/github.com/google/uuid/uuid_test.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" "os" + "runtime" "strings" "testing" "time" @@ -58,12 +59,22 @@ var tests = []test{ {"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true}, {"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true}, + {"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false}, {"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false}, {"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false}, {"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false}, {"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false}, {"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false}, + + + {"{f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, RFC4122, true}, + {"{f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, Invalid, false}, + {"f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, Invalid, false}, + + {"f47ac10b58cc037285670e02b2c3d479", 0, RFC4122, true}, + {"f47ac10b58cc037285670e02b2c3d4790", 0, Invalid, false}, + {"f47ac10b58cc037285670e02b2c3d47", 0, Invalid, false}, } var constants = []struct { @@ -305,7 +316,7 @@ func TestVersion1(t *testing.T) { case t1 > t2 && q1 == q2: t.Error("time reversed") case t1 < t2 && q1 != q2: - t.Error("clock sequence chaned unexpectedly") + t.Error("clock sequence changed unexpectedly") } } @@ -321,8 +332,10 @@ func TestNode(t *testing.T) { if !SetNodeInterface("") { t.Error("SetNodeInterface failed") } - if ni := NodeInterface(); ni == "" { - t.Error("NodeInterface returned an empty string") + if runtime.GOARCH != "js" { + if ni := NodeInterface(); ni == "" { + t.Error("NodeInterface returned an empty string") + } } ni := NodeID() @@ -347,7 +360,7 @@ func TestNode(t *testing.T) { } if ni := NodeInterface(); ni != "user" { - t.Errorf("got inteface %q, want %q", ni, "user") + t.Errorf("got interface %q, want %q", ni, "user") } } @@ -391,8 +404,10 @@ func TestNodeID(t *testing.T) { nid := []byte{1, 2, 3, 4, 5, 6} SetNodeInterface("") s := NodeInterface() - if s == "" || s == "user" { - t.Errorf("NodeInterface %q after SetInteface", s) + if runtime.GOARCH != "js" { + if s == "" || s == "user" { + t.Errorf("NodeInterface %q after SetInterface", s) + } } node1 := NodeID() if node1 == nil { @@ -443,7 +458,7 @@ func TestDCE(t *testing.T) { type badRand struct{} func (r badRand) Read(buf []byte) (int, error) { - for i, _ := range buf { + for i := range buf { buf[i] = byte(i) } return len(buf), nil @@ -454,13 +469,53 @@ func TestBadRand(t *testing.T) { uuid1 := New() uuid2 := New() if uuid1 != uuid2 { - t.Errorf("execpted duplicates, got %q and %q", uuid1, uuid2) + t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2) } SetRand(nil) uuid1 = New() uuid2 = New() if uuid1 == uuid2 { - t.Errorf("unexecpted duplicates, got %q", uuid1) + t.Errorf("unexpected duplicates, got %q", uuid1) + } +} + +func TestSetRand(t *testing.T) { + myString := "805-9dd6-1a877cb526c678e71d38-7122-44c0-9b7c-04e7001cc78783ac3e82-47a3-4cc3-9951-13f3339d88088f5d685a-11f7-4078-ada9-de44ad2daeb7" + + SetRand(strings.NewReader(myString)) + uuid1 := New() + uuid2 := New() + + SetRand(strings.NewReader(myString)) + uuid3 := New() + uuid4 := New() + + if uuid1 != uuid3 { + t.Errorf("expected duplicates, got %q and %q", uuid1, uuid3) + } + if uuid2 != uuid4 { + t.Errorf("expected duplicates, got %q and %q", uuid2, uuid4) + } +} + +func TestRandomFromReader(t *testing.T) { + myString := "8059ddhdle77cb52" + r := bytes.NewReader([]byte(myString)) + r2 := bytes.NewReader([]byte(myString)) + uuid1, err := NewRandomFromReader(r) + if err != nil { + t.Errorf("failed generating UUID from a reader") + } + _, err = NewRandomFromReader(r) + if err == nil { + t.Errorf("expecting an error as reader has no more bytes. Got uuid. NewRandomFromReader may not be using the provided reader") + } + uuid3, err := NewRandomFromReader(r2) + if err != nil { + t.Errorf("failed generating UUID from a reader") + } + if uuid1 != uuid3 { + t.Errorf("expected duplicates, got %q and %q", uuid1, uuid3) } } diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go index 74c4e6c9f5..9ad1abad02 100644 --- a/vendor/github.com/google/uuid/version4.go +++ b/vendor/github.com/google/uuid/version4.go @@ -14,7 +14,7 @@ func New() UUID { return Must(NewRandom()) } -// NewRandom returns a Random (Version 4) UUID or panics. +// NewRandom returns a Random (Version 4) UUID. // // The strength of the UUIDs is based on the strength of the crypto/rand // package. @@ -27,8 +27,12 @@ func New() UUID { // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() (UUID, error) { + return NewRandomFromReader(rander) +} + +func NewRandomFromReader(r io.Reader) (UUID, error) { var uuid UUID - _, err := io.ReadFull(rander, uuid[:]) + _, err := io.ReadFull(r, uuid[:]) if err != nil { return Nil, err } @@ -36,3 +40,4 @@ func NewRandom() (UUID, error) { uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 return uuid, nil } + diff --git a/vendor/github.com/gorilla/mux/.circleci/config.yml b/vendor/github.com/gorilla/mux/.circleci/config.yml new file mode 100644 index 0000000000..536bc119f6 --- /dev/null +++ b/vendor/github.com/gorilla/mux/.circleci/config.yml @@ -0,0 +1,87 @@ +version: 2.0 + +jobs: + # Base test configuration for Go library tests Each distinct version should + # inherit this base, and override (at least) the container image used. + "test": &test + docker: + - image: circleci/golang:latest + working_directory: /go/src/github.com/gorilla/mux + steps: &steps + # Our build steps: we checkout the repo, fetch our deps, lint, and finally + # run "go test" on the package. + - checkout + # Logs the version in our build logs, for posterity + - run: go version + - run: + name: "Fetch dependencies" + command: > + go get -t -v ./... + # Only run gofmt, vet & lint against the latest Go version + - run: + name: "Run golint" + command: > + if [ "${LATEST}" = true ] && [ -z "${SKIP_GOLINT}" ]; then + go get -u golang.org/x/lint/golint + golint ./... + fi + - run: + name: "Run gofmt" + command: > + if [[ "${LATEST}" = true ]]; then + diff -u <(echo -n) <(gofmt -d -e .) + fi + - run: + name: "Run go vet" + command: > + if [[ "${LATEST}" = true ]]; then + go vet -v ./... + fi + - run: go test -v -race ./... + + "latest": + <<: *test + environment: + LATEST: true + + "1.12": + <<: *test + docker: + - image: circleci/golang:1.12 + + "1.11": + <<: *test + docker: + - image: circleci/golang:1.11 + + "1.10": + <<: *test + docker: + - image: circleci/golang:1.10 + + "1.9": + <<: *test + docker: + - image: circleci/golang:1.9 + + "1.8": + <<: *test + docker: + - image: circleci/golang:1.8 + + "1.7": + <<: *test + docker: + - image: circleci/golang:1.7 + +workflows: + version: 2 + build: + jobs: + - "latest" + - "1.12" + - "1.11" + - "1.10" + - "1.9" + - "1.8" + - "1.7" diff --git a/vendor/github.com/gorilla/mux/.github/stale.yml b/vendor/github.com/gorilla/mux/.github/stale.yml index de8a67804b..f4b12d30ba 100644 --- a/vendor/github.com/gorilla/mux/.github/stale.yml +++ b/vendor/github.com/gorilla/mux/.github/stale.yml @@ -1,10 +1,10 @@ -daysUntilStale: 60 -daysUntilClose: 7 +daysUntilStale: 75 +daysUntilClose: 14 # Issues with these labels will never be considered stale exemptLabels: - - v2 - - needs-review - - work-required + - proposal + - needs review + - build system staleLabel: stale markComment: > This issue has been automatically marked as stale because it hasn't seen diff --git a/vendor/github.com/gorilla/mux/.travis.yml b/vendor/github.com/gorilla/mux/.travis.yml deleted file mode 100644 index 0e58a7297f..0000000000 --- a/vendor/github.com/gorilla/mux/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: go -sudo: false - -matrix: - include: - - go: 1.7.x - - go: 1.8.x - - go: 1.9.x - - go: 1.10.x - - go: 1.11.x - - go: 1.x - env: LATEST=true - - go: tip - allow_failures: - - go: tip - -install: - - # Skip - -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d .) - - if [[ "$LATEST" = true ]]; then go tool vet .; fi - - go test -v -race ./... diff --git a/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md b/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md deleted file mode 100644 index 232be82e47..0000000000 --- a/vendor/github.com/gorilla/mux/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,11 +0,0 @@ -**What version of Go are you running?** (Paste the output of `go version`) - - -**What version of gorilla/mux are you at?** (Paste the output of `git rev-parse HEAD` inside `$GOPATH/src/github.com/gorilla/mux`) - - -**Describe your problem** (and what you have tried so far) - - -**Paste a minimal, runnable, reproduction of your issue below** (use backticks to format it) - diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md index 9e99a2703c..28df9a9f2e 100644 --- a/vendor/github.com/gorilla/mux/README.md +++ b/vendor/github.com/gorilla/mux/README.md @@ -1,7 +1,7 @@ # gorilla/mux [![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux) -[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux) +[![CircleCI](https://circleci.com/gh/gorilla/mux.svg?style=svg)](https://circleci.com/gh/gorilla/mux) [![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge) ![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png) @@ -25,10 +25,12 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv * [Examples](#examples) * [Matching Routes](#matching-routes) * [Static Files](#static-files) +* [Serving Single Page Applications](#serving-single-page-applications) (e.g. React, Vue, Ember.js, etc.) * [Registered URLs](#registered-urls) * [Walking Routes](#walking-routes) * [Graceful Shutdown](#graceful-shutdown) * [Middleware](#middleware) +* [Handling CORS Requests](#handling-cors-requests) * [Testing Handlers](#testing-handlers) * [Full Example](#full-example) @@ -210,6 +212,93 @@ func main() { } ``` +### Serving Single Page Applications + +Most of the time it makes sense to serve your SPA on a separate web server from your API, +but sometimes it's desirable to serve them both from one place. It's possible to write a simple +handler for serving your SPA (for use with React Router's [BrowserRouter](https://reacttraining.com/react-router/web/api/BrowserRouter) for example), and leverage +mux's powerful routing for your API endpoints. + +```go +package main + +import ( + "encoding/json" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/gorilla/mux" +) + +// spaHandler implements the http.Handler interface, so we can use it +// to respond to HTTP requests. The path to the static directory and +// path to the index file within that static directory are used to +// serve the SPA in the given static directory. +type spaHandler struct { + staticPath string + indexPath string +} + +// ServeHTTP inspects the URL path to locate a file within the static dir +// on the SPA handler. If a file is found, it will be served. If not, the +// file located at the index path on the SPA handler will be served. This +// is suitable behavior for serving an SPA (single page application). +func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // get the absolute path to prevent directory traversal + path, err := filepath.Abs(r.URL.Path) + if err != nil { + // if we failed to get the absolute path respond with a 400 bad request + // and stop + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // prepend the path with the path to the static directory + path = filepath.Join(h.staticPath, path) + + // check whether a file exists at the given path + _, err = os.Stat(path) + if os.IsNotExist(err) { + // file does not exist, serve index.html + http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath)) + return + } else if err != nil { + // if we got an error (that wasn't that the file doesn't exist) stating the + // file, return a 500 internal server error and stop + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // otherwise, use http.FileServer to serve the static dir + http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r) +} + +func main() { + router := mux.NewRouter() + + router.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { + // an example API handler + json.NewEncoder(w).Encode(map[string]bool{"ok": true}) + }) + + spa := spaHandler{staticPath: "build", indexPath: "index.html"} + router.PathPrefix("/").Handler(spa) + + srv := &http.Server{ + Handler: router, + Addr: "127.0.0.1:8000", + // Good practice: enforce timeouts for servers you create! + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + log.Fatal(srv.ListenAndServe()) +} +``` + ### Registered URLs Now let's see how to build registered URLs. @@ -491,6 +580,73 @@ r.Use(amw.Middleware) Note: The handler chain will be stopped if your middleware doesn't call `next.ServeHTTP()` with the corresponding parameters. This can be used to abort a request if the middleware writer wants to. Middlewares _should_ write to `ResponseWriter` if they _are_ going to terminate the request, and they _should not_ write to `ResponseWriter` if they _are not_ going to terminate it. +### Handling CORS Requests + +[CORSMethodMiddleware](https://godoc.org/github.com/gorilla/mux#CORSMethodMiddleware) intends to make it easier to strictly set the `Access-Control-Allow-Methods` response header. + +* You will still need to use your own CORS handler to set the other CORS headers such as `Access-Control-Allow-Origin` +* The middleware will set the `Access-Control-Allow-Methods` header to all the method matchers (e.g. `r.Methods(http.MethodGet, http.MethodPut, http.MethodOptions)` -> `Access-Control-Allow-Methods: GET,PUT,OPTIONS`) on a route +* If you do not specify any methods, then: +> _Important_: there must be an `OPTIONS` method matcher for the middleware to set the headers. + +Here is an example of using `CORSMethodMiddleware` along with a custom `OPTIONS` handler to set all the required CORS headers: + +```go +package main + +import ( + "net/http" + "github.com/gorilla/mux" +) + +func main() { + r := mux.NewRouter() + + // IMPORTANT: you must specify an OPTIONS method matcher for the middleware to set CORS headers + r.HandleFunc("/foo", fooHandler).Methods(http.MethodGet, http.MethodPut, http.MethodPatch, http.MethodOptions) + r.Use(mux.CORSMethodMiddleware(r)) + + http.ListenAndServe(":8080", r) +} + +func fooHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + if r.Method == http.MethodOptions { + return + } + + w.Write([]byte("foo")) +} +``` + +And an request to `/foo` using something like: + +```bash +curl localhost:8080/foo -v +``` + +Would look like: + +```bash +* Trying ::1... +* TCP_NODELAY set +* Connected to localhost (::1) port 8080 (#0) +> GET /foo HTTP/1.1 +> Host: localhost:8080 +> User-Agent: curl/7.59.0 +> Accept: */* +> +< HTTP/1.1 200 OK +< Access-Control-Allow-Methods: GET,PUT,PATCH,OPTIONS +< Access-Control-Allow-Origin: * +< Date: Fri, 28 Jun 2019 20:13:30 GMT +< Content-Length: 3 +< Content-Type: text/plain; charset=utf-8 +< +* Connection #0 to host localhost left intact +foo +``` + ### Testing Handlers Testing handlers in a Go web application is straightforward, and _mux_ doesn't complicate this any further. Given two files: `endpoints.go` and `endpoints_test.go`, here's how we'd test an application using _mux_. @@ -503,8 +659,8 @@ package main func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { // A very simple health check. - w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) // In the future we could report back on the status of our DB, or our cache // (e.g. Redis) by performing a simple PING, and include them in the response. diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go index 38957deead..bd5a38b55d 100644 --- a/vendor/github.com/gorilla/mux/doc.go +++ b/vendor/github.com/gorilla/mux/doc.go @@ -295,7 +295,7 @@ A more complex authentication middleware, which maps session token to users, cou r := mux.NewRouter() r.HandleFunc("/", handler) - amw := authenticationMiddleware{} + amw := authenticationMiddleware{tokenUsers: make(map[string]string)} amw.Populate() r.Use(amw.Middleware) diff --git a/vendor/github.com/gorilla/mux/example_cors_method_middleware_test.go b/vendor/github.com/gorilla/mux/example_cors_method_middleware_test.go new file mode 100644 index 0000000000..00929fcee5 --- /dev/null +++ b/vendor/github.com/gorilla/mux/example_cors_method_middleware_test.go @@ -0,0 +1,37 @@ +package mux_test + +import ( + "fmt" + "net/http" + "net/http/httptest" + + "github.com/gorilla/mux" +) + +func ExampleCORSMethodMiddleware() { + r := mux.NewRouter() + + r.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) { + // Handle the request + }).Methods(http.MethodGet, http.MethodPut, http.MethodPatch) + r.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "http://example.com") + w.Header().Set("Access-Control-Max-Age", "86400") + }).Methods(http.MethodOptions) + + r.Use(mux.CORSMethodMiddleware(r)) + + rw := httptest.NewRecorder() + req, _ := http.NewRequest("OPTIONS", "/foo", nil) // needs to be OPTIONS + req.Header.Set("Access-Control-Request-Method", "POST") // needs to be non-empty + req.Header.Set("Access-Control-Request-Headers", "Authorization") // needs to be non-empty + req.Header.Set("Origin", "http://example.com") // needs to be non-empty + + r.ServeHTTP(rw, req) + + fmt.Println(rw.Header().Get("Access-Control-Allow-Methods")) + fmt.Println(rw.Header().Get("Access-Control-Allow-Origin")) + // Output: + // GET,PUT,PATCH,OPTIONS + // http://example.com +} diff --git a/vendor/github.com/gorilla/mux/go.mod b/vendor/github.com/gorilla/mux/go.mod index cfc8ede581..df170a3994 100644 --- a/vendor/github.com/gorilla/mux/go.mod +++ b/vendor/github.com/gorilla/mux/go.mod @@ -1 +1,3 @@ module github.com/gorilla/mux + +go 1.12 diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go index ceb812cee2..cf2b26dc03 100644 --- a/vendor/github.com/gorilla/mux/middleware.go +++ b/vendor/github.com/gorilla/mux/middleware.go @@ -32,37 +32,19 @@ func (r *Router) useInterface(mw middleware) { r.middlewares = append(r.middlewares, mw) } -// CORSMethodMiddleware sets the Access-Control-Allow-Methods response header -// on a request, by matching routes based only on paths. It also handles -// OPTIONS requests, by settings Access-Control-Allow-Methods, and then -// returning without calling the next http handler. +// CORSMethodMiddleware automatically sets the Access-Control-Allow-Methods response header +// on requests for routes that have an OPTIONS method matcher to all the method matchers on +// the route. Routes that do not explicitly handle OPTIONS requests will not be processed +// by the middleware. See examples for usage. func CORSMethodMiddleware(r *Router) MiddlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var allMethods []string - - err := r.Walk(func(route *Route, _ *Router, _ []*Route) error { - for _, m := range route.matchers { - if _, ok := m.(*routeRegexp); ok { - if m.Match(req, &RouteMatch{}) { - methods, err := route.GetMethods() - if err != nil { - return err - } - - allMethods = append(allMethods, methods...) - } - break - } - } - return nil - }) - + allMethods, err := getAllMethodsForRoute(r, req) if err == nil { - w.Header().Set("Access-Control-Allow-Methods", strings.Join(append(allMethods, "OPTIONS"), ",")) - - if req.Method == "OPTIONS" { - return + for _, v := range allMethods { + if v == http.MethodOptions { + w.Header().Set("Access-Control-Allow-Methods", strings.Join(allMethods, ",")) + } } } @@ -70,3 +52,28 @@ func CORSMethodMiddleware(r *Router) MiddlewareFunc { }) } } + +// getAllMethodsForRoute returns all the methods from method matchers matching a given +// request. +func getAllMethodsForRoute(r *Router, req *http.Request) ([]string, error) { + var allMethods []string + + err := r.Walk(func(route *Route, _ *Router, _ []*Route) error { + for _, m := range route.matchers { + if _, ok := m.(*routeRegexp); ok { + if m.Match(req, &RouteMatch{}) { + methods, err := route.GetMethods() + if err != nil { + return err + } + + allMethods = append(allMethods, methods...) + } + break + } + } + return nil + }) + + return allMethods, err +} diff --git a/vendor/github.com/gorilla/mux/middleware_test.go b/vendor/github.com/gorilla/mux/middleware_test.go index b708be0991..27647afe43 100644 --- a/vendor/github.com/gorilla/mux/middleware_test.go +++ b/vendor/github.com/gorilla/mux/middleware_test.go @@ -3,7 +3,6 @@ package mux import ( "bytes" "net/http" - "net/http/httptest" "testing" ) @@ -28,12 +27,12 @@ func TestMiddlewareAdd(t *testing.T) { router.useInterface(mw) if len(router.middlewares) != 1 || router.middlewares[0] != mw { - t.Fatal("Middleware was not added correctly") + t.Fatal("Middleware interface was not added correctly") } router.Use(mw.Middleware) if len(router.middlewares) != 2 { - t.Fatal("MiddlewareFunc method was not added correctly") + t.Fatal("Middleware method was not added correctly") } banalMw := func(handler http.Handler) http.Handler { @@ -41,7 +40,7 @@ func TestMiddlewareAdd(t *testing.T) { } router.Use(banalMw) if len(router.middlewares) != 3 { - t.Fatal("MiddlewareFunc method was not added correctly") + t.Fatal("Middleware function was not added correctly") } } @@ -55,34 +54,37 @@ func TestMiddleware(t *testing.T) { rw := NewRecorder() req := newRequest("GET", "/") - // Test regular middleware call - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } - - // Middleware should not be called for 404 - req = newRequest("GET", "/not/found") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } + t.Run("regular middleware call", func(t *testing.T) { + router.ServeHTTP(rw, req) + if mw.timesCalled != 1 { + t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) + } + }) - // Middleware should not be called if there is a method mismatch - req = newRequest("POST", "/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } + t.Run("not called for 404", func(t *testing.T) { + req = newRequest("GET", "/not/found") + router.ServeHTTP(rw, req) + if mw.timesCalled != 1 { + t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) + } + }) - // Add the middleware again as function - router.Use(mw.Middleware) - req = newRequest("GET", "/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 3 { - t.Fatalf("Expected %d calls, but got only %d", 3, mw.timesCalled) - } + t.Run("not called for method mismatch", func(t *testing.T) { + req = newRequest("POST", "/") + router.ServeHTTP(rw, req) + if mw.timesCalled != 1 { + t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) + } + }) + t.Run("regular call using function middleware", func(t *testing.T) { + router.Use(mw.Middleware) + req = newRequest("GET", "/") + router.ServeHTTP(rw, req) + if mw.timesCalled != 3 { + t.Fatalf("Expected %d calls, but got only %d", 3, mw.timesCalled) + } + }) } func TestMiddlewareSubrouter(t *testing.T) { @@ -98,42 +100,56 @@ func TestMiddlewareSubrouter(t *testing.T) { rw := NewRecorder() req := newRequest("GET", "/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 0 { - t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled) - } + t.Run("not called for route outside subrouter", func(t *testing.T) { + router.ServeHTTP(rw, req) + if mw.timesCalled != 0 { + t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled) + } + }) - req = newRequest("GET", "/sub/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 0 { - t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled) - } + t.Run("not called for subrouter root 404", func(t *testing.T) { + req = newRequest("GET", "/sub/") + router.ServeHTTP(rw, req) + if mw.timesCalled != 0 { + t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled) + } + }) - req = newRequest("GET", "/sub/x") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } + t.Run("called once for route inside subrouter", func(t *testing.T) { + req = newRequest("GET", "/sub/x") + router.ServeHTTP(rw, req) + if mw.timesCalled != 1 { + t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) + } + }) - req = newRequest("GET", "/sub/not/found") - router.ServeHTTP(rw, req) - if mw.timesCalled != 1 { - t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) - } + t.Run("not called for 404 inside subrouter", func(t *testing.T) { + req = newRequest("GET", "/sub/not/found") + router.ServeHTTP(rw, req) + if mw.timesCalled != 1 { + t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled) + } + }) - router.useInterface(mw) + t.Run("middleware added to router", func(t *testing.T) { + router.useInterface(mw) - req = newRequest("GET", "/") - router.ServeHTTP(rw, req) - if mw.timesCalled != 2 { - t.Fatalf("Expected %d calls, but got only %d", 2, mw.timesCalled) - } + t.Run("called once for route outside subrouter", func(t *testing.T) { + req = newRequest("GET", "/") + router.ServeHTTP(rw, req) + if mw.timesCalled != 2 { + t.Fatalf("Expected %d calls, but got only %d", 2, mw.timesCalled) + } + }) - req = newRequest("GET", "/sub/x") - router.ServeHTTP(rw, req) - if mw.timesCalled != 4 { - t.Fatalf("Expected %d calls, but got only %d", 4, mw.timesCalled) - } + t.Run("called twice for route inside subrouter", func(t *testing.T) { + req = newRequest("GET", "/sub/x") + router.ServeHTTP(rw, req) + if mw.timesCalled != 4 { + t.Fatalf("Expected %d calls, but got only %d", 4, mw.timesCalled) + } + }) + }) } func TestMiddlewareExecution(t *testing.T) { @@ -145,30 +161,33 @@ func TestMiddlewareExecution(t *testing.T) { w.Write(handlerStr) }) - rw := NewRecorder() - req := newRequest("GET", "/") + t.Run("responds normally without middleware", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/") - // Test handler-only call - router.ServeHTTP(rw, req) + router.ServeHTTP(rw, req) - if bytes.Compare(rw.Body.Bytes(), handlerStr) != 0 { - t.Fatal("Handler response is not what it should be") - } + if !bytes.Equal(rw.Body.Bytes(), handlerStr) { + t.Fatal("Handler response is not what it should be") + } + }) - // Test middleware call - rw = NewRecorder() + t.Run("responds with handler and middleware response", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/") - router.Use(func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(mwStr) - h.ServeHTTP(w, r) + router.Use(func(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write(mwStr) + h.ServeHTTP(w, r) + }) }) - }) - router.ServeHTTP(rw, req) - if bytes.Compare(rw.Body.Bytes(), append(mwStr, handlerStr...)) != 0 { - t.Fatal("Middleware + handler response is not what it should be") - } + router.ServeHTTP(rw, req) + if !bytes.Equal(rw.Body.Bytes(), append(mwStr, handlerStr...)) { + t.Fatal("Middleware + handler response is not what it should be") + } + }) } func TestMiddlewareNotFound(t *testing.T) { @@ -187,26 +206,29 @@ func TestMiddlewareNotFound(t *testing.T) { }) // Test not found call with default handler - rw := NewRecorder() - req := newRequest("GET", "/notfound") + t.Run("not called", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/notfound") - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a 404") - } + router.ServeHTTP(rw, req) + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a 404") + } + }) - // Test not found call with custom handler - rw = NewRecorder() - req = newRequest("GET", "/notfound") + t.Run("not called with custom not found handler", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/notfound") - router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Custom 404 handler")) - }) - router.ServeHTTP(rw, req) + router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.Write([]byte("Custom 404 handler")) + }) + router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a custom 404") - } + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a custom 404") + } + }) } func TestMiddlewareMethodMismatch(t *testing.T) { @@ -225,27 +247,29 @@ func TestMiddlewareMethodMismatch(t *testing.T) { }) }) - // Test method mismatch - rw := NewRecorder() - req := newRequest("POST", "/") + t.Run("not called", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("POST", "/") - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } + router.ServeHTTP(rw, req) + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a method mismatch") + } + }) - // Test not found call - rw = NewRecorder() - req = newRequest("POST", "/") + t.Run("not called with custom method not allowed handler", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("POST", "/") - router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Method not allowed")) - }) - router.ServeHTTP(rw, req) + router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.Write([]byte("Method not allowed")) + }) + router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a method mismatch") + } + }) } func TestMiddlewareNotFoundSubrouter(t *testing.T) { @@ -269,27 +293,29 @@ func TestMiddlewareNotFoundSubrouter(t *testing.T) { }) }) - // Test not found call for default handler - rw := NewRecorder() - req := newRequest("GET", "/sub/notfound") + t.Run("not called", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/sub/notfound") - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a 404") - } + router.ServeHTTP(rw, req) + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a 404") + } + }) - // Test not found call with custom handler - rw = NewRecorder() - req = newRequest("GET", "/sub/notfound") + t.Run("not called with custom not found handler", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/sub/notfound") - subrouter.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Custom 404 handler")) - }) - router.ServeHTTP(rw, req) + subrouter.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.Write([]byte("Custom 404 handler")) + }) + router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a custom 404") - } + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a custom 404") + } + }) } func TestMiddlewareMethodMismatchSubrouter(t *testing.T) { @@ -313,66 +339,142 @@ func TestMiddlewareMethodMismatchSubrouter(t *testing.T) { }) }) - // Test method mismatch without custom handler - rw := NewRecorder() - req := newRequest("POST", "/sub/") + t.Run("not called", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("POST", "/sub/") - router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } + router.ServeHTTP(rw, req) + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a method mismatch") + } + }) - // Test method mismatch with custom handler - rw = NewRecorder() - req = newRequest("POST", "/sub/") + t.Run("not called with custom method not allowed handler", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("POST", "/sub/") - router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - rw.Write([]byte("Method not allowed")) - }) - router.ServeHTTP(rw, req) + router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.Write([]byte("Method not allowed")) + }) + router.ServeHTTP(rw, req) - if bytes.Contains(rw.Body.Bytes(), mwStr) { - t.Fatal("Middleware was called for a method mismatch") - } + if bytes.Contains(rw.Body.Bytes(), mwStr) { + t.Fatal("Middleware was called for a method mismatch") + } + }) } func TestCORSMethodMiddleware(t *testing.T) { - router := NewRouter() - - cases := []struct { - path string - response string - method string - testURL string - expectedAllowedMethods string + testCases := []struct { + name string + registerRoutes func(r *Router) + requestHeader http.Header + requestMethod string + requestPath string + expectedAccessControlAllowMethodsHeader string + expectedResponse string }{ - {"/g/{o}", "a", "POST", "/g/asdf", "POST,PUT,GET,OPTIONS"}, - {"/g/{o}", "b", "PUT", "/g/bla", "POST,PUT,GET,OPTIONS"}, - {"/g/{o}", "c", "GET", "/g/orilla", "POST,PUT,GET,OPTIONS"}, - {"/g", "d", "POST", "/g", "POST,OPTIONS"}, + { + name: "does not set without OPTIONS matcher", + registerRoutes: func(r *Router) { + r.HandleFunc("/foo", stringHandler("a")).Methods(http.MethodGet, http.MethodPut, http.MethodPatch) + }, + requestMethod: "GET", + requestPath: "/foo", + expectedAccessControlAllowMethodsHeader: "", + expectedResponse: "a", + }, + { + name: "sets on non OPTIONS", + registerRoutes: func(r *Router) { + r.HandleFunc("/foo", stringHandler("a")).Methods(http.MethodGet, http.MethodPut, http.MethodPatch) + r.HandleFunc("/foo", stringHandler("b")).Methods(http.MethodOptions) + }, + requestMethod: "GET", + requestPath: "/foo", + expectedAccessControlAllowMethodsHeader: "GET,PUT,PATCH,OPTIONS", + expectedResponse: "a", + }, + { + name: "sets without preflight headers", + registerRoutes: func(r *Router) { + r.HandleFunc("/foo", stringHandler("a")).Methods(http.MethodGet, http.MethodPut, http.MethodPatch) + r.HandleFunc("/foo", stringHandler("b")).Methods(http.MethodOptions) + }, + requestMethod: "OPTIONS", + requestPath: "/foo", + expectedAccessControlAllowMethodsHeader: "GET,PUT,PATCH,OPTIONS", + expectedResponse: "b", + }, + { + name: "does not set on error", + registerRoutes: func(r *Router) { + r.HandleFunc("/foo", stringHandler("a")) + }, + requestMethod: "OPTIONS", + requestPath: "/foo", + expectedAccessControlAllowMethodsHeader: "", + expectedResponse: "a", + }, + { + name: "sets header on valid preflight", + registerRoutes: func(r *Router) { + r.HandleFunc("/foo", stringHandler("a")).Methods(http.MethodGet, http.MethodPut, http.MethodPatch) + r.HandleFunc("/foo", stringHandler("b")).Methods(http.MethodOptions) + }, + requestMethod: "OPTIONS", + requestPath: "/foo", + requestHeader: http.Header{ + "Access-Control-Request-Method": []string{"GET"}, + "Access-Control-Request-Headers": []string{"Authorization"}, + "Origin": []string{"http://example.com"}, + }, + expectedAccessControlAllowMethodsHeader: "GET,PUT,PATCH,OPTIONS", + expectedResponse: "b", + }, + { + name: "does not set methods from unmatching routes", + registerRoutes: func(r *Router) { + r.HandleFunc("/foo", stringHandler("c")).Methods(http.MethodDelete) + r.HandleFunc("/foo/bar", stringHandler("a")).Methods(http.MethodGet, http.MethodPut, http.MethodPatch) + r.HandleFunc("/foo/bar", stringHandler("b")).Methods(http.MethodOptions) + }, + requestMethod: "OPTIONS", + requestPath: "/foo/bar", + requestHeader: http.Header{ + "Access-Control-Request-Method": []string{"GET"}, + "Access-Control-Request-Headers": []string{"Authorization"}, + "Origin": []string{"http://example.com"}, + }, + expectedAccessControlAllowMethodsHeader: "GET,PUT,PATCH,OPTIONS", + expectedResponse: "b", + }, } - for _, tt := range cases { - router.HandleFunc(tt.path, stringHandler(tt.response)).Methods(tt.method) - } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + router := NewRouter() - router.Use(CORSMethodMiddleware(router)) + tt.registerRoutes(router) - for _, tt := range cases { - rr := httptest.NewRecorder() - req := newRequest(tt.method, tt.testURL) + router.Use(CORSMethodMiddleware(router)) - router.ServeHTTP(rr, req) + rw := NewRecorder() + req := newRequest(tt.requestMethod, tt.requestPath) + req.Header = tt.requestHeader - if rr.Body.String() != tt.response { - t.Errorf("Expected body '%s', found '%s'", tt.response, rr.Body.String()) - } + router.ServeHTTP(rw, req) - allowedMethods := rr.HeaderMap.Get("Access-Control-Allow-Methods") + actualMethodsHeader := rw.Header().Get("Access-Control-Allow-Methods") + if actualMethodsHeader != tt.expectedAccessControlAllowMethodsHeader { + t.Fatalf("Expected Access-Control-Allow-Methods to equal %s but got %s", tt.expectedAccessControlAllowMethodsHeader, actualMethodsHeader) + } - if allowedMethods != tt.expectedAllowedMethods { - t.Errorf("Expected Access-Control-Allow-Methods '%s', found '%s'", tt.expectedAllowedMethods, allowedMethods) - } + actualResponse := rw.Body.String() + if actualResponse != tt.expectedResponse { + t.Fatalf("Expected response to equal %s but got %s", tt.expectedResponse, actualResponse) + } + }) } } @@ -411,27 +513,33 @@ func TestMiddlewareOnMultiSubrouter(t *testing.T) { }) }) - rw := NewRecorder() - req := newRequest("GET", "/first") + t.Run("/first uses first middleware", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/first") - router.ServeHTTP(rw, req) - if rw.Body.String() != first { - t.Fatalf("Middleware did not run: expected %s middleware to write a response (got %s)", first, rw.Body.String()) - } + router.ServeHTTP(rw, req) + if rw.Body.String() != first { + t.Fatalf("Middleware did not run: expected %s middleware to write a response (got %s)", first, rw.Body.String()) + } + }) - rw = NewRecorder() - req = newRequest("GET", "/second") + t.Run("/second uses second middleware", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/second") - router.ServeHTTP(rw, req) - if rw.Body.String() != second { - t.Fatalf("Middleware did not run: expected %s middleware to write a response (got %s)", second, rw.Body.String()) - } + router.ServeHTTP(rw, req) + if rw.Body.String() != second { + t.Fatalf("Middleware did not run: expected %s middleware to write a response (got %s)", second, rw.Body.String()) + } + }) - rw = NewRecorder() - req = newRequest("GET", "/second/not-exist") + t.Run("uses not found handler", func(t *testing.T) { + rw := NewRecorder() + req := newRequest("GET", "/second/not-exist") - router.ServeHTTP(rw, req) - if rw.Body.String() != notFound { - t.Fatalf("Notfound handler did not run: expected %s for not-exist, (got %s)", notFound, rw.Body.String()) - } + router.ServeHTTP(rw, req) + if rw.Body.String() != notFound { + t.Fatalf("Notfound handler did not run: expected %s for not-exist, (got %s)", notFound, rw.Body.String()) + } + }) } diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go index 8aca972d2f..26f9582ac8 100644 --- a/vendor/github.com/gorilla/mux/mux.go +++ b/vendor/github.com/gorilla/mux/mux.go @@ -111,10 +111,8 @@ func copyRouteConf(r routeConf) routeConf { c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q)) } - c.matchers = make([]matcher, 0, len(r.matchers)) - for _, m := range r.matchers { - c.matchers = append(c.matchers, m) - } + c.matchers = make([]matcher, len(r.matchers)) + copy(c.matchers, r.matchers) return c } @@ -283,6 +281,12 @@ func (r *Router) NewRoute() *Route { return route } +// Name registers a new route with a name. +// See Route.Name(). +func (r *Router) Name(name string) *Route { + return r.NewRoute().Name(name) +} + // Handle registers a new route with a matcher for the URL path. // See Route.Path() and Route.Handler(). func (r *Router) Handle(path string, handler http.Handler) *Route { diff --git a/vendor/github.com/gorilla/mux/mux_test.go b/vendor/github.com/gorilla/mux/mux_test.go index 5198024d01..34c00dd25a 100644 --- a/vendor/github.com/gorilla/mux/mux_test.go +++ b/vendor/github.com/gorilla/mux/mux_test.go @@ -1123,10 +1123,7 @@ func TestSchemes(t *testing.T) { func TestMatcherFunc(t *testing.T) { m := func(r *http.Request, m *RouteMatch) bool { - if r.URL.Host == "aaa.bbb.ccc" { - return true - } - return false + return r.URL.Host == "aaa.bbb.ccc" } tests := []routeTest{ @@ -1444,10 +1441,11 @@ func TestNamedRoutes(t *testing.T) { r3.NewRoute().Name("g") r3.NewRoute().Name("h") r3.NewRoute().Name("i") + r3.Name("j") - if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 { - t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes) - } else if r1.Get("i") == nil { + if r1.namedRoutes == nil || len(r1.namedRoutes) != 10 { + t.Errorf("Expected 10 named routes, got %v", r1.namedRoutes) + } else if r1.Get("j") == nil { t.Errorf("Subroute name not registered") } } @@ -1945,7 +1943,7 @@ type TestA301ResponseWriter struct { } func (ho *TestA301ResponseWriter) Header() http.Header { - return http.Header(ho.hh) + return ho.hh } func (ho *TestA301ResponseWriter) Write(b []byte) (int, error) { diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go index f252886756..ac1abcd473 100644 --- a/vendor/github.com/gorilla/mux/regexp.go +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -113,6 +113,13 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro if typ != regexpTypePrefix { pattern.WriteByte('$') } + + var wildcardHostPort bool + if typ == regexpTypeHost { + if !strings.Contains(pattern.String(), ":") { + wildcardHostPort = true + } + } reverse.WriteString(raw) if endSlash { reverse.WriteByte('/') @@ -131,13 +138,14 @@ func newRouteRegexp(tpl string, typ regexpType, options routeRegexpOptions) (*ro // Done! return &routeRegexp{ - template: template, - regexpType: typ, - options: options, - regexp: reg, - reverse: reverse.String(), - varsN: varsN, - varsR: varsR, + template: template, + regexpType: typ, + options: options, + regexp: reg, + reverse: reverse.String(), + varsN: varsN, + varsR: varsR, + wildcardHostPort: wildcardHostPort, }, nil } @@ -158,11 +166,22 @@ type routeRegexp struct { varsN []string // Variable regexps (validators). varsR []*regexp.Regexp + // Wildcard host-port (no strict port match in hostname) + wildcardHostPort bool } // Match matches the regexp against the URL host or path. func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { - if r.regexpType != regexpTypeHost { + if r.regexpType == regexpTypeHost { + host := getHost(req) + if r.wildcardHostPort { + // Don't be strict on the port match + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } + } + return r.regexp.MatchString(host) + } else { if r.regexpType == regexpTypeQuery { return r.matchQueryString(req) } @@ -172,8 +191,6 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { } return r.regexp.MatchString(path) } - - return r.regexp.MatchString(getHost(req)) } // url builds a URL part using the given values. diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go index 16a7cdf4ea..8479c68c1d 100644 --- a/vendor/github.com/gorilla/mux/route.go +++ b/vendor/github.com/gorilla/mux/route.go @@ -383,7 +383,7 @@ func (r *Route) PathPrefix(tpl string) *Route { // The above route will only match if the URL contains the defined queries // values, e.g.: ?foo=bar&id=42. // -// It the value is an empty string, it will match any value if the key is set. +// If the value is an empty string, it will match any value if the key is set. // // Variables can define an optional regexp pattern to be matched: // diff --git a/vendor/github.com/opencontainers/go-digest/.mailmap b/vendor/github.com/opencontainers/go-digest/.mailmap new file mode 100644 index 0000000000..ba611cb21c --- /dev/null +++ b/vendor/github.com/opencontainers/go-digest/.mailmap @@ -0,0 +1 @@ +Stephen J Day diff --git a/vendor/github.com/opencontainers/go-digest/.travis.yml b/vendor/github.com/opencontainers/go-digest/.travis.yml index 7ea4ed1d2c..c0887229e7 100644 --- a/vendor/github.com/opencontainers/go-digest/.travis.yml +++ b/vendor/github.com/opencontainers/go-digest/.travis.yml @@ -1,4 +1,8 @@ language: go go: - - 1.7 + - 1.7.x + - 1.8.x + - 1.9.x + - 1.10.x + - 1.11.x - master diff --git a/vendor/github.com/opencontainers/go-digest/LICENSE.code b/vendor/github.com/opencontainers/go-digest/LICENSE similarity index 100% rename from vendor/github.com/opencontainers/go-digest/LICENSE.code rename to vendor/github.com/opencontainers/go-digest/LICENSE diff --git a/vendor/github.com/opencontainers/go-digest/MAINTAINERS b/vendor/github.com/opencontainers/go-digest/MAINTAINERS index f5bd5a6ed7..42a29795d7 100644 --- a/vendor/github.com/opencontainers/go-digest/MAINTAINERS +++ b/vendor/github.com/opencontainers/go-digest/MAINTAINERS @@ -1,5 +1,7 @@ +Aaron Lehmann (@aaronlehmann) Brandon Philips (@philips) Brendan Burns (@brendandburns) +Derek McGowan (@dmcgowan) Jason Bouzane (@jbouzane) John Starks (@jstarks) Jonathan Boulle (@jonboulle) diff --git a/vendor/github.com/opencontainers/go-digest/README.md b/vendor/github.com/opencontainers/go-digest/README.md index 9d6174cfdc..a043cd8607 100644 --- a/vendor/github.com/opencontainers/go-digest/README.md +++ b/vendor/github.com/opencontainers/go-digest/README.md @@ -1,10 +1,10 @@ # go-digest -[![GoDoc](https://godoc.org/github.com/docker/go-digest?status.svg)](https://godoc.org/github.com/docker/go-digest) [![Go Report Card](https://goreportcard.com/badge/github.com/docker/go-digest)](https://goreportcard.com/report/github.com/docker/go-digest) [![Build Status](https://travis-ci.org/docker/go-digest.svg?branch=master)](https://travis-ci.org/docker/go-digest) +[![GoDoc](https://godoc.org/github.com/opencontainers/go-digest?status.svg)](https://godoc.org/github.com/opencontainers/go-digest) [![Go Report Card](https://goreportcard.com/badge/github.com/opencontainers/go-digest)](https://goreportcard.com/report/github.com/opencontainers/go-digest) [![Build Status](https://travis-ci.org/opencontainers/go-digest.svg?branch=master)](https://travis-ci.org/opencontainers/go-digest) Common digest package used across the container ecosystem. -Please see the [godoc](https://godoc.org/github.com/docker/go-digest) for more information. +Please see the [godoc](https://godoc.org/github.com/opencontainers/go-digest) for more information. # What is a digest? @@ -49,7 +49,7 @@ can power a rich, safe, content distribution system. # Usage -While the [godoc](https://godoc.org/github.com/docker/go-digest) is +While the [godoc](https://godoc.org/github.com/opencontainers/go-digest) is considered the best resource, a few important items need to be called out when using this package. @@ -76,7 +76,7 @@ out when using this package. The Go API, at this stage, is considered stable, unless otherwise noted. -As always, before using a package export, read the [godoc](https://godoc.org/github.com/docker/go-digest). +As always, before using a package export, read the [godoc](https://godoc.org/github.com/opencontainers/go-digest). # Contributing @@ -86,19 +86,17 @@ New additions will be met with skepticism. If you think there is a missing feature, please file a bug clearly describing the problem and the alternatives you tried before submitting a PR. -# Reporting security issues +## Code of Conduct -The maintainers take security seriously. If you discover a security -issue, please bring it to their attention right away! +Participation in the OpenContainers community is governed by [OpenContainer's Code of Conduct][code-of-conduct]. -Please DO NOT file a public issue, instead send your report privately -to security@docker.com. +## Security -Security reports are greatly appreciated and we will publicly thank you -for it. We also like to send gifts—if you're into Docker schwag, make -sure to let us know. We currently do not offer a paid security bounty -program, but are not ruling it out in the future. +If you find an issue, please follow the [security][security] protocol to report it. # Copyright and license -Copyright © 2016 Docker, Inc. All rights reserved, except as follows. Code is released under the [Apache 2.0 license](LICENSE.code). This `README.md` file and the [`CONTRIBUTING.md`](CONTRIBUTING.md) file are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file [`LICENSE.docs`](LICENSE.docs). You may obtain a duplicate copy of the same license, titled CC BY-SA 4.0, at http://creativecommons.org/licenses/by-sa/4.0/. +Copyright © 2016 Docker, Inc. All rights reserved, except as follows. Code is released under the [Apache 2.0 license](LICENSE). This `README.md` file and the [`CONTRIBUTING.md`](CONTRIBUTING.md) file are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file [`LICENSE.docs`](LICENSE.docs). You may obtain a duplicate copy of the same license, titled CC BY-SA 4.0, at http://creativecommons.org/licenses/by-sa/4.0/. + +[security]: https://github.com/opencontainers/org/blob/master/security +[code-of-conduct]: https://github.com/opencontainers/org/blob/master/CODE_OF_CONDUCT.md diff --git a/vendor/github.com/opencontainers/go-digest/algorithm.go b/vendor/github.com/opencontainers/go-digest/algorithm.go index a3c44801d5..8813bd26f1 100644 --- a/vendor/github.com/opencontainers/go-digest/algorithm.go +++ b/vendor/github.com/opencontainers/go-digest/algorithm.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package digest import ( @@ -5,6 +19,7 @@ import ( "fmt" "hash" "io" + "regexp" ) // Algorithm identifies and implementation of a digester by an identifier. @@ -14,9 +29,9 @@ type Algorithm string // supported digest types const ( - SHA256 Algorithm = "sha256" // sha256 with hex encoding - SHA384 Algorithm = "sha384" // sha384 with hex encoding - SHA512 Algorithm = "sha512" // sha512 with hex encoding + SHA256 Algorithm = "sha256" // sha256 with hex encoding (lower case only) + SHA384 Algorithm = "sha384" // sha384 with hex encoding (lower case only) + SHA512 Algorithm = "sha512" // sha512 with hex encoding (lower case only) // Canonical is the primary digest algorithm used with the distribution // project. Other digests may be used but this one is the primary storage @@ -36,6 +51,14 @@ var ( SHA384: crypto.SHA384, SHA512: crypto.SHA512, } + + // anchoredEncodedRegexps contains anchored regular expressions for hex-encoded digests. + // Note that /A-F/ disallowed. + anchoredEncodedRegexps = map[Algorithm]*regexp.Regexp{ + SHA256: regexp.MustCompile(`^[a-f0-9]{64}$`), + SHA384: regexp.MustCompile(`^[a-f0-9]{96}$`), + SHA512: regexp.MustCompile(`^[a-f0-9]{128}$`), + } ) // Available returns true if the digest type is available for use. If this @@ -111,6 +134,14 @@ func (a Algorithm) Hash() hash.Hash { return algorithms[a].New() } +// Encode encodes the raw bytes of a digest, typically from a hash.Hash, into +// the encoded portion of the digest. +func (a Algorithm) Encode(d []byte) string { + // TODO(stevvooe): Currently, all algorithms use a hex encoding. When we + // add support for back registration, we can modify this accordingly. + return fmt.Sprintf("%x", d) +} + // FromReader returns the digest of the reader using the algorithm. func (a Algorithm) FromReader(rd io.Reader) (Digest, error) { digester := a.Digester() @@ -142,3 +173,20 @@ func (a Algorithm) FromBytes(p []byte) Digest { func (a Algorithm) FromString(s string) Digest { return a.FromBytes([]byte(s)) } + +// Validate validates the encoded portion string +func (a Algorithm) Validate(encoded string) error { + r, ok := anchoredEncodedRegexps[a] + if !ok { + return ErrDigestUnsupported + } + // Digests much always be hex-encoded, ensuring that their hex portion will + // always be size*2 + if a.Size()*2 != len(encoded) { + return ErrDigestInvalidLength + } + if r.MatchString(encoded) { + return nil + } + return ErrDigestInvalidFormat +} diff --git a/vendor/github.com/opencontainers/go-digest/algorithm_test.go b/vendor/github.com/opencontainers/go-digest/algorithm_test.go index 12db5d13ce..d50e8494fa 100644 --- a/vendor/github.com/opencontainers/go-digest/algorithm_test.go +++ b/vendor/github.com/opencontainers/go-digest/algorithm_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package digest import ( diff --git a/vendor/github.com/opencontainers/go-digest/digest.go b/vendor/github.com/opencontainers/go-digest/digest.go index 7c66c30c01..ad398cba2f 100644 --- a/vendor/github.com/opencontainers/go-digest/digest.go +++ b/vendor/github.com/opencontainers/go-digest/digest.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package digest import ( @@ -31,16 +45,21 @@ func NewDigest(alg Algorithm, h hash.Hash) Digest { // functions. This is also useful for rebuilding digests from binary // serializations. func NewDigestFromBytes(alg Algorithm, p []byte) Digest { - return Digest(fmt.Sprintf("%s:%x", alg, p)) + return NewDigestFromEncoded(alg, alg.Encode(p)) } -// NewDigestFromHex returns a Digest from alg and a the hex encoded digest. +// NewDigestFromHex is deprecated. Please use NewDigestFromEncoded. func NewDigestFromHex(alg, hex string) Digest { - return Digest(fmt.Sprintf("%s:%s", alg, hex)) + return NewDigestFromEncoded(Algorithm(alg), hex) +} + +// NewDigestFromEncoded returns a Digest from alg and the encoded digest. +func NewDigestFromEncoded(alg Algorithm, encoded string) Digest { + return Digest(fmt.Sprintf("%s:%s", alg, encoded)) } // DigestRegexp matches valid digest types. -var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+`) +var DigestRegexp = regexp.MustCompile(`[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+`) // DigestRegexpAnchored matches valid digest types, anchored to the start and end of the match. var DigestRegexpAnchored = regexp.MustCompile(`^` + DigestRegexp.String() + `$`) @@ -82,26 +101,18 @@ func FromString(s string) Digest { // error if not. func (d Digest) Validate() error { s := string(d) - i := strings.Index(s, ":") - - // validate i then run through regexp - if i < 0 || i+1 == len(s) || !DigestRegexpAnchored.MatchString(s) { + if i <= 0 || i+1 == len(s) { return ErrDigestInvalidFormat } - - algorithm := Algorithm(s[:i]) + algorithm, encoded := Algorithm(s[:i]), s[i+1:] if !algorithm.Available() { + if !DigestRegexpAnchored.MatchString(s) { + return ErrDigestInvalidFormat + } return ErrDigestUnsupported } - - // Digests much always be hex-encoded, ensuring that their hex portion will - // always be size*2 - if algorithm.Size()*2 != len(s[i+1:]) { - return ErrDigestInvalidLength - } - - return nil + return algorithm.Validate(encoded) } // Algorithm returns the algorithm portion of the digest. This will panic if @@ -119,12 +130,17 @@ func (d Digest) Verifier() Verifier { } } -// Hex returns the hex digest portion of the digest. This will panic if the +// Encoded returns the encoded portion of the digest. This will panic if the // underlying digest is not in a valid format. -func (d Digest) Hex() string { +func (d Digest) Encoded() string { return string(d[d.sepIndex()+1:]) } +// Hex is deprecated. Please use Digest.Encoded. +func (d Digest) Hex() string { + return d.Encoded() +} + func (d Digest) String() string { return string(d) } diff --git a/vendor/github.com/opencontainers/go-digest/digest_test.go b/vendor/github.com/opencontainers/go-digest/digest_test.go index d85c476f36..cc3b648a88 100644 --- a/vendor/github.com/opencontainers/go-digest/digest_test.go +++ b/vendor/github.com/opencontainers/go-digest/digest_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package digest import ( @@ -9,17 +23,17 @@ func TestParseDigest(t *testing.T) { input string err error algorithm Algorithm - hex string + encoded string }{ { input: "sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b", algorithm: "sha256", - hex: "e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b", + encoded: "e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b", }, { input: "sha384:d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", algorithm: "sha384", - hex: "d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", + encoded: "d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", }, { // empty hex @@ -39,7 +53,7 @@ func TestParseDigest(t *testing.T) { { // not hex input: "sha256:d41d8cd98f00b204e9800m98ecf8427e", - err: ErrDigestInvalidFormat, + err: ErrDigestInvalidLength, }, { // too short @@ -55,6 +69,34 @@ func TestParseDigest(t *testing.T) { input: "foo:d41d8cd98f00b204e9800998ecf8427e", err: ErrDigestUnsupported, }, + { + // repeated separators + input: "sha384__foo+bar:d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", + err: ErrDigestInvalidFormat, + }, + { + // ensure that we parse, but we don't have support for the algorithm + input: "sha384.foo+bar:d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", + algorithm: "sha384.foo+bar", + encoded: "d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", + err: ErrDigestUnsupported, + }, + { + input: "sha384_foo+bar:d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", + algorithm: "sha384_foo+bar", + encoded: "d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", + err: ErrDigestUnsupported, + }, + { + input: "sha256+b64:LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564", + algorithm: "sha256+b64", + encoded: "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564", + err: ErrDigestUnsupported, + }, + { + input: "sha256:E58FCF7418D4390DEC8E8FB69D88C06EC07039D651FEDD3AA72AF9972E7D046B", + err: ErrDigestInvalidFormat, + }, } { digest, err := Parse(testcase.input) if err != testcase.err { @@ -69,8 +111,8 @@ func TestParseDigest(t *testing.T) { t.Fatalf("incorrect algorithm for parsed digest: %q != %q", digest.Algorithm(), testcase.algorithm) } - if digest.Hex() != testcase.hex { - t.Fatalf("incorrect hex for parsed digest: %q != %q", digest.Hex(), testcase.hex) + if digest.Encoded() != testcase.encoded { + t.Fatalf("incorrect hex for parsed digest: %q != %q", digest.Encoded(), testcase.encoded) } // Parse string return value and check equality @@ -84,7 +126,7 @@ func TestParseDigest(t *testing.T) { t.Fatalf("expected equal: %q != %q", newParsed, digest) } - newFromHex := NewDigestFromHex(newParsed.Algorithm().String(), newParsed.Hex()) + newFromHex := NewDigestFromEncoded(newParsed.Algorithm(), newParsed.Encoded()) if newFromHex != digest { t.Fatalf("%v != %v", newFromHex, digest) } diff --git a/vendor/github.com/opencontainers/go-digest/digester.go b/vendor/github.com/opencontainers/go-digest/digester.go index 918a3f9191..36fa2728ef 100644 --- a/vendor/github.com/opencontainers/go-digest/digester.go +++ b/vendor/github.com/opencontainers/go-digest/digester.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package digest import "hash" diff --git a/vendor/github.com/opencontainers/go-digest/doc.go b/vendor/github.com/opencontainers/go-digest/doc.go index f64b0db32b..491ea1ef1f 100644 --- a/vendor/github.com/opencontainers/go-digest/doc.go +++ b/vendor/github.com/opencontainers/go-digest/doc.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Package digest provides a generalized type to opaquely represent message // digests and their operations within the registry. The Digest type is // designed to serve as a flexible identifier in a content-addressable system. diff --git a/vendor/github.com/opencontainers/go-digest/verifiers.go b/vendor/github.com/opencontainers/go-digest/verifiers.go index f1db6cda84..32125e9187 100644 --- a/vendor/github.com/opencontainers/go-digest/verifiers.go +++ b/vendor/github.com/opencontainers/go-digest/verifiers.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package digest import ( diff --git a/vendor/github.com/opencontainers/go-digest/verifiers_test.go b/vendor/github.com/opencontainers/go-digest/verifiers_test.go index 251d4fce54..d67bb1bc65 100644 --- a/vendor/github.com/opencontainers/go-digest/verifiers_test.go +++ b/vendor/github.com/opencontainers/go-digest/verifiers_test.go @@ -1,3 +1,17 @@ +// Copyright 2017 Docker, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package digest import ( diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk index b8a8112c02..fffc5b3a3c 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk @@ -20,12 +20,12 @@ CODEGEN_GROUPS_VERSION :=openshiftapiserver:v1alpha1 # $ make -n --print-data-base | grep ^CODEGEN # This will call a macro called "build-image" which will generate image specific targets based on the parameters: -# $0 - macro name -# $1 - target suffix -# $2 - Dockerfile path -# $3 - context directory for image build +# $1 - target name +# $2 - image ref +# $3 - Dockerfile path +# $4 - context # It will generate target "image-$(1)" for builing the image an binding it as a prerequisite to target "images". -$(call build-image,origin-cluster-openshift-apiserver-operator,./Dockerfile,.) +$(call build-image,ocp-cli,registry.svc.ci.openshift.org/ocp/4.2:cli,./images/cli/Dockerfile.rhel,.) # This will call a macro called "add-bindata" which will generate bindata specific targets based on the parameters: # $0 - macro name diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk.help.log b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk.help.log index 3645ce965c..92aa6acdbb 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk.help.log +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.example.mk.help.log @@ -4,7 +4,7 @@ build clean clean-binaries help -image-origin-cluster-openshift-apiserver-operator +image-ocp-cli images test test-unit diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk index 2f0326a9cb..7e6ff98d56 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk @@ -22,12 +22,12 @@ CODEGEN_GROUPS_VERSION :=openshiftapiserver:v1alpha1 # $ make -n --print-data-base | grep ^CODEGEN # This will call a macro called "build-image" which will generate image specific targets based on the parameters: -# $0 - macro name -# $1 - target suffix -# $2 - Dockerfile path -# $3 - context directory for image build +# $1 - target name +# $2 - image ref +# $3 - Dockerfile path +# $4 - context # It will generate target "image-$(1)" for builing the image an binding it as a prerequisite to target "images". -$(call build-image,origin-cluster-openshift-apiserver-operator,./Dockerfile,.) +$(call build-image,ocp-openshift-apiserver-operator,registry.svc.ci.openshift.org/ocp/4.2:openshift-apiserver-operator,./Dockerfile.rhel,.) # This will call a macro called "add-bindata" which will generate bindata specific targets based on the parameters: # $0 - macro name diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk.help.log b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk.help.log index 3645ce965c..a1489d212b 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk.help.log +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/operator.example.mk.help.log @@ -4,7 +4,7 @@ build clean clean-binaries help -image-origin-cluster-openshift-apiserver-operator +image-ocp-openshift-apiserver-operator images test test-unit diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/images.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/images.mk index b48741a739..00e76ac261 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/images.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/images.mk @@ -1,19 +1,23 @@ -IMAGE_REGISTRY ?= -IMAGE_ORG ?=openshift -IMAGE_TAG ?=latest - - # IMAGE_BUILD_EXTRA_FLAGS lets you add extra flags for imagebuilder # e.g. to mount secrets and repo information into base image like: # make images IMAGE_BUILD_EXTRA_FLAGS='-mount ~/projects/origin-repos/4.2/:/etc/yum.repos.d/' +IMAGE_BUILD_DEFAULT_FLAGS ?=--allow-pull IMAGE_BUILD_EXTRA_FLAGS ?= -# $1 - image name -# $2 - Dockerfile path -# $3 - context +# $1 - target name +# $2 - image ref +# $3 - Dockerfile path +# $4 - context define build-image-internal image-$(1): - $(strip imagebuilder --allow-pull $(IMAGE_BUILD_EXTRA_FLAGS) -f $(2) -t $(addsuffix /,$(IMAGE_REGISTRY))$(addsuffix /,$(IMAGE_ORG))$(1)$(addprefix :,$(IMAGE_TAG)) $(3)) + $(strip \ + imagebuilder \ + $(IMAGE_BUILD_DEFAULT_FLAGS) \ + -t $(2) + -f $(3) \ + $(IMAGE_BUILD_EXTRA_FLAGS) \ + $(4) \ + ) .PHONY: image-$(1) images: image-$(1) @@ -21,5 +25,5 @@ images: image-$(1) endef define build-image -$(eval $(call build-image-internal,$(1),$(2),$(3))) +$(eval $(call build-image-internal,$(1),$(2),$(3),$(4))) endef