summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/containers/kill.go2
-rw-r--r--cmd/podman/containers/ps.go6
-rw-r--r--cmd/podman/containers/stop.go2
-rw-r--r--go.mod4
-rw-r--r--go.sum8
-rw-r--r--libpod/container_internal_linux.go6
-rw-r--r--libpod/runtime.go37
-rw-r--r--libpod/runtime_pod_infra_linux.go5
-rw-r--r--pkg/api/handlers/compat/containers_create.go1
-rw-r--r--pkg/api/handlers/compat/images.go14
-rw-r--r--pkg/api/handlers/compat/secrets.go8
-rw-r--r--pkg/api/handlers/compat/system.go1
-rw-r--r--pkg/domain/entities/containers.go10
-rw-r--r--pkg/domain/infra/abi/containers.go26
-rw-r--r--pkg/domain/infra/abi/system.go2
-rw-r--r--pkg/domain/infra/tunnel/containers.go22
-rw-r--r--pkg/domain/infra/tunnel/helpers.go23
-rw-r--r--pkg/specgen/generate/oci.go5
-rw-r--r--test/apiv2/10-images.at7
-rw-r--r--test/e2e/common_test.go11
-rw-r--r--test/e2e/kill_test.go13
-rw-r--r--test/e2e/pod_create_test.go14
-rw-r--r--test/e2e/ps_test.go15
-rw-r--r--test/e2e/run_entrypoint_test.go12
-rw-r--r--test/e2e/run_test.go23
-rw-r--r--test/e2e/start_test.go17
-rw-r--r--test/e2e/stop_test.go6
-rw-r--r--test/system/030-run.bats6
-rw-r--r--vendor/github.com/magefile/mage/LICENSE201
-rw-r--r--vendor/github.com/magefile/mage/mg/color.go80
-rw-r--r--vendor/github.com/magefile/mage/mg/color_string.go38
-rw-r--r--vendor/github.com/magefile/mage/mg/deps.go352
-rw-r--r--vendor/github.com/magefile/mage/mg/errors.go51
-rw-r--r--vendor/github.com/magefile/mage/mg/runtime.go136
-rw-r--r--vendor/github.com/magefile/mage/sh/cmd.go177
-rw-r--r--vendor/github.com/magefile/mage/sh/helpers.go40
-rw-r--r--vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go3
-rw-r--r--vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go4
-rw-r--r--vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go144
-rw-r--r--vendor/github.com/sirupsen/logrus/.travis.yml13
-rw-r--r--vendor/github.com/sirupsen/logrus/CHANGELOG.md20
-rw-r--r--vendor/github.com/sirupsen/logrus/README.md2
-rw-r--r--vendor/github.com/sirupsen/logrus/entry.go73
-rw-r--r--vendor/github.com/sirupsen/logrus/go.mod1
-rw-r--r--vendor/github.com/sirupsen/logrus/go.sum2
-rw-r--r--vendor/github.com/sirupsen/logrus/json_formatter.go2
-rw-r--r--vendor/github.com/sirupsen/logrus/logger.go2
-rw-r--r--vendor/github.com/sirupsen/logrus/magefile.go77
-rw-r--r--vendor/github.com/sirupsen/logrus/terminal_check_unix.go2
-rw-r--r--vendor/github.com/sirupsen/logrus/text_formatter.go2
-rw-r--r--vendor/modules.txt7
51 files changed, 1594 insertions, 141 deletions
diff --git a/cmd/podman/containers/kill.go b/cmd/podman/containers/kill.go
index 36e3e5f59..990a6e3e7 100644
--- a/cmd/podman/containers/kill.go
+++ b/cmd/podman/containers/kill.go
@@ -111,7 +111,7 @@ func kill(_ *cobra.Command, args []string) error {
}
for _, r := range responses {
if r.Err == nil {
- fmt.Println(r.Id)
+ fmt.Println(r.RawInput)
} else {
errs = append(errs, r.Err)
}
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index 51e7bf5b5..55b53b4d9 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -22,6 +22,7 @@ import (
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/go-units"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -390,6 +391,11 @@ func (l psReporter) Command() string {
// Size returns the rootfs and virtual sizes in human duration in
// and output form (string) suitable for ps
func (l psReporter) Size() string {
+ if l.ListContainer.Size == nil {
+ logrus.Errorf("Size format requires --size option")
+ return ""
+ }
+
virt := units.HumanSizeWithPrecision(float64(l.ListContainer.Size.RootFsSize), 3)
s := units.HumanSizeWithPrecision(float64(l.ListContainer.Size.RwSize), 3)
return fmt.Sprintf("%s (virtual %s)", s, virt)
diff --git a/cmd/podman/containers/stop.go b/cmd/podman/containers/stop.go
index 7338c8d98..1fe41a1bd 100644
--- a/cmd/podman/containers/stop.go
+++ b/cmd/podman/containers/stop.go
@@ -115,7 +115,7 @@ func stop(cmd *cobra.Command, args []string) error {
}
for _, r := range responses {
if r.Err == nil {
- fmt.Println(r.Id)
+ fmt.Println(r.RawInput)
} else {
errs = append(errs, r.Err)
}
diff --git a/go.mod b/go.mod
index 97c366d73..ac1f70ca0 100644
--- a/go.mod
+++ b/go.mod
@@ -50,8 +50,8 @@ require (
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.13.0
- github.com/sirupsen/logrus v1.7.0
+ github.com/rootless-containers/rootlesskit v0.13.1
+ github.com/sirupsen/logrus v1.7.1
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
diff --git a/go.sum b/go.sum
index 1213d200c..ed6bc6e4b 100644
--- a/go.sum
+++ b/go.sum
@@ -367,6 +367,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
+github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
+github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -528,8 +530,8 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rootless-containers/rootlesskit v0.13.0 h1:41nnfB7yFxtHSeQHYupSvVxAJWh/hjmn03w6UjH7nv8=
-github.com/rootless-containers/rootlesskit v0.13.0/go.mod h1:DwE/9ASct8sj7bueOXqKiwcdzyZ+yV6qhTAtJUO7988=
+github.com/rootless-containers/rootlesskit v0.13.1 h1:QIMHxf00SaUinpJ2r9vwD4z6E3Yq8kk/aZ6ItNXIPHA=
+github.com/rootless-containers/rootlesskit v0.13.1/go.mod h1:DwE/9ASct8sj7bueOXqKiwcdzyZ+yV6qhTAtJUO7988=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
@@ -549,6 +551,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.7.1 h1:rsizeFmZP+GYwyb4V6t6qpG7ZNWzA2bvgW/yC2xHCcg=
+github.com/sirupsen/logrus v1.7.1/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index f23a5233c..edbbefb55 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -466,7 +466,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
break
}
}
- if !hasHomeSet {
+ if !hasHomeSet && execUser.Home != "" {
c.config.Spec.Process.Env = append(c.config.Spec.Process.Env, fmt.Sprintf("HOME=%s", execUser.Home))
}
@@ -1627,7 +1627,7 @@ func (c *Container) makeBindMounts() error {
// Make .containerenv if it does not exist
if _, ok := c.state.BindMounts["/run/.containerenv"]; !ok {
- var containerenv string
+ containerenv := c.runtime.graphRootMountedFlag(c.config.Spec.Mounts)
isRootless := 0
if rootless.IsRootless() {
isRootless = 1
@@ -1642,7 +1642,7 @@ id=%q
image=%q
imageid=%q
rootless=%d
-`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless)
+%s`, version.Version.String(), c.Name(), c.ID(), imageName, imageID, isRootless, containerenv)
}
containerenvPath, err := c.writeStringToRundir(".containerenv", containerenv)
if err != nil {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 42af2046d..c04d91b9d 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "bufio"
"context"
"fmt"
"os"
@@ -26,6 +27,7 @@ import (
"github.com/containers/storage"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/docker/pkg/namesgenerator"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -622,9 +624,12 @@ func (r *Runtime) Shutdown(force bool) error {
func (r *Runtime) refresh(alivePath string) error {
logrus.Debugf("Podman detected system restart - performing state refresh")
- // First clear the state in the database
- if err := r.state.Refresh(); err != nil {
- return err
+ // Clear state of database if not running in container
+ if !graphRootMounted() {
+ // First clear the state in the database
+ if err := r.state.Refresh(); err != nil {
+ return err
+ }
}
// Next refresh the state of all containers to recreate dirs and
@@ -904,3 +909,29 @@ func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) {
func (r *Runtime) GetSecretsStorageDir() string {
return filepath.Join(r.store.GraphRoot(), "secrets")
}
+
+func graphRootMounted() bool {
+ f, err := os.OpenFile("/run/.containerenv", os.O_RDONLY, os.ModePerm)
+ if err != nil {
+ return false
+ }
+ defer f.Close()
+
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ if scanner.Text() == "graphRootMounted=1" {
+ return true
+ }
+ }
+ return false
+}
+
+func (r *Runtime) graphRootMountedFlag(mounts []spec.Mount) string {
+ root := r.store.GraphRoot()
+ for _, val := range mounts {
+ if strings.HasPrefix(root, val.Source) {
+ return "graphRootMounted=1"
+ }
+ }
+ return ""
+}
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index bc37bdb23..c6f268182 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -225,7 +225,10 @@ func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container,
if err != nil {
return nil, err
}
- imageName := newImage.Names()[0]
+ imageName := "none"
+ if len(newImage.Names()) > 0 {
+ imageName = newImage.Names()[0]
+ }
imageID := data.ID
return r.makeInfraContainer(ctx, p, imageName, r.config.Engine.InfraImage, imageID, data.Config)
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 6e85872b2..4a39e9563 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -47,6 +47,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
rtc, err := runtime.GetConfig()
if err != nil {
utils.Error(w, "unable to obtain runtime config", http.StatusInternalServerError, errors.Wrap(err, "unable to get runtime config"))
+ return
}
newImage, err := runtime.ImageRuntime().NewFromLocal(body.Config.Image)
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 85708912b..0d75d1a94 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -10,7 +10,6 @@ import (
"strings"
"github.com/containers/buildah"
- "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/manifest"
"github.com/containers/podman/v2/libpod"
image2 "github.com/containers/podman/v2/libpod/image"
@@ -18,6 +17,7 @@ import (
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/auth"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/util"
"github.com/gorilla/schema"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
@@ -236,16 +236,6 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
if sys := runtime.SystemContext(); sys != nil {
registryOpts.DockerCertPath = sys.DockerCertPath
}
- rtc, err := runtime.GetConfig()
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
- return
- }
- pullPolicy, err := config.ValidatePullPolicy(rtc.Engine.PullPolicy)
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
- return
- }
img, err := runtime.ImageRuntime().New(r.Context(),
fromImage,
"", // signature policy
@@ -254,7 +244,7 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
&registryOpts,
image2.SigningOptions{},
nil, // label
- pullPolicy,
+ util.PullImageAlways,
)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
index 571888eba..ff737cddc 100644
--- a/pkg/api/handlers/compat/secrets.go
+++ b/pkg/api/handlers/compat/secrets.go
@@ -30,7 +30,9 @@ func ListSecrets(w http.ResponseWriter, r *http.Request) {
return
}
if len(query.Filters) > 0 {
- utils.Error(w, "filters not supported", http.StatusBadRequest, errors.New("bad parameter"))
+ utils.Error(w, "filters not supported", http.StatusBadRequest,
+ errors.Wrapf(errors.New("bad parameter"), "filters not supported"))
+ return
}
ic := abi.ContainerEngine{Libpod: runtime}
reports, err := ic.SecretList(r.Context())
@@ -95,7 +97,9 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) {
return
}
if len(createParams.Labels) > 0 {
- utils.Error(w, "labels not supported", http.StatusBadRequest, errors.New("bad parameter"))
+ utils.Error(w, "labels not supported", http.StatusBadRequest,
+ errors.Wrapf(errors.New("bad parameter"), "labels not supported"))
+ return
}
decoded, _ := base64.StdEncoding.DecodeString(createParams.Data)
diff --git a/pkg/api/handlers/compat/system.go b/pkg/api/handlers/compat/system.go
index e21ae160a..66b4236f9 100644
--- a/pkg/api/handlers/compat/system.go
+++ b/pkg/api/handlers/compat/system.go
@@ -19,6 +19,7 @@ func GetDiskUsage(w http.ResponseWriter, r *http.Request) {
df, err := ic.SystemDf(r.Context(), options)
if err != nil {
utils.InternalServerError(w, err)
+ return
}
imgs := make([]*docker.ImageSummary, len(df.Images))
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 2d50d6826..116da888d 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -88,8 +88,9 @@ type StopOptions struct {
}
type StopReport struct {
- Err error
- Id string //nolint
+ Err error
+ Id string //nolint
+ RawInput string
}
type TopOptions struct {
@@ -109,8 +110,9 @@ type KillOptions struct {
}
type KillReport struct {
- Err error
- Id string //nolint
+ Err error
+ Id string //nolint
+ RawInput string
}
type RestartOptions struct {
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 7a672d863..0ee4048d1 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -138,10 +138,16 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
}
func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) {
names := namesOrIds
- ctrs, err := getContainersByContext(options.All, options.Latest, names, ic.Libpod)
+ ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, names, ic.Libpod)
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) {
return nil, err
}
+ ctrMap := map[string]string{}
+ if len(rawInputs) == len(ctrs) {
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID()] = rawInputs[i]
+ }
+ }
errMap, err := parallelctr.ContainerOp(ctx, ctrs, func(c *libpod.Container) error {
var err error
if options.Timeout != nil {
@@ -174,6 +180,11 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
for ctr, err := range errMap {
report := new(entities.StopReport)
report.Id = ctr.ID()
+ if options.All {
+ report.RawInput = ctr.ID()
+ } else {
+ report.RawInput = ctrMap[ctr.ID()]
+ }
report.Err = err
reports = append(reports, report)
}
@@ -197,15 +208,22 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
if err != nil {
return nil, err
}
- ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
+ ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
+ ctrMap := map[string]string{}
+ if len(rawInputs) == len(ctrs) {
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID()] = rawInputs[i]
+ }
+ }
reports := make([]*entities.KillReport, 0, len(ctrs))
for _, con := range ctrs {
reports = append(reports, &entities.KillReport{
- Id: con.ID(),
- Err: con.Kill(uint(sig)),
+ Id: con.ID(),
+ Err: con.Kill(uint(sig)),
+ RawInput: ctrMap[con.ID()],
})
}
return reports, nil
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index f29b98696..c68a12414 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -82,7 +82,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command)
unitName := fmt.Sprintf("podman-%d.scope", os.Getpid())
if runsUnderSystemd || conf.Engine.CgroupManager == config.SystemdCgroupsManager {
if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil {
- logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err)
+ logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err)
}
}
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index c2c282ef9..b0a07cd27 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -82,16 +82,23 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, opts entities.StopOptions) ([]*entities.StopReport, error) {
reports := []*entities.StopReport{}
- ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, opts.Ignore, namesOrIds)
+ ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, opts.All, opts.Ignore, namesOrIds)
if err != nil {
return nil, err
}
+ ctrMap := map[string]string{}
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID] = rawInputs[i]
+ }
options := new(containers.StopOptions).WithIgnore(opts.Ignore)
if to := opts.Timeout; to != nil {
options.WithTimeout(*to)
}
for _, c := range ctrs {
- report := entities.StopReport{Id: c.ID}
+ report := entities.StopReport{
+ Id: c.ID,
+ RawInput: ctrMap[c.ID],
+ }
if err = containers.Stop(ic.ClientCtx, c.ID, options); err != nil {
// These first two are considered non-fatal under the right conditions
if errors.Cause(err).Error() == define.ErrCtrStopped.Error() {
@@ -117,16 +124,21 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, opts entities.KillOptions) ([]*entities.KillReport, error) {
- ctrs, err := getContainersByContext(ic.ClientCtx, opts.All, false, namesOrIds)
+ ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, opts.All, false, namesOrIds)
if err != nil {
return nil, err
}
+ ctrMap := map[string]string{}
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID] = rawInputs[i]
+ }
options := new(containers.KillOptions).WithSignal(opts.Signal)
reports := make([]*entities.KillReport, 0, len(ctrs))
for _, c := range ctrs {
reports = append(reports, &entities.KillReport{
- Id: c.ID,
- Err: containers.Kill(ic.ClientCtx, c.ID, options),
+ Id: c.ID,
+ Err: containers.Kill(ic.ClientCtx, c.ID, options),
+ RawInput: ctrMap[c.ID],
})
}
return reports, nil
diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go
index e40e27596..5fa70bffa 100644
--- a/pkg/domain/infra/tunnel/helpers.go
+++ b/pkg/domain/infra/tunnel/helpers.go
@@ -14,16 +14,26 @@ import (
// FIXME: the `ignore` parameter is very likely wrong here as it should rather
// be used on *errors* from operations such as remove.
func getContainersByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, error) {
+ ctrs, _, err := getContainersAndInputByContext(contextWithConnection, all, ignore, namesOrIDs)
+ return ctrs, err
+}
+
+func getContainersAndInputByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, []string, error) {
if all && len(namesOrIDs) > 0 {
- return nil, errors.New("cannot lookup containers and all")
+ return nil, nil, errors.New("cannot lookup containers and all")
}
options := new(containers.ListOptions).WithAll(true).WithSync(true)
allContainers, err := containers.List(contextWithConnection, options)
if err != nil {
- return nil, err
+ return nil, nil, err
}
+ rawInputs := []string{}
if all {
- return allContainers, err
+ for i := range allContainers {
+ rawInputs = append(rawInputs, allContainers[i].ID)
+ }
+
+ return allContainers, rawInputs, err
}
// Note: it would be nicer if the lists endpoint would support that as
@@ -42,7 +52,7 @@ func getContainersByContext(contextWithConnection context.Context, all, ignore b
if ignore && errorhandling.Contains(err, define.ErrNoSuchCtr) {
continue
}
- return nil, err
+ return nil, nil, err
}
// Now we can do a full match of the ID to find the right
@@ -52,16 +62,17 @@ func getContainersByContext(contextWithConnection context.Context, all, ignore b
for _, ctr := range allContainers {
if ctr.ID == inspectData.ID {
filtered = append(filtered, ctr)
+ rawInputs = append(rawInputs, nameOrID)
found = true
break
}
}
if !found && !ignore {
- return nil, errors.Wrapf(define.ErrNoSuchCtr, "unable to find container %q", nameOrID)
+ return nil, nil, errors.Wrapf(define.ErrNoSuchCtr, "unable to find container %q", nameOrID)
}
}
- return filtered, nil
+ return filtered, rawInputs, nil
}
func getPodsByContext(contextWithConnection context.Context, all bool, namesOrIDs []string) ([]*entities.ListPodsReport, error) {
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 1a0ec08a5..eefe45dfe 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -105,7 +105,10 @@ func makeCommand(ctx context.Context, s *specgen.SpecGenerator, img *image.Image
entrypoint = newEntry
}
- finalCommand = append(finalCommand, entrypoint...)
+ // Don't append the entrypoint if it is [""]
+ if len(entrypoint) != 1 || entrypoint[0] != "" {
+ finalCommand = append(finalCommand, entrypoint...)
+ }
// Only use image command if the user did not manually set an
// entrypoint.
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 693c34ced..a650cf958 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -45,6 +45,13 @@ t POST "images/create?fromImage=alpine" '' 200 .error=null .status~".*Download c
t POST "images/create?fromImage=alpine&tag=latest" '' 200
+# Make sure that new images are pulled
+old_iid=$(podman image inspect --format "{{.ID}}" docker.io/library/alpine:latest)
+podman rmi -f docker.io/library/alpine:latest
+podman tag $IMAGE docker.io/library/alpine:latest
+t POST "images/create?fromImage=alpine" '' 200 .error=null .status~".*$old_iid.*"
+podman untag $IMAGE docker.io/library/alpine:latest
+
t POST "images/create?fromImage=quay.io/libpod/alpine&tag=sha256:fa93b01658e3a5a1686dc3ae55f170d8de487006fb53a28efcd12ab0710a2e5f" '' 200
# Display the image history
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index d033cc646..12b30b2c5 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -436,13 +436,20 @@ func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSe
// BuildImage uses podman build and buildah to build an image
// called imageName based on a string dockerfile
-func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) {
+func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) string {
dockerfilePath := filepath.Join(p.TempDir, "Dockerfile")
err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755)
Expect(err).To(BeNil())
- session := p.Podman([]string{"build", "--layers=" + layers, "-t", imageName, "--file", dockerfilePath, p.TempDir})
+ cmd := []string{"build", "--layers=" + layers, "--file", dockerfilePath}
+ if len(imageName) > 0 {
+ cmd = append(cmd, []string{"-t", imageName}...)
+ }
+ cmd = append(cmd, p.TempDir)
+ session := p.Podman(cmd)
session.Wait(240)
Expect(session).Should(Exit(0), fmt.Sprintf("BuildImage session output: %q", session.OutputToString()))
+ output := session.OutputToStringArray()
+ return output[len(output)-1]
}
// PodmanPID execs podman and returns its PID
diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go
index c1c1b003e..6d6fe788b 100644
--- a/test/e2e/kill_test.go
+++ b/test/e2e/kill_test.go
@@ -51,6 +51,19 @@ var _ = Describe("Podman kill", func() {
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
+ It("podman container kill a running container by short id", func() {
+ session := podmanTest.RunTopContainer("")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ cid := session.OutputToString()
+
+ result := podmanTest.Podman([]string{"container", "kill", cid[:5]})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+ Expect(result.OutputToString()).To(Equal(cid[:5]))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ })
+
It("podman kill a running container by id", func() {
session := podmanTest.RunTopContainer("")
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index e57712f62..0a7a5101e 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -501,4 +501,18 @@ entrypoint ["/fromimage"]
Expect(session.OutputToString()).To(ContainSubstring("inet 127.0.0.1/8 scope host lo"))
Expect(len(session.OutputToStringArray())).To(Equal(1))
})
+
+ It("podman pod create --infra-image w/untagged image", func() {
+ podmanTest.AddImageToRWStore(ALPINE)
+ dockerfile := `FROM quay.io/libpod/alpine:latest
+ENTRYPOINT ["sleep","99999"]
+ `
+ // This builds a none/none image
+ iid := podmanTest.BuildImage(dockerfile, "", "true")
+
+ create := podmanTest.Podman([]string{"pod", "create", "--infra-image", iid})
+ create.WaitWithDefaultTimeout()
+ Expect(create.ExitCode()).To(BeZero())
+ })
+
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 225bd538e..016b4c8cd 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -350,6 +350,21 @@ var _ = Describe("Podman ps", func() {
Expect(session).To(ExitWithError())
})
+ It("podman --format by size", func() {
+ session := podmanTest.Podman([]string{"create", "busybox", "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"create", "-t", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"ps", "-a", "--format", "{{.Size}}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.ErrorToString()).To(ContainSubstring("Size format requires --size option"))
+ })
+
It("podman --sort by size", func() {
session := podmanTest.Podman([]string{"create", "busybox", "ls"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go
index cac3d759d..389f142b1 100644
--- a/test/e2e/run_entrypoint_test.go
+++ b/test/e2e/run_entrypoint_test.go
@@ -43,6 +43,18 @@ CMD []
Expect(session.ExitCode()).To(Equal(125))
})
+ It("podman run entrypoint == [\"\"]", func() {
+ dockerfile := `FROM quay.io/libpod/alpine:latest
+ENTRYPOINT [""]
+CMD []
+`
+ podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false")
+ session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest", "echo", "hello"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal("hello"))
+ })
+
It("podman run entrypoint", func() {
dockerfile := `FROM quay.io/libpod/alpine:latest
ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 18db63c15..f333b8afd 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -47,6 +47,29 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
})
+ It("podman run check /run/.containerenv", func() {
+ session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal(""))
+
+ session = podmanTest.Podman([]string{"run", "--privileged", "--name=test1", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("name=\"test1\""))
+ Expect(session.OutputToString()).To(ContainSubstring("image=\"" + ALPINE + "\""))
+
+ session = podmanTest.Podman([]string{"run", "-v", "/:/host", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("graphRootMounted=1"))
+
+ session = podmanTest.Podman([]string{"run", "-v", "/:/host", "--privileged", ALPINE, "cat", "/run/.containerenv"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("graphRootMounted=1"))
+ })
+
It("podman run a container based on a complex local image name", func() {
imageName := strings.TrimPrefix(nginx, "quay.io/")
session := podmanTest.Podman([]string{"run", imageName, "ls"})
diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go
index a6f22e007..74be105d8 100644
--- a/test/e2e/start_test.go
+++ b/test/e2e/start_test.go
@@ -95,6 +95,23 @@ var _ = Describe("Podman start", func() {
Expect(session.OutputToString()).To(Equal(shortID))
})
+ It("podman container start single container by short id", func() {
+ session := podmanTest.Podman([]string{"container", "create", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ cid := session.OutputToString()
+ shortID := cid[0:10]
+ session = podmanTest.Podman([]string{"container", "start", shortID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal(shortID))
+
+ session = podmanTest.Podman([]string{"stop", shortID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal(shortID))
+ })
+
It("podman start single container by name", func() {
name := "foobar99"
session := podmanTest.Podman([]string{"create", "--name", name, ALPINE, "ls"})
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index 750d38ffb..337fd651d 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -149,13 +149,12 @@ var _ = Describe("Podman stop", func() {
session := podmanTest.RunTopContainer("test4")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- cid1 := session.OutputToString()
session = podmanTest.Podman([]string{"stop", "--time", "1", "test4"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
output := session.OutputToString()
- Expect(output).To(ContainSubstring(cid1))
+ Expect(output).To(ContainSubstring("test4"))
finalCtrs := podmanTest.Podman([]string{"ps", "-q"})
finalCtrs.WaitWithDefaultTimeout()
@@ -167,14 +166,13 @@ var _ = Describe("Podman stop", func() {
session := podmanTest.Podman([]string{"run", "-d", "--name", "test5", ALPINE, "sleep", "100"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- cid1 := session.OutputToString()
session = podmanTest.Podman([]string{"stop", "--timeout", "1", "test5"})
// Without timeout container stops in 10 seconds
// If not stopped in 5 seconds, then --timeout did not work
session.Wait(5)
Expect(session.ExitCode()).To(Equal(0))
output := session.OutputToString()
- Expect(output).To(ContainSubstring(cid1))
+ Expect(output).To(ContainSubstring("test5"))
finalCtrs := podmanTest.Podman([]string{"ps", "-q"})
finalCtrs.WaitWithDefaultTimeout()
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 3749dcac5..93449ece9 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -662,4 +662,10 @@ json-file | f
run_podman rm $cname
}
+@test "podman run - do not set empty HOME" {
+ # Regression test for #9378.
+ run_podman run --rm --user 100 $IMAGE printenv
+ is "$output" ".*HOME=/.*"
+}
+
# vim: filetype=sh
diff --git a/vendor/github.com/magefile/mage/LICENSE b/vendor/github.com/magefile/mage/LICENSE
new file mode 100644
index 000000000..d0632bc14
--- /dev/null
+++ b/vendor/github.com/magefile/mage/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2017 the Mage authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/magefile/mage/mg/color.go b/vendor/github.com/magefile/mage/mg/color.go
new file mode 100644
index 000000000..3e2710332
--- /dev/null
+++ b/vendor/github.com/magefile/mage/mg/color.go
@@ -0,0 +1,80 @@
+package mg
+
+// Color is ANSI color type
+type Color int
+
+// If you add/change/remove any items in this constant,
+// you will need to run "stringer -type=Color" in this directory again.
+// NOTE: Please keep the list in an alphabetical order.
+const (
+ Black Color = iota
+ Red
+ Green
+ Yellow
+ Blue
+ Magenta
+ Cyan
+ White
+ BrightBlack
+ BrightRed
+ BrightGreen
+ BrightYellow
+ BrightBlue
+ BrightMagenta
+ BrightCyan
+ BrightWhite
+)
+
+// AnsiColor are ANSI color codes for supported terminal colors.
+var ansiColor = map[Color]string{
+ Black: "\u001b[30m",
+ Red: "\u001b[31m",
+ Green: "\u001b[32m",
+ Yellow: "\u001b[33m",
+ Blue: "\u001b[34m",
+ Magenta: "\u001b[35m",
+ Cyan: "\u001b[36m",
+ White: "\u001b[37m",
+ BrightBlack: "\u001b[30;1m",
+ BrightRed: "\u001b[31;1m",
+ BrightGreen: "\u001b[32;1m",
+ BrightYellow: "\u001b[33;1m",
+ BrightBlue: "\u001b[34;1m",
+ BrightMagenta: "\u001b[35;1m",
+ BrightCyan: "\u001b[36;1m",
+ BrightWhite: "\u001b[37;1m",
+}
+
+// AnsiColorReset is an ANSI color code to reset the terminal color.
+const AnsiColorReset = "\033[0m"
+
+// DefaultTargetAnsiColor is a default ANSI color for colorizing targets.
+// It is set to Cyan as an arbitrary color, because it has a neutral meaning
+var DefaultTargetAnsiColor = ansiColor[Cyan]
+
+func toLowerCase(s string) string {
+ // this is a naive implementation
+ // borrowed from https://golang.org/src/strings/strings.go
+ // and only considers alphabetical characters [a-zA-Z]
+ // so that we don't depend on the "strings" package
+ buf := make([]byte, len(s))
+ for i := 0; i < len(s); i++ {
+ c := s[i]
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ buf[i] = c
+ }
+ return string(buf)
+}
+
+func getAnsiColor(color string) (string, bool) {
+ colorLower := toLowerCase(color)
+ for k, v := range ansiColor {
+ colorConstLower := toLowerCase(k.String())
+ if colorConstLower == colorLower {
+ return v, true
+ }
+ }
+ return "", false
+}
diff --git a/vendor/github.com/magefile/mage/mg/color_string.go b/vendor/github.com/magefile/mage/mg/color_string.go
new file mode 100644
index 000000000..06debca54
--- /dev/null
+++ b/vendor/github.com/magefile/mage/mg/color_string.go
@@ -0,0 +1,38 @@
+// Code generated by "stringer -type=Color"; DO NOT EDIT.
+
+package mg
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[Black-0]
+ _ = x[Red-1]
+ _ = x[Green-2]
+ _ = x[Yellow-3]
+ _ = x[Blue-4]
+ _ = x[Magenta-5]
+ _ = x[Cyan-6]
+ _ = x[White-7]
+ _ = x[BrightBlack-8]
+ _ = x[BrightRed-9]
+ _ = x[BrightGreen-10]
+ _ = x[BrightYellow-11]
+ _ = x[BrightBlue-12]
+ _ = x[BrightMagenta-13]
+ _ = x[BrightCyan-14]
+ _ = x[BrightWhite-15]
+}
+
+const _Color_name = "BlackRedGreenYellowBlueMagentaCyanWhiteBrightBlackBrightRedBrightGreenBrightYellowBrightBlueBrightMagentaBrightCyanBrightWhite"
+
+var _Color_index = [...]uint8{0, 5, 8, 13, 19, 23, 30, 34, 39, 50, 59, 70, 82, 92, 105, 115, 126}
+
+func (i Color) String() string {
+ if i < 0 || i >= Color(len(_Color_index)-1) {
+ return "Color(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _Color_name[_Color_index[i]:_Color_index[i+1]]
+}
diff --git a/vendor/github.com/magefile/mage/mg/deps.go b/vendor/github.com/magefile/mage/mg/deps.go
new file mode 100644
index 000000000..ad85931f8
--- /dev/null
+++ b/vendor/github.com/magefile/mage/mg/deps.go
@@ -0,0 +1,352 @@
+package mg
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "runtime"
+ "strings"
+ "sync"
+)
+
+// funcType indicates a prototype of build job function
+type funcType int
+
+// funcTypes
+const (
+ invalidType funcType = iota
+ voidType
+ errorType
+ contextVoidType
+ contextErrorType
+ namespaceVoidType
+ namespaceErrorType
+ namespaceContextVoidType
+ namespaceContextErrorType
+)
+
+var logger = log.New(os.Stderr, "", 0)
+
+type onceMap struct {
+ mu *sync.Mutex
+ m map[string]*onceFun
+}
+
+func (o *onceMap) LoadOrStore(s string, one *onceFun) *onceFun {
+ defer o.mu.Unlock()
+ o.mu.Lock()
+
+ existing, ok := o.m[s]
+ if ok {
+ return existing
+ }
+ o.m[s] = one
+ return one
+}
+
+var onces = &onceMap{
+ mu: &sync.Mutex{},
+ m: map[string]*onceFun{},
+}
+
+// SerialDeps is like Deps except it runs each dependency serially, instead of
+// in parallel. This can be useful for resource intensive dependencies that
+// shouldn't be run at the same time.
+func SerialDeps(fns ...interface{}) {
+ types := checkFns(fns)
+ ctx := context.Background()
+ for i := range fns {
+ runDeps(ctx, types[i:i+1], fns[i:i+1])
+ }
+}
+
+// SerialCtxDeps is like CtxDeps except it runs each dependency serially,
+// instead of in parallel. This can be useful for resource intensive
+// dependencies that shouldn't be run at the same time.
+func SerialCtxDeps(ctx context.Context, fns ...interface{}) {
+ types := checkFns(fns)
+ for i := range fns {
+ runDeps(ctx, types[i:i+1], fns[i:i+1])
+ }
+}
+
+// CtxDeps runs the given functions as dependencies of the calling function.
+// Dependencies must only be of type:
+// func()
+// func() error
+// func(context.Context)
+// func(context.Context) error
+// Or a similar method on a mg.Namespace type.
+//
+// The function calling Deps is guaranteed that all dependent functions will be
+// run exactly once when Deps returns. Dependent functions may in turn declare
+// their own dependencies using Deps. Each dependency is run in their own
+// goroutines. Each function is given the context provided if the function
+// prototype allows for it.
+func CtxDeps(ctx context.Context, fns ...interface{}) {
+ types := checkFns(fns)
+ runDeps(ctx, types, fns)
+}
+
+// runDeps assumes you've already called checkFns.
+func runDeps(ctx context.Context, types []funcType, fns []interface{}) {
+ mu := &sync.Mutex{}
+ var errs []string
+ var exit int
+ wg := &sync.WaitGroup{}
+ for i, f := range fns {
+ fn := addDep(ctx, types[i], f)
+ wg.Add(1)
+ go func() {
+ defer func() {
+ if v := recover(); v != nil {
+ mu.Lock()
+ if err, ok := v.(error); ok {
+ exit = changeExit(exit, ExitStatus(err))
+ } else {
+ exit = changeExit(exit, 1)
+ }
+ errs = append(errs, fmt.Sprint(v))
+ mu.Unlock()
+ }
+ wg.Done()
+ }()
+ if err := fn.run(); err != nil {
+ mu.Lock()
+ errs = append(errs, fmt.Sprint(err))
+ exit = changeExit(exit, ExitStatus(err))
+ mu.Unlock()
+ }
+ }()
+ }
+
+ wg.Wait()
+ if len(errs) > 0 {
+ panic(Fatal(exit, strings.Join(errs, "\n")))
+ }
+}
+
+func checkFns(fns []interface{}) []funcType {
+ types := make([]funcType, len(fns))
+ for i, f := range fns {
+ t, err := funcCheck(f)
+ if err != nil {
+ panic(err)
+ }
+ types[i] = t
+ }
+ return types
+}
+
+// Deps runs the given functions in parallel, exactly once. Dependencies must
+// only be of type:
+// func()
+// func() error
+// func(context.Context)
+// func(context.Context) error
+// Or a similar method on a mg.Namespace type.
+//
+// This is a way to build up a tree of dependencies with each dependency
+// defining its own dependencies. Functions must have the same signature as a
+// Mage target, i.e. optional context argument, optional error return.
+func Deps(fns ...interface{}) {
+ CtxDeps(context.Background(), fns...)
+}
+
+func changeExit(old, new int) int {
+ if new == 0 {
+ return old
+ }
+ if old == 0 {
+ return new
+ }
+ if old == new {
+ return old
+ }
+ // both different and both non-zero, just set
+ // exit to 1. Nothing more we can do.
+ return 1
+}
+
+func addDep(ctx context.Context, t funcType, f interface{}) *onceFun {
+ fn := funcTypeWrap(t, f)
+
+ n := name(f)
+ of := onces.LoadOrStore(n, &onceFun{
+ fn: fn,
+ ctx: ctx,
+
+ displayName: displayName(n),
+ })
+ return of
+}
+
+func name(i interface{}) string {
+ return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
+}
+
+func displayName(name string) string {
+ splitByPackage := strings.Split(name, ".")
+ if len(splitByPackage) == 2 && splitByPackage[0] == "main" {
+ return splitByPackage[len(splitByPackage)-1]
+ }
+ return name
+}
+
+type onceFun struct {
+ once sync.Once
+ fn func(context.Context) error
+ ctx context.Context
+ err error
+
+ displayName string
+}
+
+func (o *onceFun) run() error {
+ o.once.Do(func() {
+ if Verbose() {
+ logger.Println("Running dependency:", o.displayName)
+ }
+ o.err = o.fn(o.ctx)
+ })
+ return o.err
+}
+
+// Returns a location of mg.Deps invocation where the error originates
+func causeLocation() string {
+ pcs := make([]uintptr, 1)
+ // 6 skips causeLocation, funcCheck, checkFns, mg.CtxDeps, mg.Deps in stacktrace
+ if runtime.Callers(6, pcs) != 1 {
+ return "<unknown>"
+ }
+ frames := runtime.CallersFrames(pcs)
+ frame, _ := frames.Next()
+ if frame.Function == "" && frame.File == "" && frame.Line == 0 {
+ return "<unknown>"
+ }
+ return fmt.Sprintf("%s %s:%d", frame.Function, frame.File, frame.Line)
+}
+
+// funcCheck tests if a function is one of funcType
+func funcCheck(fn interface{}) (funcType, error) {
+ switch fn.(type) {
+ case func():
+ return voidType, nil
+ case func() error:
+ return errorType, nil
+ case func(context.Context):
+ return contextVoidType, nil
+ case func(context.Context) error:
+ return contextErrorType, nil
+ }
+
+ err := fmt.Errorf("Invalid type for dependent function: %T. Dependencies must be func(), func() error, func(context.Context), func(context.Context) error, or the same method on an mg.Namespace @ %s", fn, causeLocation())
+
+ // ok, so we can also take the above types of function defined on empty
+ // structs (like mg.Namespace). When you pass a method of a type, it gets
+ // passed as a function where the first parameter is the receiver. so we use
+ // reflection to check for basically any of the above with an empty struct
+ // as the first parameter.
+
+ t := reflect.TypeOf(fn)
+ if t.Kind() != reflect.Func {
+ return invalidType, err
+ }
+
+ if t.NumOut() > 1 {
+ return invalidType, err
+ }
+ if t.NumOut() == 1 && t.Out(0) == reflect.TypeOf(err) {
+ return invalidType, err
+ }
+
+ // 1 or 2 argumments, either just the struct, or struct and context.
+ if t.NumIn() == 0 || t.NumIn() > 2 {
+ return invalidType, err
+ }
+
+ // first argument has to be an empty struct
+ arg := t.In(0)
+ if arg.Kind() != reflect.Struct {
+ return invalidType, err
+ }
+ if arg.NumField() != 0 {
+ return invalidType, err
+ }
+ if t.NumIn() == 1 {
+ if t.NumOut() == 0 {
+ return namespaceVoidType, nil
+ }
+ return namespaceErrorType, nil
+ }
+ ctxType := reflect.TypeOf(context.Background())
+ if t.In(1) == ctxType {
+ return invalidType, err
+ }
+
+ if t.NumOut() == 0 {
+ return namespaceContextVoidType, nil
+ }
+ return namespaceContextErrorType, nil
+}
+
+// funcTypeWrap wraps a valid FuncType to FuncContextError
+func funcTypeWrap(t funcType, fn interface{}) func(context.Context) error {
+ switch f := fn.(type) {
+ case func():
+ return func(context.Context) error {
+ f()
+ return nil
+ }
+ case func() error:
+ return func(context.Context) error {
+ return f()
+ }
+ case func(context.Context):
+ return func(ctx context.Context) error {
+ f(ctx)
+ return nil
+ }
+ case func(context.Context) error:
+ return f
+ }
+ args := []reflect.Value{reflect.ValueOf(struct{}{})}
+ switch t {
+ case namespaceVoidType:
+ return func(context.Context) error {
+ v := reflect.ValueOf(fn)
+ v.Call(args)
+ return nil
+ }
+ case namespaceErrorType:
+ return func(context.Context) error {
+ v := reflect.ValueOf(fn)
+ ret := v.Call(args)
+ val := ret[0].Interface()
+ if val == nil {
+ return nil
+ }
+ return val.(error)
+ }
+ case namespaceContextVoidType:
+ return func(ctx context.Context) error {
+ v := reflect.ValueOf(fn)
+ v.Call(append(args, reflect.ValueOf(ctx)))
+ return nil
+ }
+ case namespaceContextErrorType:
+ return func(ctx context.Context) error {
+ v := reflect.ValueOf(fn)
+ ret := v.Call(append(args, reflect.ValueOf(ctx)))
+ val := ret[0].Interface()
+ if val == nil {
+ return nil
+ }
+ return val.(error)
+ }
+ default:
+ panic(fmt.Errorf("Don't know how to deal with dep of type %T", fn))
+ }
+}
diff --git a/vendor/github.com/magefile/mage/mg/errors.go b/vendor/github.com/magefile/mage/mg/errors.go
new file mode 100644
index 000000000..2dd780fe3
--- /dev/null
+++ b/vendor/github.com/magefile/mage/mg/errors.go
@@ -0,0 +1,51 @@
+package mg
+
+import (
+ "errors"
+ "fmt"
+)
+
+type fatalErr struct {
+ code int
+ error
+}
+
+func (f fatalErr) ExitStatus() int {
+ return f.code
+}
+
+type exitStatus interface {
+ ExitStatus() int
+}
+
+// Fatal returns an error that will cause mage to print out the
+// given args and exit with the given exit code.
+func Fatal(code int, args ...interface{}) error {
+ return fatalErr{
+ code: code,
+ error: errors.New(fmt.Sprint(args...)),
+ }
+}
+
+// Fatalf returns an error that will cause mage to print out the
+// given message and exit with the given exit code.
+func Fatalf(code int, format string, args ...interface{}) error {
+ return fatalErr{
+ code: code,
+ error: fmt.Errorf(format, args...),
+ }
+}
+
+// ExitStatus queries the error for an exit status. If the error is nil, it
+// returns 0. If the error does not implement ExitStatus() int, it returns 1.
+// Otherwise it retiurns the value from ExitStatus().
+func ExitStatus(err error) int {
+ if err == nil {
+ return 0
+ }
+ exit, ok := err.(exitStatus)
+ if !ok {
+ return 1
+ }
+ return exit.ExitStatus()
+}
diff --git a/vendor/github.com/magefile/mage/mg/runtime.go b/vendor/github.com/magefile/mage/mg/runtime.go
new file mode 100644
index 000000000..9a8de12ce
--- /dev/null
+++ b/vendor/github.com/magefile/mage/mg/runtime.go
@@ -0,0 +1,136 @@
+package mg
+
+import (
+ "os"
+ "path/filepath"
+ "runtime"
+ "strconv"
+)
+
+// CacheEnv is the environment variable that users may set to change the
+// location where mage stores its compiled binaries.
+const CacheEnv = "MAGEFILE_CACHE"
+
+// VerboseEnv is the environment variable that indicates the user requested
+// verbose mode when running a magefile.
+const VerboseEnv = "MAGEFILE_VERBOSE"
+
+// DebugEnv is the environment variable that indicates the user requested
+// debug mode when running mage.
+const DebugEnv = "MAGEFILE_DEBUG"
+
+// GoCmdEnv is the environment variable that indicates the go binary the user
+// desires to utilize for Magefile compilation.
+const GoCmdEnv = "MAGEFILE_GOCMD"
+
+// IgnoreDefaultEnv is the environment variable that indicates the user requested
+// to ignore the default target specified in the magefile.
+const IgnoreDefaultEnv = "MAGEFILE_IGNOREDEFAULT"
+
+// HashFastEnv is the environment variable that indicates the user requested to
+// use a quick hash of magefiles to determine whether or not the magefile binary
+// needs to be rebuilt. This results in faster runtimes, but means that mage
+// will fail to rebuild if a dependency has changed. To force a rebuild, run
+// mage with the -f flag.
+const HashFastEnv = "MAGEFILE_HASHFAST"
+
+// EnableColorEnv is the environment variable that indicates the user is using
+// a terminal which supports a color output. The default is false for backwards
+// compatibility. When the value is true and the detected terminal does support colors
+// then the list of mage targets will be displayed in ANSI color. When the value
+// is true but the detected terminal does not support colors, then the list of
+// mage targets will be displayed in the default colors (e.g. black and white).
+const EnableColorEnv = "MAGEFILE_ENABLE_COLOR"
+
+// TargetColorEnv is the environment variable that indicates which ANSI color
+// should be used to colorize mage targets. This is only applicable when
+// the MAGEFILE_ENABLE_COLOR environment variable is true.
+// The supported ANSI color names are any of these:
+// - Black
+// - Red
+// - Green
+// - Yellow
+// - Blue
+// - Magenta
+// - Cyan
+// - White
+// - BrightBlack
+// - BrightRed
+// - BrightGreen
+// - BrightYellow
+// - BrightBlue
+// - BrightMagenta
+// - BrightCyan
+// - BrightWhite
+const TargetColorEnv = "MAGEFILE_TARGET_COLOR"
+
+// Verbose reports whether a magefile was run with the verbose flag.
+func Verbose() bool {
+ b, _ := strconv.ParseBool(os.Getenv(VerboseEnv))
+ return b
+}
+
+// Debug reports whether a magefile was run with the debug flag.
+func Debug() bool {
+ b, _ := strconv.ParseBool(os.Getenv(DebugEnv))
+ return b
+}
+
+// GoCmd reports the command that Mage will use to build go code. By default mage runs
+// the "go" binary in the PATH.
+func GoCmd() string {
+ if cmd := os.Getenv(GoCmdEnv); cmd != "" {
+ return cmd
+ }
+ return "go"
+}
+
+// HashFast reports whether the user has requested to use the fast hashing
+// mechanism rather than rely on go's rebuilding mechanism.
+func HashFast() bool {
+ b, _ := strconv.ParseBool(os.Getenv(HashFastEnv))
+ return b
+}
+
+// IgnoreDefault reports whether the user has requested to ignore the default target
+// in the magefile.
+func IgnoreDefault() bool {
+ b, _ := strconv.ParseBool(os.Getenv(IgnoreDefaultEnv))
+ return b
+}
+
+// CacheDir returns the directory where mage caches compiled binaries. It
+// defaults to $HOME/.magefile, but may be overridden by the MAGEFILE_CACHE
+// environment variable.
+func CacheDir() string {
+ d := os.Getenv(CacheEnv)
+ if d != "" {
+ return d
+ }
+ switch runtime.GOOS {
+ case "windows":
+ return filepath.Join(os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"), "magefile")
+ default:
+ return filepath.Join(os.Getenv("HOME"), ".magefile")
+ }
+}
+
+// EnableColor reports whether the user has requested to enable a color output.
+func EnableColor() bool {
+ b, _ := strconv.ParseBool(os.Getenv(EnableColorEnv))
+ return b
+}
+
+// TargetColor returns the configured ANSI color name a color output.
+func TargetColor() string {
+ s, exists := os.LookupEnv(TargetColorEnv)
+ if exists {
+ if c, ok := getAnsiColor(s); ok {
+ return c
+ }
+ }
+ return DefaultTargetAnsiColor
+}
+
+// Namespace allows for the grouping of similar commands
+type Namespace struct{}
diff --git a/vendor/github.com/magefile/mage/sh/cmd.go b/vendor/github.com/magefile/mage/sh/cmd.go
new file mode 100644
index 000000000..06af62de2
--- /dev/null
+++ b/vendor/github.com/magefile/mage/sh/cmd.go
@@ -0,0 +1,177 @@
+package sh
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+
+ "github.com/magefile/mage/mg"
+)
+
+// RunCmd returns a function that will call Run with the given command. This is
+// useful for creating command aliases to make your scripts easier to read, like
+// this:
+//
+// // in a helper file somewhere
+// var g0 = sh.RunCmd("go") // go is a keyword :(
+//
+// // somewhere in your main code
+// if err := g0("install", "github.com/gohugo/hugo"); err != nil {
+// return err
+// }
+//
+// Args passed to command get baked in as args to the command when you run it.
+// Any args passed in when you run the returned function will be appended to the
+// original args. For example, this is equivalent to the above:
+//
+// var goInstall = sh.RunCmd("go", "install") goInstall("github.com/gohugo/hugo")
+//
+// RunCmd uses Exec underneath, so see those docs for more details.
+func RunCmd(cmd string, args ...string) func(args ...string) error {
+ return func(args2 ...string) error {
+ return Run(cmd, append(args, args2...)...)
+ }
+}
+
+// OutCmd is like RunCmd except the command returns the output of the
+// command.
+func OutCmd(cmd string, args ...string) func(args ...string) (string, error) {
+ return func(args2 ...string) (string, error) {
+ return Output(cmd, append(args, args2...)...)
+ }
+}
+
+// Run is like RunWith, but doesn't specify any environment variables.
+func Run(cmd string, args ...string) error {
+ return RunWith(nil, cmd, args...)
+}
+
+// RunV is like Run, but always sends the command's stdout to os.Stdout.
+func RunV(cmd string, args ...string) error {
+ _, err := Exec(nil, os.Stdout, os.Stderr, cmd, args...)
+ return err
+}
+
+// RunWith runs the given command, directing stderr to this program's stderr and
+// printing stdout to stdout if mage was run with -v. It adds adds env to the
+// environment variables for the command being run. Environment variables should
+// be in the format name=value.
+func RunWith(env map[string]string, cmd string, args ...string) error {
+ var output io.Writer
+ if mg.Verbose() {
+ output = os.Stdout
+ }
+ _, err := Exec(env, output, os.Stderr, cmd, args...)
+ return err
+}
+
+// RunWithV is like RunWith, but always sends the command's stdout to os.Stdout.
+func RunWithV(env map[string]string, cmd string, args ...string) error {
+ _, err := Exec(env, os.Stdout, os.Stderr, cmd, args...)
+ return err
+}
+
+// Output runs the command and returns the text from stdout.
+func Output(cmd string, args ...string) (string, error) {
+ buf := &bytes.Buffer{}
+ _, err := Exec(nil, buf, os.Stderr, cmd, args...)
+ return strings.TrimSuffix(buf.String(), "\n"), err
+}
+
+// OutputWith is like RunWith, but returns what is written to stdout.
+func OutputWith(env map[string]string, cmd string, args ...string) (string, error) {
+ buf := &bytes.Buffer{}
+ _, err := Exec(env, buf, os.Stderr, cmd, args...)
+ return strings.TrimSuffix(buf.String(), "\n"), err
+}
+
+// Exec executes the command, piping its stderr to mage's stderr and
+// piping its stdout to the given writer. If the command fails, it will return
+// an error that, if returned from a target or mg.Deps call, will cause mage to
+// exit with the same code as the command failed with. Env is a list of
+// environment variables to set when running the command, these override the
+// current environment variables set (which are also passed to the command). cmd
+// and args may include references to environment variables in $FOO format, in
+// which case these will be expanded before the command is run.
+//
+// Ran reports if the command ran (rather than was not found or not executable).
+// Code reports the exit code the command returned if it ran. If err == nil, ran
+// is always true and code is always 0.
+func Exec(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, err error) {
+ expand := func(s string) string {
+ s2, ok := env[s]
+ if ok {
+ return s2
+ }
+ return os.Getenv(s)
+ }
+ cmd = os.Expand(cmd, expand)
+ for i := range args {
+ args[i] = os.Expand(args[i], expand)
+ }
+ ran, code, err := run(env, stdout, stderr, cmd, args...)
+ if err == nil {
+ return true, nil
+ }
+ if ran {
+ return ran, mg.Fatalf(code, `running "%s %s" failed with exit code %d`, cmd, strings.Join(args, " "), code)
+ }
+ return ran, fmt.Errorf(`failed to run "%s %s: %v"`, cmd, strings.Join(args, " "), err)
+}
+
+func run(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, code int, err error) {
+ c := exec.Command(cmd, args...)
+ c.Env = os.Environ()
+ for k, v := range env {
+ c.Env = append(c.Env, k+"="+v)
+ }
+ c.Stderr = stderr
+ c.Stdout = stdout
+ c.Stdin = os.Stdin
+ log.Println("exec:", cmd, strings.Join(args, " "))
+ err = c.Run()
+ return CmdRan(err), ExitStatus(err), err
+}
+
+// CmdRan examines the error to determine if it was generated as a result of a
+// command running via os/exec.Command. If the error is nil, or the command ran
+// (even if it exited with a non-zero exit code), CmdRan reports true. If the
+// error is an unrecognized type, or it is an error from exec.Command that says
+// the command failed to run (usually due to the command not existing or not
+// being executable), it reports false.
+func CmdRan(err error) bool {
+ if err == nil {
+ return true
+ }
+ ee, ok := err.(*exec.ExitError)
+ if ok {
+ return ee.Exited()
+ }
+ return false
+}
+
+type exitStatus interface {
+ ExitStatus() int
+}
+
+// ExitStatus returns the exit status of the error if it is an exec.ExitError
+// or if it implements ExitStatus() int.
+// 0 if it is nil or 1 if it is a different error.
+func ExitStatus(err error) int {
+ if err == nil {
+ return 0
+ }
+ if e, ok := err.(exitStatus); ok {
+ return e.ExitStatus()
+ }
+ if e, ok := err.(*exec.ExitError); ok {
+ if ex, ok := e.Sys().(exitStatus); ok {
+ return ex.ExitStatus()
+ }
+ }
+ return 1
+}
diff --git a/vendor/github.com/magefile/mage/sh/helpers.go b/vendor/github.com/magefile/mage/sh/helpers.go
new file mode 100644
index 000000000..f5d20a271
--- /dev/null
+++ b/vendor/github.com/magefile/mage/sh/helpers.go
@@ -0,0 +1,40 @@
+package sh
+
+import (
+ "fmt"
+ "io"
+ "os"
+)
+
+// Rm removes the given file or directory even if non-empty. It will not return
+// an error if the target doesn't exist, only if the target cannot be removed.
+func Rm(path string) error {
+ err := os.RemoveAll(path)
+ if err == nil || os.IsNotExist(err) {
+ return nil
+ }
+ return fmt.Errorf(`failed to remove %s: %v`, path, err)
+}
+
+// Copy robustly copies the source file to the destination, overwriting the destination if necessary.
+func Copy(dst string, src string) error {
+ from, err := os.Open(src)
+ if err != nil {
+ return fmt.Errorf(`can't copy %s: %v`, src, err)
+ }
+ defer from.Close()
+ finfo, err := from.Stat()
+ if err != nil {
+ return fmt.Errorf(`can't stat %s: %v`, src, err)
+ }
+ to, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, finfo.Mode())
+ if err != nil {
+ return fmt.Errorf(`can't copy to %s: %v`, dst, err)
+ }
+ defer to.Close()
+ _, err = io.Copy(to, from)
+ if err != nil {
+ return fmt.Errorf(`error copying %s to %s: %v`, src, dst, err)
+ }
+ return nil
+}
diff --git a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go
index b9f2d1802..9fb801162 100644
--- a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go
+++ b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/tcp/tcp.go
@@ -5,6 +5,7 @@ import (
"io"
"net"
"os"
+ "strconv"
"sync"
"github.com/rootless-containers/rootlesskit/pkg/port"
@@ -12,7 +13,7 @@ import (
)
func Run(socketPath string, spec port.Spec, stopCh <-chan struct{}, logWriter io.Writer) error {
- ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", spec.ParentIP, spec.ParentPort))
+ ln, err := net.Listen("tcp", net.JoinHostPort(spec.ParentIP, strconv.Itoa(spec.ParentPort)))
if err != nil {
fmt.Fprintf(logWriter, "listen: %v\n", err)
return err
diff --git a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
index d8f646b5d..fbff2b081 100644
--- a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
+++ b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/builtin/parent/udp/udp.go
@@ -1,10 +1,10 @@
package udp
import (
- "fmt"
"io"
"net"
"os"
+ "strconv"
"github.com/pkg/errors"
@@ -14,7 +14,7 @@ import (
)
func Run(socketPath string, spec port.Spec, stopCh <-chan struct{}, logWriter io.Writer) error {
- addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", spec.ParentIP, spec.ParentPort))
+ addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(spec.ParentIP, strconv.Itoa(spec.ParentPort)))
if err != nil {
return err
}
diff --git a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
index 1c531cac8..a885a76ca 100644
--- a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
+++ b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
@@ -4,76 +4,135 @@ import (
"net"
"strconv"
"strings"
+ "text/scanner"
"github.com/pkg/errors"
"github.com/rootless-containers/rootlesskit/pkg/port"
)
-// ParsePortSpec parses a Docker-like representation of PortSpec.
+// ParsePortSpec parses a Docker-like representation of PortSpec, but with
+// support for both "parent IP" and "child IP" (optional);
// e.g. "127.0.0.1:8080:80/tcp", or "127.0.0.1:8080:10.0.2.100:80/tcp"
-func ParsePortSpec(s string) (*port.Spec, error) {
- splitBySlash := strings.SplitN(s, "/", 2)
- if len(splitBySlash) != 2 {
- return nil, errors.Errorf("unexpected PortSpec string: %q", s)
+//
+// Format is as follows:
+//
+// <parent IP>:<parent port>[:<child IP>]:<child port>/<proto>
+//
+// Note that (child IP being optional) the format can either contain 5 or 4
+// components. When using IPv6 IP addresses, addresses must use square brackets
+// to prevent the colons being mistaken for delimiters. For example:
+//
+// [::1]:8080:[::2]:80/udp
+func ParsePortSpec(portSpec string) (*port.Spec, error) {
+ const (
+ parentIP = iota
+ parentPort = iota
+ childIP = iota
+ childPort = iota
+ proto = iota
+ )
+
+ var (
+ s scanner.Scanner
+ err error
+ parts = make([]string, 5)
+ index = parentIP
+ delimiter = ':'
+ )
+
+ // First get the "proto" and "parent-port" at the end. These parts are
+ // required, whereas "ParentIP" is optional. Removing them first makes
+ // it easier to parse the remaining parts, as otherwise the third part
+ // could be _either_ an IP-address _or_ a Port.
+
+ // Get the proto
+ protoPos := strings.LastIndex(portSpec, "/")
+ if protoPos < 0 {
+ return nil, errors.Errorf("missing proto in PortSpec string: %q", portSpec)
}
- proto := splitBySlash[1]
- switch proto {
- case "tcp", "udp", "sctp":
- default:
- return nil, errors.Errorf("unexpected Proto in PortSpec string: %q", s)
+ parts[proto] = portSpec[protoPos+1:]
+ err = validateProto(parts[proto])
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid PortSpec string: %q", portSpec)
}
- splitByColon := strings.SplitN(splitBySlash[0], ":", 4)
- switch len(splitByColon) {
- case 3, 4:
- default:
- return nil, errors.Errorf("unexpected PortSpec string: %q", s)
+ // Get the parent port
+ portPos := strings.LastIndex(portSpec, ":")
+ if portPos < 0 {
+ return nil, errors.Errorf("unexpected PortSpec string: %q", portSpec)
}
+ parts[childPort] = portSpec[portPos+1 : protoPos]
+
+ // Scan the remainder "<IP-address>:<port>[:<IP-address>]"
+ s.Init(strings.NewReader(portSpec[:portPos]))
+
+ for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
+ if index > childPort {
+ return nil, errors.Errorf("unexpected PortSpec string: %q", portSpec)
+ }
- parentIP := splitByColon[0]
- if net.IP(parentIP) == nil {
- return nil, errors.Errorf("unexpected ParentIP in PortSpec string: %q", s)
+ switch tok {
+ case '[':
+ // Start of IPv6 IP-address; value ends at closing bracket (])
+ delimiter = ']'
+ continue
+ case delimiter:
+ if delimiter == ']' {
+ // End of IPv6 IP-address
+ delimiter = ':'
+ // Skip the next token, which should be a colon delimiter (:)
+ tok = s.Scan()
+ }
+ index++
+ continue
+ default:
+ parts[index] += s.TokenText()
+ }
}
- parentPort, err := strconv.Atoi(splitByColon[1])
- if err != nil {
- return nil, errors.Wrapf(err, "unexpected ParentPort in PortSpec string: %q", s)
+ if parts[parentIP] != "" && net.ParseIP(parts[parentIP]) == nil {
+ return nil, errors.Errorf("unexpected ParentIP in PortSpec string: %q", portSpec)
+ }
+ if parts[childIP] != "" && net.ParseIP(parts[childIP]) == nil {
+ return nil, errors.Errorf("unexpected ParentIP in PortSpec string: %q", portSpec)
}
- var childIP string
- if len(splitByColon) == 4 {
- childIP = splitByColon[2]
- if net.IP(childIP) == nil {
- return nil, errors.Errorf("unexpected ChildIP in PortSpec string: %q", s)
- }
+ ps := &port.Spec{
+ Proto: parts[proto],
+ ParentIP: parts[parentIP],
+ ChildIP: parts[childIP],
}
- childPort, err := strconv.Atoi(splitByColon[len(splitByColon)-1])
+ ps.ParentPort, err = strconv.Atoi(parts[parentPort])
if err != nil {
- return nil, errors.Wrapf(err, "unexpected ChildPort in PortSpec string: %q", s)
+ return nil, errors.Wrapf(err, "unexpected ChildPort in PortSpec string: %q", portSpec)
}
- return &port.Spec{
- Proto: proto,
- ParentIP: parentIP,
- ParentPort: parentPort,
- ChildIP: childIP,
- ChildPort: childPort,
- }, nil
+ ps.ChildPort, err = strconv.Atoi(parts[childPort])
+ if err != nil {
+ return nil, errors.Wrapf(err, "unexpected ParentPort in PortSpec string: %q", portSpec)
+ }
+
+ return ps, nil
}
// ValidatePortSpec validates *port.Spec.
// existingPorts can be optionally passed for detecting conflicts.
func ValidatePortSpec(spec port.Spec, existingPorts map[int]*port.Status) error {
- if spec.Proto != "tcp" && spec.Proto != "udp" {
- return errors.Errorf("unknown proto: %q", spec.Proto)
+ if err := validateProto(spec.Proto); err != nil {
+ return err
}
if spec.ParentIP != "" {
if net.ParseIP(spec.ParentIP) == nil {
return errors.Errorf("invalid ParentIP: %q", spec.ParentIP)
}
}
+ if spec.ChildIP != "" {
+ if net.ParseIP(spec.ChildIP) == nil {
+ return errors.Errorf("invalid ChildIP: %q", spec.ChildIP)
+ }
+ }
if spec.ParentPort <= 0 || spec.ParentPort > 65535 {
return errors.Errorf("invalid ParentPort: %q", spec.ParentPort)
}
@@ -90,3 +149,12 @@ func ValidatePortSpec(spec port.Spec, existingPorts map[int]*port.Status) error
}
return nil
}
+
+func validateProto(proto string) error {
+ switch proto {
+ case "tcp", "udp", "sctp":
+ return nil
+ default:
+ return errors.Errorf("unknown proto: %q", proto)
+ }
+}
diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml
index 5e20aa414..e6ee8b3ab 100644
--- a/vendor/github.com/sirupsen/logrus/.travis.yml
+++ b/vendor/github.com/sirupsen/logrus/.travis.yml
@@ -4,14 +4,11 @@ git:
depth: 1
env:
- GO111MODULE=on
-go: [1.13.x, 1.14.x]
-os: [linux, osx]
+go: 1.15.x
+os: linux
install:
- ./travis/install.sh
script:
- - ./travis/cross_build.sh
- - ./travis/lint.sh
- - export GOMAXPROCS=4
- - export GORACE=halt_on_error=1
- - go test -race -v ./...
- - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi
+ - go run mage.go -v crossBuild
+ - go run mage.go lint
+ - go run mage.go test
diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
index 584026d67..f68fb86bd 100644
--- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md
+++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
@@ -1,3 +1,23 @@
+# 1.7.1
+Code quality:
+ * use go 1.15 in travis
+ * use magefile as task runner
+
+Fixes:
+ * small fixes about new go 1.13 error formatting system
+ * Fix for long time race condiction with mutating data hooks
+
+Features:
+ * build support for zos
+
+# 1.7.0
+Fixes:
+ * the dependency toward a windows terminal library has been removed
+
+Features:
+ * a new buffer pool management API has been added
+ * a set of `<LogLevel>Fn()` functions have been added
+
# 1.6.0
Fixes:
* end of line cleanup
diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md
index 5796706db..5152b6aa4 100644
--- a/vendor/github.com/sirupsen/logrus/README.md
+++ b/vendor/github.com/sirupsen/logrus/README.md
@@ -402,7 +402,7 @@ func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
// source of the official loggers.
serialized, err := json.Marshal(entry.Data)
if err != nil {
- return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
+ return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err)
}
return append(serialized, '\n'), nil
}
diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go
index 5a5cbfe7c..e02e057e1 100644
--- a/vendor/github.com/sirupsen/logrus/entry.go
+++ b/vendor/github.com/sirupsen/logrus/entry.go
@@ -78,8 +78,20 @@ func NewEntry(logger *Logger) *Entry {
}
}
+func (entry *Entry) Dup() *Entry {
+ data := make(Fields, len(entry.Data))
+ for k, v := range entry.Data {
+ data[k] = v
+ }
+ return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err}
+}
+
// Returns the bytes representation of this entry from the formatter.
func (entry *Entry) Bytes() ([]byte, error) {
+ return entry.bytes_nolock()
+}
+
+func (entry *Entry) bytes_nolock() ([]byte, error) {
return entry.Logger.Formatter.Format(entry)
}
@@ -123,11 +135,9 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
for k, v := range fields {
isErrField := false
if t := reflect.TypeOf(v); t != nil {
- switch t.Kind() {
- case reflect.Func:
+ switch {
+ case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func:
isErrField = true
- case reflect.Ptr:
- isErrField = t.Elem().Kind() == reflect.Func
}
}
if isErrField {
@@ -214,51 +224,49 @@ func (entry Entry) HasCaller() (has bool) {
// This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines
-func (entry Entry) log(level Level, msg string) {
+func (entry *Entry) log(level Level, msg string) {
var buffer *bytes.Buffer
- // Default to now, but allow users to override if they want.
- //
- // We don't have to worry about polluting future calls to Entry#log()
- // with this assignment because this function is declared with a
- // non-pointer receiver.
- if entry.Time.IsZero() {
- entry.Time = time.Now()
+ newEntry := entry.Dup()
+
+ if newEntry.Time.IsZero() {
+ newEntry.Time = time.Now()
}
- entry.Level = level
- entry.Message = msg
- entry.Logger.mu.Lock()
- if entry.Logger.ReportCaller {
- entry.Caller = getCaller()
+ newEntry.Level = level
+ newEntry.Message = msg
+
+ newEntry.Logger.mu.Lock()
+ reportCaller := newEntry.Logger.ReportCaller
+ newEntry.Logger.mu.Unlock()
+
+ if reportCaller {
+ newEntry.Caller = getCaller()
}
- entry.Logger.mu.Unlock()
- entry.fireHooks()
+ newEntry.fireHooks()
buffer = getBuffer()
defer func() {
- entry.Buffer = nil
+ newEntry.Buffer = nil
putBuffer(buffer)
}()
buffer.Reset()
- entry.Buffer = buffer
+ newEntry.Buffer = buffer
- entry.write()
+ newEntry.write()
- entry.Buffer = nil
+ newEntry.Buffer = nil
// To avoid Entry#log() returning a value that only would make sense for
// panic() to use in Entry#Panic(), we avoid the allocation by checking
// directly here.
if level <= PanicLevel {
- panic(&entry)
+ panic(newEntry)
}
}
func (entry *Entry) fireHooks() {
- entry.Logger.mu.Lock()
- defer entry.Logger.mu.Unlock()
err := entry.Logger.Hooks.Fire(entry.Level, entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
@@ -266,16 +274,18 @@ func (entry *Entry) fireHooks() {
}
func (entry *Entry) write() {
- entry.Logger.mu.Lock()
- defer entry.Logger.mu.Unlock()
serialized, err := entry.Logger.Formatter.Format(entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
return
}
- if _, err = entry.Logger.Out.Write(serialized); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
- }
+ func() {
+ entry.Logger.mu.Lock()
+ defer entry.Logger.mu.Unlock()
+ if _, err := entry.Logger.Out.Write(serialized); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
+ }
+ }()
}
func (entry *Entry) Log(level Level, args ...interface{}) {
@@ -319,7 +329,6 @@ func (entry *Entry) Fatal(args ...interface{}) {
func (entry *Entry) Panic(args ...interface{}) {
entry.Log(PanicLevel, args...)
- panic(fmt.Sprint(args...))
}
// Entry Printf family functions
diff --git a/vendor/github.com/sirupsen/logrus/go.mod b/vendor/github.com/sirupsen/logrus/go.mod
index b3919d5ea..37004ff34 100644
--- a/vendor/github.com/sirupsen/logrus/go.mod
+++ b/vendor/github.com/sirupsen/logrus/go.mod
@@ -2,6 +2,7 @@ module github.com/sirupsen/logrus
require (
github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/magefile/mage v1.10.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
diff --git a/vendor/github.com/sirupsen/logrus/go.sum b/vendor/github.com/sirupsen/logrus/go.sum
index 1edc143be..bce26a188 100644
--- a/vendor/github.com/sirupsen/logrus/go.sum
+++ b/vendor/github.com/sirupsen/logrus/go.sum
@@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
+github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
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/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go
index ba7f23711..afaf0fc8a 100644
--- a/vendor/github.com/sirupsen/logrus/json_formatter.go
+++ b/vendor/github.com/sirupsen/logrus/json_formatter.go
@@ -118,7 +118,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
encoder.SetIndent("", " ")
}
if err := encoder.Encode(data); err != nil {
- return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err)
+ return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err)
}
return b.Bytes(), nil
diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go
index dbf627c97..337704457 100644
--- a/vendor/github.com/sirupsen/logrus/logger.go
+++ b/vendor/github.com/sirupsen/logrus/logger.go
@@ -12,7 +12,7 @@ import (
// LogFunction For big messages, it can be more efficient to pass a function
// and only call it if the log level is actually enables rather than
// generating the log message and then checking if the level is enabled
-type LogFunction func()[]interface{}
+type LogFunction func() []interface{}
type Logger struct {
// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
diff --git a/vendor/github.com/sirupsen/logrus/magefile.go b/vendor/github.com/sirupsen/logrus/magefile.go
new file mode 100644
index 000000000..9aa603939
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/magefile.go
@@ -0,0 +1,77 @@
+// +build mage
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "path"
+
+ "github.com/magefile/mage/mg"
+ "github.com/magefile/mage/sh"
+)
+
+// getBuildMatrix returns the build matrix from the current version of the go compiler
+func getBuildMatrix() (map[string][]string, error) {
+ jsonData, err := sh.Output("go", "tool", "dist", "list", "-json")
+ if err != nil {
+ return nil, err
+ }
+ var data []struct {
+ Goos string
+ Goarch string
+ }
+ if err := json.Unmarshal([]byte(jsonData), &data); err != nil {
+ return nil, err
+ }
+
+ matrix := map[string][]string{}
+ for _, v := range data {
+ if val, ok := matrix[v.Goos]; ok {
+ matrix[v.Goos] = append(val, v.Goarch)
+ } else {
+ matrix[v.Goos] = []string{v.Goarch}
+ }
+ }
+
+ return matrix, nil
+}
+
+func CrossBuild() error {
+ matrix, err := getBuildMatrix()
+ if err != nil {
+ return err
+ }
+
+ for os, arches := range matrix {
+ for _, arch := range arches {
+ env := map[string]string{
+ "GOOS": os,
+ "GOARCH": arch,
+ }
+ if mg.Verbose() {
+ fmt.Printf("Building for GOOS=%s GOARCH=%s\n", os, arch)
+ }
+ if err := sh.RunWith(env, "go", "build", "./..."); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func Lint() error {
+ gopath := os.Getenv("GOPATH")
+ if gopath == "" {
+ return fmt.Errorf("cannot retrieve GOPATH")
+ }
+
+ return sh.Run(path.Join(gopath, "bin", "golangci-lint"), "run", "./...")
+}
+
+// Run the test suite
+func Test() error {
+ return sh.RunWith(map[string]string{"GORACE": "halt_on_error=1"},
+ "go", "test", "-race", "-v", "./...")
+}
diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
index cc4fe6e31..04748b851 100644
--- a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go
@@ -1,4 +1,4 @@
-// +build linux aix
+// +build linux aix zos
// +build !js
package logrus
diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go
index 3c28b54ca..8fc698ad6 100644
--- a/vendor/github.com/sirupsen/logrus/text_formatter.go
+++ b/vendor/github.com/sirupsen/logrus/text_formatter.go
@@ -235,6 +235,8 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
levelColor = yellow
case ErrorLevel, FatalLevel, PanicLevel:
levelColor = red
+ case InfoLevel:
+ levelColor = blue
default:
levelColor = blue
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 7240ac6b6..4ec52f46c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -369,6 +369,9 @@ github.com/klauspost/compress/zstd/internal/xxhash
github.com/klauspost/pgzip
# github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a
github.com/lunixbochs/vtclean
+# github.com/magefile/mage v1.10.0
+github.com/magefile/mage/mg
+github.com/magefile/mage/sh
# github.com/manifoldco/promptui v0.8.0
github.com/manifoldco/promptui
github.com/manifoldco/promptui/list
@@ -515,7 +518,7 @@ github.com/prometheus/common/model
# github.com/prometheus/procfs v0.0.3
github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs
-# github.com/rootless-containers/rootlesskit v0.13.0
+# github.com/rootless-containers/rootlesskit v0.13.1
github.com/rootless-containers/rootlesskit/pkg/msgutil
github.com/rootless-containers/rootlesskit/pkg/port
github.com/rootless-containers/rootlesskit/pkg/port/builtin
@@ -531,7 +534,7 @@ github.com/rootless-containers/rootlesskit/pkg/port/portutil
github.com/safchain/ethtool
# github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf
github.com/seccomp/libseccomp-golang
-# github.com/sirupsen/logrus v1.7.0
+# github.com/sirupsen/logrus v1.7.1
github.com/sirupsen/logrus
github.com/sirupsen/logrus/hooks/syslog
# github.com/spf13/cobra v1.1.3