Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add cni networking support #1073

Merged
merged 6 commits into from
Jul 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/entitlements"
"github.com/moby/buildkit/util/testutil"
"github.com/moby/buildkit/util/testutil/echoserver"
"github.com/moby/buildkit/util/testutil/httpserver"
"github.com/moby/buildkit/util/testutil/integration"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -97,6 +98,7 @@ func TestClientIntegration(t *testing.T) {
testPushByDigest,
testBasicInlineCacheImportExport,
testExportBusyboxLocal,
testBridgeNetworking,
}, mirrors)

integration.Run(t, []integration.Test{
Expand All @@ -109,12 +111,75 @@ func TestClientIntegration(t *testing.T) {
"insecure": securityInsecure,
}),
)

integration.Run(t, []integration.Test{
testHostNetworking,
},
mirrors,
integration.WithMatrix("netmode", map[string]interface{}{
"default": defaultNetwork,
"host": hostNetwork,
}),
)
}

func newContainerd(cdAddress string) (*containerd.Client, error) {
return containerd.New(cdAddress, containerd.WithTimeout(60*time.Second))
}

func testBridgeNetworking(t *testing.T, sb integration.Sandbox) {
if os.Getenv("BUILDKIT_RUN_NETWORK_INTEGRATION_TESTS") == "" {
t.SkipNow()
}
if sb.Rootless() {
t.SkipNow()
}
c, err := New(context.TODO(), sb.Address())
require.NoError(t, err)
defer c.Close()

s, err := echoserver.NewTestServer("foo")
require.NoError(t, err)
addrParts := strings.Split(s.Addr().String(), ":")

def, err := llb.Image("busybox").Run(llb.Shlexf("sh -c 'nc 127.0.0.1 %s | grep foo'", addrParts[len(addrParts)-1])).Marshal()
require.NoError(t, err)

_, err = c.Solve(context.TODO(), def, SolveOpt{}, nil)
require.Error(t, err)
}
func testHostNetworking(t *testing.T, sb integration.Sandbox) {
if os.Getenv("BUILDKIT_RUN_NETWORK_INTEGRATION_TESTS") == "" {
t.SkipNow()
}
netMode := sb.Value("netmode")
var allowedEntitlements []entitlements.Entitlement
if netMode == hostNetwork {
allowedEntitlements = []entitlements.Entitlement{entitlements.EntitlementNetworkHost}
}
c, err := New(context.TODO(), sb.Address())
require.NoError(t, err)
defer c.Close()

s, err := echoserver.NewTestServer("foo")
require.NoError(t, err)
addrParts := strings.Split(s.Addr().String(), ":")

def, err := llb.Image("busybox").Run(llb.Shlexf("sh -c 'nc 127.0.0.1 %s | grep foo'", addrParts[len(addrParts)-1]), llb.Network(llb.NetModeHost)).Marshal()
require.NoError(t, err)

_, err = c.Solve(context.TODO(), def, SolveOpt{
AllowedEntitlements: allowedEntitlements,
}, nil)
if netMode == hostNetwork {
require.NoError(t, err)
t.Logf("host-noerror")
} else {
require.Error(t, err)
t.Logf("bridge-error")
}
}

// #877
func testExportBusyboxLocal(t *testing.T, sb integration.Sandbox) {
c, err := New(context.TODO(), sb.Address())
Expand Down Expand Up @@ -2452,3 +2517,18 @@ func (*secModeInsecure) UpdateConfigFile(in string) string {

var securitySandbox integration.ConfigUpdater = &secModeSandbox{}
var securityInsecure integration.ConfigUpdater = &secModeInsecure{}

type netModeHost struct{}

func (*netModeHost) UpdateConfigFile(in string) string {
return in + "\n\ninsecure-entitlements = [\"network.host\"]\n"
}

type netModeDefault struct{}

func (*netModeDefault) UpdateConfigFile(in string) string {
return in
}

var hostNetwork integration.ConfigUpdater = &netModeHost{}
var defaultNetwork integration.ConfigUpdater = &netModeDefault{}
8 changes: 8 additions & 0 deletions cmd/buildkitd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ type GCConfig struct {
GCPolicy []GCPolicy `toml:"gcpolicy"`
}

type NetworkConfig struct {
Mode string `toml:"networkMode"`
CNIConfigPath string `toml:"cniConfigPath"`
CNIBinaryPath string `toml:"cniBinaryPath"`
}

type OCIConfig struct {
Enabled *bool `toml:"enabled"`
Labels map[string]string `toml:"labels"`
Expand All @@ -66,6 +72,7 @@ type OCIConfig struct {
Rootless bool `toml:"rootless"`
NoProcessSandbox bool `toml:"noProcessSandbox"`
GCConfig
NetworkConfig
// UserRemapUnsupported is unsupported key for testing. The feature is
// incomplete and the intention is to make it default without config.
UserRemapUnsupported string `toml:"userRemapUnsupported"`
Expand All @@ -78,6 +85,7 @@ type ContainerdConfig struct {
Platforms []string `toml:"platforms"`
Namespace string `toml:"namespace"`
GCConfig
NetworkConfig
}

type GCPolicy struct {
Expand Down
16 changes: 16 additions & 0 deletions cmd/buildkitd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,19 @@ func defaultConf() (config.Config, *toml.MetaData, error) {
return cfg, md, nil
}

func setDefaultNetworkConfig(nc config.NetworkConfig) config.NetworkConfig {
if nc.Mode == "" {
nc.Mode = "auto"
}
if nc.CNIConfigPath == "" {
nc.CNIConfigPath = "/etc/buildkit/cni.json"
}
if nc.CNIBinaryPath == "" {
nc.CNIBinaryPath = "/opt/cni/bin"
}
return nc
}

func setDefaultConfig(cfg *config.Config) {
orig := *cfg

Expand All @@ -368,6 +381,9 @@ func setDefaultConfig(cfg *config.Config) {
cfg.Workers.Containerd.Platforms = binfmt_misc.SupportedPlatforms()
}

cfg.Workers.OCI.NetworkConfig = setDefaultNetworkConfig(cfg.Workers.OCI.NetworkConfig)
cfg.Workers.Containerd.NetworkConfig = setDefaultNetworkConfig(cfg.Workers.Containerd.NetworkConfig)

if system.RunningInUserNS() {
// if buildkitd is being executed as the mapped-root (not only EUID==0 but also $USER==root)
// in a user namespace, we need to enable the rootless mode but
Expand Down
35 changes: 34 additions & 1 deletion cmd/buildkitd/main_containerd_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

ctd "github.com/containerd/containerd"
"github.com/moby/buildkit/cmd/buildkitd/config"
"github.com/moby/buildkit/util/network"
"github.com/moby/buildkit/worker"
"github.com/moby/buildkit/worker/base"
"github.com/moby/buildkit/worker/containerd"
Expand Down Expand Up @@ -69,6 +70,21 @@ func init() {
Value: defaultConf.Workers.Containerd.Namespace,
Hidden: true,
},
cli.StringFlag{
Name: "containerd-worker-net",
Usage: "worker network type (auto, cni or host)",
Value: defaultConf.Workers.Containerd.NetworkConfig.Mode,
},
cli.StringFlag{
Name: "containerd-cni-config-path",
Usage: "path of cni config file",
Value: defaultConf.Workers.Containerd.NetworkConfig.CNIConfigPath,
},
cli.StringFlag{
Name: "containerd-cni-binary-dir",
Usage: "path of cni binary files",
Value: defaultConf.Workers.Containerd.NetworkConfig.CNIBinaryPath,
},
}

if defaultConf.Workers.Containerd.GC == nil || *defaultConf.Workers.Containerd.GC {
Expand Down Expand Up @@ -158,6 +174,16 @@ func applyContainerdFlags(c *cli.Context, cfg *config.Config) error {
cfg.Workers.Containerd.GCKeepStorage = c.GlobalInt64("containerd-worker-gc-keepstorage") * 1e6
}

if c.GlobalIsSet("containerd-worker-net") {
cfg.Workers.Containerd.NetworkConfig.Mode = c.GlobalString("containerd-worker-net")
}
if c.GlobalIsSet("containerd-cni-config-path") {
cfg.Workers.Containerd.NetworkConfig.CNIConfigPath = c.GlobalString("containerd-cni-worker-path")
}
if c.GlobalIsSet("containerd-cni-binary-dir") {
cfg.Workers.Containerd.NetworkConfig.CNIBinaryPath = c.GlobalString("containerd-cni-binary-dir")
}

return nil
}

Expand All @@ -174,7 +200,14 @@ func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([

dns := getDNSConfig(common.config.DNS)

opt, err := containerd.NewWorkerOpt(common.config.Root, cfg.Address, ctd.DefaultSnapshotter, cfg.Namespace, cfg.Labels, dns, ctd.WithTimeout(60*time.Second))
nc := network.Opt{
Root: common.config.Root,
Mode: common.config.Workers.Containerd.NetworkConfig.Mode,
CNIConfigPath: common.config.Workers.Containerd.CNIConfigPath,
CNIBinaryDir: common.config.Workers.Containerd.CNIBinaryPath,
}

opt, err := containerd.NewWorkerOpt(common.config.Root, cfg.Address, ctd.DefaultSnapshotter, cfg.Namespace, cfg.Labels, dns, nc, ctd.WithTimeout(60*time.Second))
if err != nil {
return nil, err
}
Expand Down
37 changes: 36 additions & 1 deletion cmd/buildkitd/main_oci_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/containerd/containerd/snapshots/overlay"
"github.com/moby/buildkit/cmd/buildkitd/config"
"github.com/moby/buildkit/executor/oci"
"github.com/moby/buildkit/util/network"
"github.com/moby/buildkit/worker"
"github.com/moby/buildkit/worker/base"
"github.com/moby/buildkit/worker/runc"
Expand Down Expand Up @@ -53,6 +54,21 @@ func init() {
Name: "oci-worker-platform",
Usage: "override supported platforms for worker",
},
cli.StringFlag{
Name: "oci-worker-net",
Usage: "worker network type (auto, cni or host)",
Value: defaultConf.Workers.OCI.NetworkConfig.Mode,
},
cli.StringFlag{
Name: "oci-cni-config-path",
Usage: "path of cni config file",
Value: defaultConf.Workers.OCI.NetworkConfig.CNIConfigPath,
},
cli.StringFlag{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you making two different paths for OCI and containerd cni binaries? I think it would be safe to just have one dir

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from a data structure perspective workers should be isolated, eg. there should be a remote worker in the future that could run on a different machine (and different net config). So I want these values to be tied to the worker, not to the builder instance.

Name: "oci-cni-binary-dir",
Usage: "path of cni binary files",
Value: defaultConf.Workers.OCI.NetworkConfig.CNIBinaryPath,
},
}
n := "oci-worker-rootless"
u := "enable rootless mode"
Expand Down Expand Up @@ -154,6 +170,15 @@ func applyOCIFlags(c *cli.Context, cfg *config.Config) error {
cfg.Workers.OCI.GCKeepStorage = c.GlobalInt64("oci-worker-gc-keepstorage") * 1e6
}

if c.GlobalIsSet("oci-worker-net") {
cfg.Workers.OCI.NetworkConfig.Mode = c.GlobalString("oci-worker-net")
}
if c.GlobalIsSet("oci-cni-config-path") {
cfg.Workers.OCI.NetworkConfig.CNIConfigPath = c.GlobalString("oci-cni-worker-path")
}
if c.GlobalIsSet("oci-cni-binary-dir") {
cfg.Workers.OCI.NetworkConfig.CNIBinaryPath = c.GlobalString("oci-cni-binary-dir")
}
return nil
}

Expand Down Expand Up @@ -181,6 +206,9 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker

if cfg.Rootless {
logrus.Debugf("running in rootless mode")
if common.config.Workers.OCI.NetworkConfig.Mode == "auto" {
common.config.Workers.OCI.NetworkConfig.Mode = "host"
}
}

processMode := oci.ProcessSandbox
Expand All @@ -194,7 +222,14 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker

dns := getDNSConfig(common.config.DNS)

opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels, idmapping, dns)
nc := network.Opt{
Root: common.config.Root,
Mode: common.config.Workers.OCI.NetworkConfig.Mode,
CNIConfigPath: common.config.Workers.OCI.CNIConfigPath,
CNIBinaryDir: common.config.Workers.OCI.CNIBinaryPath,
}

opt, err := runc.NewWorkerOpt(common.config.Root, snFactory, cfg.Rootless, processMode, cfg.Labels, idmapping, nc, dns)
if err != nil {
return nil, err
}
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ require (
github.com/containerd/containerd v1.3.0-0.20190426060238-3a3f0aac8819
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260 // indirect
github.com/containerd/go-cni v0.0.0-20190610170741-5a4663dad645
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3
github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7 // indirect
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd // indirect
github.com/containernetworking/cni v0.6.1-0.20180218032124-142cde0c766c // indirect
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
github.com/docker/cli v0.0.0-20190321234815-f40f9c240ab0
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVl
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260 h1:XGyg7oTtD0DoRFhbpV6x1WfV0flKC4UxXU7ab1zC08U=
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
github.com/containerd/go-cni v0.0.0-20190610170741-5a4663dad645 h1:CCxW+4asjsbhMjWAznv/rTLYYI7Mcm6LovkzaPtD3rU=
github.com/containerd/go-cni v0.0.0-20190610170741-5a4663dad645/go.mod h1:2wlRxCQdiBY+OcjNg5x8kI+5mEL1fGt25L4IzQHYJsM=
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3 h1:esQOJREg8nw8aXj6uCN5dfW5cKUBiEJ/+nni1Q/D/sw=
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7 h1:SKDlsIhYxNE1LO0xwuOR+3QWj3zRibVQu5jWIMQmOfU=
github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8NEo3bC/vx9pbi/g2WI8mtP2/nXzu297Y=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/containernetworking/cni v0.6.1-0.20180218032124-142cde0c766c h1:X6Gxg2GV1i0UhDodKZYrp//lg8h3KANe8l3gtFHoi9M=
github.com/containernetworking/cni v0.6.1-0.20180218032124-142cde0c766c/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -51,6 +55,7 @@ github.com/docker/go-units v0.3.1 h1:QAFdsA6jLCnglbqE6mUsHuPcJlntY94DkxHf4deHKIU
github.com/docker/go-units v0.3.1/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libnetwork v0.8.0-dev.2.0.20190604151032-3c26b4e7495e h1:/9dBUVUO865jROD5LfE232z9ssWlBlzIMVW0BaEn8DM=
github.com/docker/libnetwork v0.8.0-dev.2.0.20190604151032-3c26b4e7495e/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
Expand All @@ -77,6 +82,7 @@ github.com/hashicorp/golang-lru v0.0.0-20160207214719-a0d98a5f2880 h1:OaRuzt9oCK
github.com/hashicorp/golang-lru v0.0.0-20160207214719-a0d98a5f2880/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c h1:nQcv325vxv2fFHJsOt53eSRf1eINt6vOdYUFfXs4rgk=
github.com/hashicorp/uuid v0.0.0-20160311170451-ebb0a03e909c/go.mod h1:fHzc09UnyJyqyW+bFuq864eh+wC7dj65aXmXLRe5to0=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ishidawataru/sctp v0.0.0-20180213033435-07191f837fed h1:3MJOWnAfq3T9eoCQTarEY2DMlUWYcBkBLf03dAMvEb8=
github.com/ishidawataru/sctp v0.0.0-20180213033435-07191f837fed/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8=
Expand All @@ -92,7 +98,9 @@ github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
Expand All @@ -119,6 +127,7 @@ github.com/sirupsen/logrus v1.0.3/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjM
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
Expand Down Expand Up @@ -175,9 +184,12 @@ gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
Expand Down
Loading