diff options
29 files changed, 649 insertions, 84 deletions
diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go index de7cca40d..53be82dda 100644 --- a/cmd/podman/images/list.go +++ b/cmd/podman/images/list.go @@ -128,7 +128,7 @@ func writeID(imgs []imageReporter) error { func writeJSON(images []imageReporter) error { type image struct { entities.ImageSummary - Created string + Created int64 CreatedAt string } @@ -136,8 +136,8 @@ func writeJSON(images []imageReporter) error { for _, e := range images { var h image h.ImageSummary = e.ImageSummary - h.Created = units.HumanDuration(time.Since(e.ImageSummary.Created)) + " ago" - h.CreatedAt = e.ImageSummary.Created.Format(time.RFC3339Nano) + h.Created = e.ImageSummary.Created + h.CreatedAt = e.created().Format(time.RFC3339Nano) h.RepoTags = nil imgs = append(imgs, h) @@ -284,11 +284,11 @@ func (i imageReporter) ID() string { } func (i imageReporter) Created() string { - return units.HumanDuration(time.Since(i.ImageSummary.Created)) + " ago" + return units.HumanDuration(time.Since(i.created())) + " ago" } func (i imageReporter) created() time.Time { - return i.ImageSummary.Created + return time.Unix(i.ImageSummary.Created, 0).UTC() } func (i imageReporter) Size() string { @@ -302,7 +302,7 @@ func (i imageReporter) History() string { } func (i imageReporter) CreatedAt() string { - return i.ImageSummary.Created.String() + return i.created().String() } func (i imageReporter) CreatedSince() string { @@ -11,7 +11,7 @@ require ( github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921 github.com/containernetworking/plugins v0.8.6 github.com/containers/buildah v1.15.0 - github.com/containers/common v0.14.3 + github.com/containers/common v0.15.1 github.com/containers/conmon v2.0.18+incompatible github.com/containers/image/v5 v5.5.1 github.com/containers/psgo v1.5.1 @@ -43,7 +43,7 @@ require ( github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 github.com/opencontainers/runtime-tools v0.9.0 github.com/opencontainers/selinux v1.5.2 - github.com/opentracing/opentracing-go v1.1.0 + github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 github.com/rootless-containers/rootlesskit v0.9.5 @@ -64,6 +64,6 @@ require ( golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 gopkg.in/yaml.v2 v2.3.0 k8s.io/api v0.18.4 - k8s.io/apimachinery v0.18.4 + k8s.io/apimachinery v0.18.5 k8s.io/client-go v0.0.0-20190620085101-78d2af792bab ) @@ -70,8 +70,8 @@ github.com/containers/buildah v1.15.0 h1:p9cYJwcQ5Fnv0iBeHAFwHR0K+kcv7LbyAjUtc+H github.com/containers/buildah v1.15.0/go.mod h1:j0AY2kWpmaOPPV5GKDJY9dMtekk5WMmMhcB+z0OW+vc= github.com/containers/common v0.14.0 h1:hiZFDPf6ajKiDmojN5f5X3gboKPO73NLrYb0RXfrQiA= github.com/containers/common v0.14.0/go.mod h1:9olhlE+WhYof1npnMJdyRMX14/yIUint6zyHzcyRVAg= -github.com/containers/common v0.14.3 h1:LNsRPkap5Q/EqPyhiLKRZg8u629U8CEeoB49ilG6ZR4= -github.com/containers/common v0.14.3/go.mod h1:9olhlE+WhYof1npnMJdyRMX14/yIUint6zyHzcyRVAg= +github.com/containers/common v0.15.1 h1:ycIJf7ugHf0f2ag9uYFijQLbcrPu1KnOqdARgs2XbRU= +github.com/containers/common v0.15.1/go.mod h1:zJ/BLqK6INqFOCxN/gh9ae1qqWD/ghk2T0jAYqz/Xq4= github.com/containers/conmon v2.0.18+incompatible h1:rjwjNnE756NuXcdE/uUmj4kDbrykslPuBMHI31wh43E= github.com/containers/conmon v2.0.18+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.4.4/go.mod h1:g7cxNXitiLi6pEr9/L9n/0wfazRuhDKXU15kV86N8h8= @@ -343,8 +343,8 @@ github.com/opencontainers/selinux v1.5.2 h1:F6DgIsjgBIcDksLW4D5RG9bXok6oqZ3nvMwj github.com/opencontainers/selinux v1.5.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/openshift/imagebuilder v1.1.5 h1:WAIHV6cGF9e0AcLBA7RIi7XbFoB7R+e/MWu1I+1NUOM= github.com/openshift/imagebuilder v1.1.5/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw= github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -631,6 +631,8 @@ k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4= k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= k8s.io/apimachinery v0.18.4 h1:ST2beySjhqwJoIFk6p7Hp5v5O0hYY6Gngq/gUYXTPIA= k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= +k8s.io/apimachinery v0.18.5 h1:Lh6tgsM9FMkC12K5T5QjRm7rDs6aQN5JHkA0JomULDM= +k8s.io/apimachinery v0.18.5/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= k8s.io/client-go v0.0.0-20190620085101-78d2af792bab h1:E8Fecph0qbNsAbijJJQryKu4Oi9QTp5cVpjTE+nqg6g= k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go new file mode 100644 index 000000000..1c9366409 --- /dev/null +++ b/pkg/api/handlers/compat/volumes.go @@ -0,0 +1,259 @@ +package compat + +import ( + "encoding/json" + "net/http" + "time" + + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/containers/libpod/pkg/domain/filters" + "github.com/containers/libpod/pkg/domain/infra/abi/parse" + docker_api_types "github.com/docker/docker/api/types" + docker_api_types_volume "github.com/docker/docker/api/types/volume" + "github.com/gorilla/schema" + "github.com/pkg/errors" +) + +func ListVolumes(w http.ResponseWriter, r *http.Request) { + var ( + decoder = r.Context().Value("decoder").(*schema.Decoder) + runtime = r.Context().Value("runtime").(*libpod.Runtime) + ) + query := struct { + Filters map[string][]string `schema:"filters"` + }{ + // override any golang type defaults + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) + return + } + + // Reject any libpod specific filters since `GenerateVolumeFilters()` will + // happily parse them for us. + for filter := range query.Filters { + if filter == "opts" { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Errorf("unsupported libpod filters passed to docker endpoint")) + return + } + } + volumeFilters, err := filters.GenerateVolumeFilters(query.Filters) + if err != nil { + utils.InternalServerError(w, err) + return + } + + vols, err := runtime.Volumes(volumeFilters...) + if err != nil { + utils.InternalServerError(w, err) + return + } + volumeConfigs := make([]*docker_api_types.Volume, 0, len(vols)) + for _, v := range vols { + config := docker_api_types.Volume{ + Name: v.Name(), + Driver: v.Driver(), + Mountpoint: v.MountPoint(), + CreatedAt: v.CreatedTime().Format(time.RFC3339), + Labels: v.Labels(), + Scope: v.Scope(), + Options: v.Options(), + } + volumeConfigs = append(volumeConfigs, &config) + } + response := docker_api_types_volume.VolumeListOKBody{ + Volumes: volumeConfigs, + Warnings: []string{}, + } + utils.WriteResponse(w, http.StatusOK, response) +} + +func CreateVolume(w http.ResponseWriter, r *http.Request) { + var ( + volumeOptions []libpod.VolumeCreateOption + runtime = r.Context().Value("runtime").(*libpod.Runtime) + decoder = r.Context().Value("decoder").(*schema.Decoder) + ) + /* No query string data*/ + query := struct{}{} + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) + return + } + // decode params from body + input := docker_api_types_volume.VolumeCreateBody{} + if err := json.NewDecoder(r.Body).Decode(&input); err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + return + } + + if len(input.Name) > 0 { + volumeOptions = append(volumeOptions, libpod.WithVolumeName(input.Name)) + } + if len(input.Driver) > 0 { + volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(input.Driver)) + } + if len(input.Labels) > 0 { + volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(input.Labels)) + } + if len(input.DriverOpts) > 0 { + parsedOptions, err := parse.VolumeOptions(input.DriverOpts) + if err != nil { + utils.InternalServerError(w, err) + return + } + volumeOptions = append(volumeOptions, parsedOptions...) + } + vol, err := runtime.NewVolume(r.Context(), volumeOptions...) + if err != nil { + utils.InternalServerError(w, err) + return + } + config, err := vol.Config() + if err != nil { + utils.InternalServerError(w, err) + return + } + volResponse := docker_api_types.Volume{ + Name: config.Name, + Driver: config.Driver, + Mountpoint: config.MountPoint, + CreatedAt: config.CreatedTime.Format(time.RFC3339), + Labels: config.Labels, + Options: config.Options, + Scope: "local", + // ^^ We don't have volume scoping so we'll just claim it's "local" + // like we do in the `libpod.Volume.Scope()` method + // + // TODO: We don't include the volume `Status` or `UsageData`, but both + // are nullable in the Docker engine API spec so that's fine for now + } + utils.WriteResponse(w, http.StatusCreated, volResponse) +} + +func InspectVolume(w http.ResponseWriter, r *http.Request) { + var ( + runtime = r.Context().Value("runtime").(*libpod.Runtime) + ) + name := utils.GetName(r) + vol, err := runtime.GetVolume(name) + if err != nil { + utils.VolumeNotFound(w, name, err) + return + } + volResponse := docker_api_types.Volume{ + Name: vol.Name(), + Driver: vol.Driver(), + Mountpoint: vol.MountPoint(), + CreatedAt: vol.CreatedTime().Format(time.RFC3339), + Labels: vol.Labels(), + Options: vol.Options(), + Scope: vol.Scope(), + // TODO: As above, we don't return `Status` or `UsageData` yet + } + utils.WriteResponse(w, http.StatusOK, volResponse) +} + +func RemoveVolume(w http.ResponseWriter, r *http.Request) { + var ( + runtime = r.Context().Value("runtime").(*libpod.Runtime) + decoder = r.Context().Value("decoder").(*schema.Decoder) + ) + query := struct { + Force bool `schema:"force"` + }{ + // override any golang type defaults + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) + return + } + + /* The implications for `force` differ between Docker and us, so we can't + * simply pass the `force` parameter to `runeimt.RemoveVolume()`. + * Specifically, Docker's behavior seems to be that `force` means "do not + * error on missing volume"; ours means "remove any not-running containers + * using the volume at the same time". + * + * With this in mind, we only consider the `force` query parameter when we + * hunt for specified volume by name, using it to seletively return a 204 + * or blow up depending on `force` being truthy or falsey/unset + * respectively. + */ + name := utils.GetName(r) + vol, err := runtime.LookupVolume(name) + if err == nil { + // As above, we do not pass `force` from the query parameters here + if err := runtime.RemoveVolume(r.Context(), vol, false); err != nil { + if errors.Cause(err) == define.ErrVolumeBeingUsed { + utils.Error(w, "volumes being used", http.StatusConflict, err) + } else { + utils.InternalServerError(w, err) + } + } else { + // Success + utils.WriteResponse(w, http.StatusNoContent, "") + } + } else { + if !query.Force { + utils.VolumeNotFound(w, name, err) + } else { + // Volume does not exist and `force` is truthy - this emulates what + // Docker would do when told to `force` removal of a nonextant + // volume + utils.WriteResponse(w, http.StatusNoContent, "") + } + } +} + +func PruneVolumes(w http.ResponseWriter, r *http.Request) { + var ( + runtime = r.Context().Value("runtime").(*libpod.Runtime) + decoder = r.Context().Value("decoder").(*schema.Decoder) + ) + // For some reason the prune filters are query parameters even though this + // is a POST endpoint + query := struct { + Filters map[string][]string `schema:"filters"` + }{ + // override any golang type defaults + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) + return + } + // TODO: We have no ability to pass pruning filters to `PruneVolumes()` so + // we'll explicitly reject the request if we see any + if len(query.Filters) > 0 { + utils.InternalServerError(w, errors.New("filters for pruning volumes is not implemented")) + return + } + + pruned, err := runtime.PruneVolumes(r.Context()) + if err != nil { + utils.InternalServerError(w, err) + return + } + prunedIds := make([]string, 0, len(pruned)) + for k := range pruned { + // XXX: This drops any pruning per-volume error messages on the floor + prunedIds = append(prunedIds, k) + } + pruneResponse := docker_api_types.VolumesPruneReport{ + VolumesDeleted: prunedIds, + // TODO: We don't have any insight into how much space was reclaimed + // from `PruneVolumes()` but it's not nullable + SpaceReclaimed: 0, + } + + utils.WriteResponse(w, http.StatusOK, pruneResponse) +} diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 54e202103..ebcb1f460 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -112,7 +112,6 @@ func GetImages(w http.ResponseWriter, r *http.Request) { return } // libpod has additional fields that we need to populate. - is.Created = img.Created() is.ReadOnly = img.IsReadOnly() summaries[j] = is } diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index c1e84ab5a..72e1a756e 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -221,7 +221,7 @@ func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) { ID: l.ID(), ParentId: l.Parent, RepoTags: repoTags, - Created: l.Created(), + Created: l.Created().Unix(), Size: int64(*size), SharedSize: 0, VirtualSize: l.VirtualSize, diff --git a/pkg/api/server/register_volumes.go b/pkg/api/server/register_volumes.go index 1d5abd830..0f4f18b0a 100644 --- a/pkg/api/server/register_volumes.go +++ b/pkg/api/server/register_volumes.go @@ -3,12 +3,13 @@ package server import ( "net/http" + "github.com/containers/libpod/pkg/api/handlers/compat" "github.com/containers/libpod/pkg/api/handlers/libpod" "github.com/gorilla/mux" ) func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { - // swagger:operation POST /libpod/volumes/create volumes createVolume + // swagger:operation POST /libpod/volumes/create volumes libpodCreateVolume // --- // summary: Create a volume // parameters: @@ -25,7 +26,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.Handle(VersionedPath("/libpod/volumes/create"), s.APIHandler(libpod.CreateVolume)).Methods(http.MethodPost) - // swagger:operation GET /libpod/volumes/json volumes listVolumes + // swagger:operation GET /libpod/volumes/json volumes libpodListVolumes // --- // summary: List volumes // description: Returns a list of volumes @@ -47,7 +48,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.Handle(VersionedPath("/libpod/volumes/json"), s.APIHandler(libpod.ListVolumes)).Methods(http.MethodGet) - // swagger:operation POST /libpod/volumes/prune volumes pruneVolumes + // swagger:operation POST /libpod/volumes/prune volumes libpodPruneVolumes // --- // summary: Prune volumes // produces: @@ -58,7 +59,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.Handle(VersionedPath("/libpod/volumes/prune"), s.APIHandler(libpod.PruneVolumes)).Methods(http.MethodPost) - // swagger:operation GET /libpod/volumes/{name}/json volumes inspectVolume + // swagger:operation GET /libpod/volumes/{name}/json volumes libpodInspectVolume // --- // summary: Inspect volume // parameters: @@ -77,7 +78,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { // '500': // "$ref": "#/responses/InternalError" r.Handle(VersionedPath("/libpod/volumes/{name}/json"), s.APIHandler(libpod.InspectVolume)).Methods(http.MethodGet) - // swagger:operation DELETE /libpod/volumes/{name} volumes removeVolume + // swagger:operation DELETE /libpod/volumes/{name} volumes libpodRemoveVolume // --- // summary: Remove volume // parameters: @@ -102,5 +103,127 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error { // 500: // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/libpod/volumes/{name}"), s.APIHandler(libpod.RemoveVolume)).Methods(http.MethodDelete) + + /* + * Docker compatibility endpoints + */ + + // swagger:operation GET /volumes compat listVolumes + // --- + // summary: List volumes + // description: Returns a list of volume + // produces: + // - application/json + // parameters: + // - in: query + // name: filters + // type: string + // description: | + // JSON encoded value of the filters (a map[string][]string) to process on the volumes list. Available filters: + // - driver=<volume-driver-name> Matches volumes based on their driver. + // - label=<key> or label=<key>:<value> Matches volumes based on the presence of a label alone or a label and a value. + // - name=<volume-name> Matches all of volume name. + // + // Note: + // The boolean `dangling` filter is not yet implemented for this endpoint. + // responses: + // '200': + // "$ref": "#/responses/DockerVolumeList" + // '500': + // "$ref": "#/responses/InternalError" + r.Handle(VersionedPath("/volumes"), s.APIHandler(compat.ListVolumes)).Methods(http.MethodGet) + r.Handle("/volumes", s.APIHandler(compat.ListVolumes)).Methods(http.MethodGet) + + // swagger:operation POST /volumes/create volumes createVolume + // --- + // summary: Create a volume + // parameters: + // - in: body + // name: create + // description: attributes for creating a container + // schema: + // $ref: "#/definitions/DockerVolumeCreate" + // produces: + // - application/json + // responses: + // '201': + // "$ref": "#/responses/DockerVolumeInfoResponse" + // '500': + // "$ref": "#/responses/InternalError" + r.Handle(VersionedPath("/volumes/create"), s.APIHandler(compat.CreateVolume)).Methods(http.MethodPost) + r.Handle("/volumes/create", s.APIHandler(compat.CreateVolume)).Methods(http.MethodPost) + + // swagger:operation GET /volumes/{name} volumes inspectVolume + // --- + // summary: Inspect volume + // parameters: + // - in: path + // name: name + // type: string + // required: true + // description: the name or ID of the volume + // produces: + // - application/json + // responses: + // '200': + // "$ref": "#/responses/DockerVolumeInfoResponse" + // '404': + // "$ref": "#/responses/NoSuchVolume" + // '500': + // "$ref": "#/responses/InternalError" + r.Handle(VersionedPath("/volumes/{name}"), s.APIHandler(compat.InspectVolume)).Methods(http.MethodGet) + r.Handle("/volumes/{name}", s.APIHandler(compat.InspectVolume)).Methods(http.MethodGet) + + // swagger:operation DELETE /volumes/{name} volumes removeVolume + // --- + // summary: Remove volume + // parameters: + // - in: path + // name: name + // type: string + // required: true + // description: the name or ID of the volume + // - in: query + // name: force + // type: boolean + // description: | + // Force removal of the volume. This actually only causes errors due + // to the names volume not being found to be suppressed, which is the + // behaviour Docker implements. + // produces: + // - application/json + // responses: + // 204: + // description: no error + // 404: + // "$ref": "#/responses/NoSuchVolume" + // 409: + // description: Volume is in use and cannot be removed + // 500: + // "$ref": "#/responses/InternalError" + r.Handle(VersionedPath("/volumes/{name}"), s.APIHandler(compat.RemoveVolume)).Methods(http.MethodDelete) + r.Handle("/volumes/{name}", s.APIHandler(compat.RemoveVolume)).Methods(http.MethodDelete) + + // swagger:operation POST /volumes/prune volumes pruneVolumes + // --- + // summary: Prune volumes + // produces: + // - application/json + // parameters: + // - in: query + // name: filters + // type: string + // description: | + // JSON encoded value of filters (a map[string][]string) to match volumes against before pruning. + // + // Note: No filters are currently supported and any filters specified will cause an error response. + // responses: + // '200': + // "$ref": "#/responses/DockerVolumePruneResponse" + // '500': + // "$ref": "#/responses/InternalError" + r.Handle(VersionedPath("/volumes/prune"), s.APIHandler(compat.PruneVolumes)).Methods(http.MethodPost) + r.Handle("/volumes/prune", s.APIHandler(compat.PruneVolumes)).Methods(http.MethodPost) + return nil } diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 81f52fef5..27f887e8e 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -53,7 +53,7 @@ type ImageSummary struct { ID string `json:"Id"` ParentId string `json:",omitempty"` // nolint RepoTags []string `json:",omitempty"` - Created time.Time `json:",omitempty"` + Created int64 `json:",omitempty"` Size int64 `json:",omitempty"` SharedSize int `json:",omitempty"` VirtualSize int64 `json:",omitempty"` diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go index c99b39f2d..2311d1f25 100644 --- a/pkg/domain/entities/volumes.go +++ b/pkg/domain/entities/volumes.go @@ -2,6 +2,9 @@ package entities import ( "time" + + docker_api_types "github.com/docker/docker/api/types" + docker_api_types_volume "github.com/docker/docker/api/types/volume" ) // swagger:model VolumeCreate @@ -90,3 +93,35 @@ type VolumeListOptions struct { type VolumeListReport struct { VolumeConfigResponse } + +/* + * Docker API compatibility types + */ +// swagger:response DockerVolumeList +type SwagDockerVolumeListResponse struct { + // in:body + Body struct { + docker_api_types_volume.VolumeListOKBody + } +} + +// swagger:model DockerVolumeCreate +type DockerVolumeCreate docker_api_types_volume.VolumeCreateBody + +// This response definition is used for both the create and inspect endpoints +// swagger:response DockerVolumeInfoResponse +type SwagDockerVolumeInfoResponse struct { + // in:body + Body struct { + docker_api_types.Volume + } +} + +// Volume prune response +// swagger:response DockerVolumePruneResponse +type SwagDockerVolumePruneResponse struct { + // in:body + Body struct { + docker_api_types.VolumesPruneReport + } +} diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go index 98c041c15..92ab0a998 100644 --- a/pkg/domain/infra/abi/images_list.go +++ b/pkg/domain/infra/abi/images_list.go @@ -52,7 +52,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) ID: img.ID(), ConfigDigest: string(img.ConfigDigest), - Created: img.Created(), + Created: img.Created().Unix(), Dangling: img.Dangling(), Digest: string(img.Digest()), Digests: digests, diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index 7a3518df2..d0bf28b9a 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -84,7 +84,7 @@ function like() { if expr "$actual" : "$expect" &>/dev/null; then # On success, include expected value; this helps readers understand - _show_ok 1 "$testname~$expect" + _show_ok 1 "$testname ('$actual') ~ $expect" return fi _show_ok 0 "$testname" "~ $expect" "$actual" diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index d60464739..c652a66f2 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -165,6 +165,9 @@ type ContainersConfig struct { // ShmSize holds the size of /dev/shm. ShmSize string `toml:"shm_size,omitempty"` + //TZ sets the timezone inside the container + TZ string `toml:"tz,omitempty"` + // UTSNS indicates how to create a UTS namespace for the container UTSNS string `toml:"utsns,omitempty"` @@ -207,6 +210,9 @@ type EngineConfig struct { // memory. EnablePortReservation bool `toml:"enable_port_reservation,omitempty"` + // Environment variables to be used when running the container engine (e.g., Podman, Buildah). For example "http_proxy=internal.proxy.company.com" + Env []string `toml:"env,omitempty"` + // EventsLogFilePath is where the events log is stored. EventsLogFilePath string `toml:"events_logfile_path,omitempty"` @@ -416,11 +422,10 @@ func NewConfig(userConfigPath string) (*Config, error) { // Merge changes in later configs with the previous configs. // Each config file that specified fields, will override the // previous fields. - config, err := readConfigFromFile(path, config) - if err != nil { + if err = readConfigFromFile(path, config); err != nil { return nil, errors.Wrapf(err, "error reading system config %q", path) } - logrus.Debugf("Merged system config %q: %v", path, config) + logrus.Debugf("Merged system config %q: %+v", path, config) } // If the caller specified a config path to use, then we read it to @@ -429,11 +434,10 @@ func NewConfig(userConfigPath string) (*Config, error) { var err error // readConfigFromFile reads in container config in the specified // file and then merge changes with the current default. - config, err = readConfigFromFile(userConfigPath, config) - if err != nil { + if err = readConfigFromFile(userConfigPath, config); err != nil { return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath) } - logrus.Debugf("Merged user config %q: %v", userConfigPath, config) + logrus.Debugf("Merged user config %q: %+v", userConfigPath, config) } config.addCAPPrefix() @@ -448,13 +452,12 @@ func NewConfig(userConfigPath string) (*Config, error) { // unmarshal its content into a Config. The config param specifies the previous // default config. If the path, only specifies a few fields in the Toml file // the defaults from the config parameter will be used for all other fields. -func readConfigFromFile(path string, config *Config) (*Config, error) { +func readConfigFromFile(path string, config *Config) error { logrus.Debugf("Reading configuration file %q", path) - _, err := toml.DecodeFile(path, config) - if err != nil { - return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err) + if _, err := toml.DecodeFile(path, config); err != nil { + return errors.Wrapf(err, "unable to decode configuration %v", path) } - return config, err + return nil } // Returns the list of configuration files, if they exist in order of hierarchy. @@ -465,7 +468,7 @@ func systemConfigs() ([]string, error) { path := os.Getenv("CONTAINERS_CONF") if path != "" { if _, err := os.Stat(path); err != nil { - return nil, errors.Wrap(err, "failed to stat of %s from CONTAINERS_CONF environment variable") + return nil, errors.Wrapf(err, "failed to stat of %s from CONTAINERS_CONF environment variable", path) } return append(configs, path), nil } @@ -575,6 +578,10 @@ func (c *ContainersConfig) Validate() error { return err } + if err := c.validateTZ(); err != nil { + return err + } + if c.LogSizeMax >= 0 && c.LogSizeMax < OCIBufSize { return fmt.Errorf("log size max should be negative or >= %d", OCIBufSize) } @@ -892,8 +899,7 @@ func ReadCustomConfig() (*Config, error) { newConfig := &Config{} if _, err := os.Stat(path); err == nil { - newConfig, err = readConfigFromFile(path, newConfig) - if err != nil { + if err = readConfigFromFile(path, newConfig); err != nil { return nil, err } } else { diff --git a/vendor/github.com/containers/common/pkg/config/config_local.go b/vendor/github.com/containers/common/pkg/config/config_local.go index 8f4daa3d7..a6ab33c50 100644 --- a/vendor/github.com/containers/common/pkg/config/config_local.go +++ b/vendor/github.com/containers/common/pkg/config/config_local.go @@ -76,6 +76,18 @@ func (c *ContainersConfig) validateUlimits() error { return nil } +func (c *ContainersConfig) validateTZ() error { + if c.TZ == "local" { + return nil + } + zonePath := filepath.Join("/usr/share/zoneinfo", c.TZ) + _, err := os.Stat(zonePath) + if err != nil { + return fmt.Errorf("Unrecognized timezone %s", zonePath) + } + return nil +} + func isRemote() bool { return false } diff --git a/vendor/github.com/containers/common/pkg/config/config_remote.go b/vendor/github.com/containers/common/pkg/config/config_remote.go index d012dbd2f..61dd159ad 100644 --- a/vendor/github.com/containers/common/pkg/config/config_remote.go +++ b/vendor/github.com/containers/common/pkg/config/config_remote.go @@ -23,3 +23,7 @@ func (c *ContainersConfig) validateDevices() error { func (c *ContainersConfig) validateUlimits() error { return nil } + +func (c *ContainersConfig) validateTZ() error { + return nil +} diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index 389479fa5..80afbb9bc 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -205,6 +205,11 @@ # # shm_size = "65536k" +# Set timezone in container. Takes IANA timezones as well as "local", +# which sets the timezone in the container to match the host machine. +# +# tz = "" + # Default way to to create a UTS namespace for the container # Options are: # `private` Create private UTS Namespace for the container. @@ -279,6 +284,12 @@ # # enable_port_reservation = true +# Environment variables to be used when running the container engine (e.g., Podman, Buildah). +# For example "http_proxy=internal.proxy.company.com". +# Note these environment variables will not be used within the container. +# Set the env section under [containers] table, if you want to set environment variables for the container. +# env = [] + # Selects which logging mechanism to use for container engine events. # Valid values are `journald`, `file` and `none`. # @@ -329,6 +340,14 @@ # Whether to pull new image before running a container # pull_policy = "missing" +# Default Remote URI to access the Podman service. +# Examples: +# rootless "unix://run/user/$UID/podman/podman.sock" (Default) +# rootfull "unix://run/podman/podman.sock.(Default) +# remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock +# remote rootfull ssh://root@10.10.1.136:22/run/podman/podman.sock +# remote_uri= "" + # Directory for persistent engine files (database, etc) # By default, this will be configured relative to where the containers/storage # stores containers @@ -364,6 +383,9 @@ # # runtime_supports_kvm = ["kata"] +# Number of seconds to wait for container to exit before sending kill signal. +# stop_timeout = 10 + # Paths to look for a valid OCI runtime (runc, runv, kata, etc) [engine.runtimes] # runc = [ @@ -397,9 +419,6 @@ # "/usr/bin/kata-fc", # ] -# Number of seconds to wait for container to exit before sending kill signal. -#stop_timeout = 10 - # The [engine.runtimes] table MUST be the last entry in this file. # (Unless another table is added) # TOML does not provide a way to end a table other than a further table being diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index fe523cbf5..60811637f 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -191,6 +191,7 @@ func DefaultConfig() (*Config, error) { PidNS: "private", SeccompProfile: SeccompDefaultPath, ShmSize: DefaultShmSize, + TZ: "", UTSNS: "private", UserNS: "host", UserNSSize: DefaultUserNSSize, @@ -498,3 +499,8 @@ func (c *Config) PidsLimit() int64 { func (c *Config) DetachKeys() string { return c.Engine.DetachKeys } + +// Tz returns the timezone in the container +func (c *Config) TZ() string { + return c.Containers.TZ +} diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 38a45dfb2..bbbca741c 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.14.3" +const Version = "0.15.1" diff --git a/vendor/github.com/opentracing/opentracing-go/.travis.yml b/vendor/github.com/opentracing/opentracing-go/.travis.yml index 8d5b75e41..b950e4296 100644 --- a/vendor/github.com/opentracing/opentracing-go/.travis.yml +++ b/vendor/github.com/opentracing/opentracing-go/.travis.yml @@ -2,8 +2,8 @@ language: go matrix: include: - - go: "1.11.x" - - go: "1.12.x" + - go: "1.13.x" + - go: "1.14.x" - go: "tip" env: - LINT=true diff --git a/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md b/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md index 7c14febe1..d3bfcf623 100644 --- a/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md +++ b/vendor/github.com/opentracing/opentracing-go/CHANGELOG.md @@ -1,6 +1,23 @@ Changes by Version ================== + +1.2.0 (2020-07-01) +------------------- + +* Restore the ability to reset the current span in context to nil (#231) -- Yuri Shkuro +* Use error.object per OpenTracing Semantic Conventions (#179) -- Rahman Syed +* Convert nil pointer log field value to string "nil" (#230) -- Cyril Tovena +* Add Go module support (#215) -- Zaba505 +* Make SetTag helper types in ext public (#229) -- Blake Edwards +* Add log/fields helpers for keys from specification (#226) -- Dmitry Monakhov +* Improve noop impementation (#223) -- chanxuehong +* Add an extension to Tracer interface for custom go context creation (#220) -- Krzesimir Nowak +* Fix typo in comments (#222) -- meteorlxy +* Improve documentation for log.Object() to emphasize the requirement to pass immutable arguments (#219) -- 疯狂的小企鹅 +* [mock] Return ErrInvalidSpanContext if span context is not MockSpanContext (#216) -- Milad Irannejad + + 1.1.0 (2019-03-23) ------------------- diff --git a/vendor/github.com/opentracing/opentracing-go/ext.go b/vendor/github.com/opentracing/opentracing-go/ext.go new file mode 100644 index 000000000..e11977ebe --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/ext.go @@ -0,0 +1,24 @@ +package opentracing + +import ( + "context" +) + +// TracerContextWithSpanExtension is an extension interface that the +// implementation of the Tracer interface may want to implement. It +// allows to have some control over the go context when the +// ContextWithSpan is invoked. +// +// The primary purpose of this extension are adapters from opentracing +// API to some other tracing API. +type TracerContextWithSpanExtension interface { + // ContextWithSpanHook gets called by the ContextWithSpan + // function, when the Tracer implementation also implements + // this interface. It allows to put extra information into the + // context and make it available to the callers of the + // ContextWithSpan. + // + // This hook is invoked before the ContextWithSpan function + // actually puts the span into the context. + ContextWithSpanHook(ctx context.Context, span Span) context.Context +} diff --git a/vendor/github.com/opentracing/opentracing-go/ext/field.go b/vendor/github.com/opentracing/opentracing-go/ext/field.go new file mode 100644 index 000000000..8282bd758 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/ext/field.go @@ -0,0 +1,17 @@ +package ext + +import ( + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/log" +) + +// LogError sets the error=true tag on the Span and logs err as an "error" event. +func LogError(span opentracing.Span, err error, fields ...log.Field) { + Error.Set(span, true) + ef := []log.Field{ + log.Event("error"), + log.Error(err), + } + ef = append(ef, fields...) + span.LogFields(ef...) +} diff --git a/vendor/github.com/opentracing/opentracing-go/ext/tags.go b/vendor/github.com/opentracing/opentracing-go/ext/tags.go index 52e889582..a414b5951 100644 --- a/vendor/github.com/opentracing/opentracing-go/ext/tags.go +++ b/vendor/github.com/opentracing/opentracing-go/ext/tags.go @@ -47,40 +47,40 @@ var ( // Component is a low-cardinality identifier of the module, library, // or package that is generating a span. - Component = stringTagName("component") + Component = StringTagName("component") ////////////////////////////////////////////////////////////////////// // Sampling hint ////////////////////////////////////////////////////////////////////// // SamplingPriority determines the priority of sampling this Span. - SamplingPriority = uint16TagName("sampling.priority") + SamplingPriority = Uint16TagName("sampling.priority") ////////////////////////////////////////////////////////////////////// - // Peer tags. These tags can be emitted by either client-side of + // Peer tags. These tags can be emitted by either client-side or // server-side to describe the other side/service in a peer-to-peer // communications, like an RPC call. ////////////////////////////////////////////////////////////////////// // PeerService records the service name of the peer. - PeerService = stringTagName("peer.service") + PeerService = StringTagName("peer.service") // PeerAddress records the address name of the peer. This may be a "ip:port", // a bare "hostname", a FQDN or even a database DSN substring // like "mysql://username@127.0.0.1:3306/dbname" - PeerAddress = stringTagName("peer.address") + PeerAddress = StringTagName("peer.address") // PeerHostname records the host name of the peer - PeerHostname = stringTagName("peer.hostname") + PeerHostname = StringTagName("peer.hostname") // PeerHostIPv4 records IP v4 host address of the peer - PeerHostIPv4 = ipv4Tag("peer.ipv4") + PeerHostIPv4 = IPv4TagName("peer.ipv4") // PeerHostIPv6 records IP v6 host address of the peer - PeerHostIPv6 = stringTagName("peer.ipv6") + PeerHostIPv6 = StringTagName("peer.ipv6") // PeerPort records port number of the peer - PeerPort = uint16TagName("peer.port") + PeerPort = Uint16TagName("peer.port") ////////////////////////////////////////////////////////////////////// // HTTP Tags @@ -88,46 +88,46 @@ var ( // HTTPUrl should be the URL of the request being handled in this segment // of the trace, in standard URI format. The protocol is optional. - HTTPUrl = stringTagName("http.url") + HTTPUrl = StringTagName("http.url") // HTTPMethod is the HTTP method of the request, and is case-insensitive. - HTTPMethod = stringTagName("http.method") + HTTPMethod = StringTagName("http.method") // HTTPStatusCode is the numeric HTTP status code (200, 404, etc) of the // HTTP response. - HTTPStatusCode = uint16TagName("http.status_code") + HTTPStatusCode = Uint16TagName("http.status_code") ////////////////////////////////////////////////////////////////////// // DB Tags ////////////////////////////////////////////////////////////////////// // DBInstance is database instance name. - DBInstance = stringTagName("db.instance") + DBInstance = StringTagName("db.instance") // DBStatement is a database statement for the given database type. // It can be a query or a prepared statement (i.e., before substitution). - DBStatement = stringTagName("db.statement") + DBStatement = StringTagName("db.statement") // DBType is a database type. For any SQL database, "sql". // For others, the lower-case database category, e.g. "redis" - DBType = stringTagName("db.type") + DBType = StringTagName("db.type") // DBUser is a username for accessing database. - DBUser = stringTagName("db.user") + DBUser = StringTagName("db.user") ////////////////////////////////////////////////////////////////////// // Message Bus Tag ////////////////////////////////////////////////////////////////////// // MessageBusDestination is an address at which messages can be exchanged - MessageBusDestination = stringTagName("message_bus.destination") + MessageBusDestination = StringTagName("message_bus.destination") ////////////////////////////////////////////////////////////////////// // Error Tag ////////////////////////////////////////////////////////////////////// // Error indicates that operation represented by the span resulted in an error. - Error = boolTagName("error") + Error = BoolTagName("error") ) // --- @@ -163,48 +163,53 @@ func RPCServerOption(client opentracing.SpanContext) opentracing.StartSpanOption // --- -type stringTagName string +// StringTagName is a common tag name to be set to a string value +type StringTagName string // Set adds a string tag to the `span` -func (tag stringTagName) Set(span opentracing.Span, value string) { +func (tag StringTagName) Set(span opentracing.Span, value string) { span.SetTag(string(tag), value) } // --- -type uint32TagName string +// Uint32TagName is a common tag name to be set to a uint32 value +type Uint32TagName string // Set adds a uint32 tag to the `span` -func (tag uint32TagName) Set(span opentracing.Span, value uint32) { +func (tag Uint32TagName) Set(span opentracing.Span, value uint32) { span.SetTag(string(tag), value) } // --- -type uint16TagName string +// Uint16TagName is a common tag name to be set to a uint16 value +type Uint16TagName string // Set adds a uint16 tag to the `span` -func (tag uint16TagName) Set(span opentracing.Span, value uint16) { +func (tag Uint16TagName) Set(span opentracing.Span, value uint16) { span.SetTag(string(tag), value) } // --- -type boolTagName string +// BoolTagName is a common tag name to be set to a bool value +type BoolTagName string -// Add adds a bool tag to the `span` -func (tag boolTagName) Set(span opentracing.Span, value bool) { +// Set adds a bool tag to the `span` +func (tag BoolTagName) Set(span opentracing.Span, value bool) { span.SetTag(string(tag), value) } -type ipv4Tag string +// IPv4TagName is a common tag name to be set to an ipv4 value +type IPv4TagName string // Set adds IP v4 host address of the peer as an uint32 value to the `span`, keep this for backward and zipkin compatibility -func (tag ipv4Tag) Set(span opentracing.Span, value uint32) { +func (tag IPv4TagName) Set(span opentracing.Span, value uint32) { span.SetTag(string(tag), value) } // SetString records IP v4 host address of the peer as a .-separated tuple to the `span`. E.g., "127.0.0.1" -func (tag ipv4Tag) SetString(span opentracing.Span, value string) { +func (tag IPv4TagName) SetString(span opentracing.Span, value string) { span.SetTag(string(tag), value) } diff --git a/vendor/github.com/opentracing/opentracing-go/go.mod b/vendor/github.com/opentracing/opentracing-go/go.mod new file mode 100644 index 000000000..bf48bb5d7 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/go.mod @@ -0,0 +1,5 @@ +module github.com/opentracing/opentracing-go + +go 1.14 + +require github.com/stretchr/testify v1.3.0 diff --git a/vendor/github.com/opentracing/opentracing-go/go.sum b/vendor/github.com/opentracing/opentracing-go/go.sum new file mode 100644 index 000000000..4347755af --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/go.sum @@ -0,0 +1,7 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/vendor/github.com/opentracing/opentracing-go/gocontext.go b/vendor/github.com/opentracing/opentracing-go/gocontext.go index 08c00c04e..1831bc9b2 100644 --- a/vendor/github.com/opentracing/opentracing-go/gocontext.go +++ b/vendor/github.com/opentracing/opentracing-go/gocontext.go @@ -7,8 +7,13 @@ type contextKey struct{} var activeSpanKey = contextKey{} // ContextWithSpan returns a new `context.Context` that holds a reference to -// `span`'s SpanContext. +// the span. If span is nil, a new context without an active span is returned. func ContextWithSpan(ctx context.Context, span Span) context.Context { + if span != nil { + if tracerWithHook, ok := span.Tracer().(TracerContextWithSpanExtension); ok { + ctx = tracerWithHook.ContextWithSpanHook(ctx, span) + } + } return context.WithValue(ctx, activeSpanKey, span) } diff --git a/vendor/github.com/opentracing/opentracing-go/log/field.go b/vendor/github.com/opentracing/opentracing-go/log/field.go index 50feea341..f222ded79 100644 --- a/vendor/github.com/opentracing/opentracing-go/log/field.go +++ b/vendor/github.com/opentracing/opentracing-go/log/field.go @@ -122,16 +122,19 @@ func Float64(key string, val float64) Field { } } -// Error adds an error with the key "error" to a Span.LogFields() record +// Error adds an error with the key "error.object" to a Span.LogFields() record func Error(err error) Field { return Field{ - key: "error", + key: "error.object", fieldType: errorType, interfaceVal: err, } } // Object adds an object-valued key:value pair to a Span.LogFields() record +// Please pass in an immutable object, otherwise there may be concurrency issues. +// Such as passing in the map, log.Object may result in "fatal error: concurrent map iteration and map write". +// Because span is sent asynchronously, it is possible that this map will also be modified. func Object(key string, obj interface{}) Field { return Field{ key: key, @@ -140,6 +143,16 @@ func Object(key string, obj interface{}) Field { } } +// Event creates a string-valued Field for span logs with key="event" and value=val. +func Event(val string) Field { + return String("event", val) +} + +// Message creates a string-valued Field for span logs with key="message" and value=val. +func Message(val string) Field { + return String("message", val) +} + // LazyLogger allows for user-defined, late-bound logging of arbitrary data type LazyLogger func(fv Encoder) diff --git a/vendor/github.com/opentracing/opentracing-go/log/util.go b/vendor/github.com/opentracing/opentracing-go/log/util.go index 3832feb5c..d57e28aa5 100644 --- a/vendor/github.com/opentracing/opentracing-go/log/util.go +++ b/vendor/github.com/opentracing/opentracing-go/log/util.go @@ -1,6 +1,9 @@ package log -import "fmt" +import ( + "fmt" + "reflect" +) // InterleavedKVToFields converts keyValues a la Span.LogKV() to a Field slice // a la Span.LogFields(). @@ -46,6 +49,10 @@ func InterleavedKVToFields(keyValues ...interface{}) ([]Field, error) { case float64: fields[i] = Float64(key, typedVal) default: + if typedVal == nil || (reflect.ValueOf(typedVal).Kind() == reflect.Ptr && reflect.ValueOf(typedVal).IsNil()) { + fields[i] = String(key, "nil") + continue + } // When in doubt, coerce to a string fields[i] = String(key, fmt.Sprint(typedVal)) } diff --git a/vendor/github.com/opentracing/opentracing-go/noop.go b/vendor/github.com/opentracing/opentracing-go/noop.go index 0d32f692c..f9b680a21 100644 --- a/vendor/github.com/opentracing/opentracing-go/noop.go +++ b/vendor/github.com/opentracing/opentracing-go/noop.go @@ -21,9 +21,9 @@ type noopSpan struct{} type noopSpanContext struct{} var ( - defaultNoopSpanContext = noopSpanContext{} - defaultNoopSpan = noopSpan{} - defaultNoopTracer = NoopTracer{} + defaultNoopSpanContext SpanContext = noopSpanContext{} + defaultNoopSpan Span = noopSpan{} + defaultNoopTracer Tracer = NoopTracer{} ) const ( @@ -35,7 +35,7 @@ func (n noopSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {} // noopSpan: func (n noopSpan) Context() SpanContext { return defaultNoopSpanContext } -func (n noopSpan) SetBaggageItem(key, val string) Span { return defaultNoopSpan } +func (n noopSpan) SetBaggageItem(key, val string) Span { return n } func (n noopSpan) BaggageItem(key string) string { return emptyString } func (n noopSpan) SetTag(key string, value interface{}) Span { return n } func (n noopSpan) LogFields(fields ...log.Field) {} diff --git a/vendor/modules.txt b/vendor/modules.txt index 497381b52..697ce70cb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -84,7 +84,7 @@ github.com/containers/buildah/pkg/secrets github.com/containers/buildah/pkg/supplemented github.com/containers/buildah/pkg/umask github.com/containers/buildah/util -# github.com/containers/common v0.14.3 +# github.com/containers/common v0.15.1 github.com/containers/common/pkg/apparmor github.com/containers/common/pkg/auth github.com/containers/common/pkg/capabilities @@ -437,7 +437,7 @@ github.com/openshift/imagebuilder/dockerfile/command github.com/openshift/imagebuilder/dockerfile/parser github.com/openshift/imagebuilder/signal github.com/openshift/imagebuilder/strslice -# github.com/opentracing/opentracing-go v1.1.0 +# github.com/opentracing/opentracing-go v1.2.0 github.com/opentracing/opentracing-go github.com/opentracing/opentracing-go/ext github.com/opentracing/opentracing-go/log @@ -692,7 +692,7 @@ gopkg.in/yaml.v3 # k8s.io/api v0.18.4 k8s.io/api/apps/v1 k8s.io/api/core/v1 -# k8s.io/apimachinery v0.18.4 +# k8s.io/apimachinery v0.18.5 k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/apis/meta/v1 |