diff --git a/go.mod b/go.mod index 7a6efb582c2..d4d81f892c7 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/alauda/kube-ovn go 1.12 require ( - github.com/containernetworking/cni v0.7.1 - github.com/containernetworking/plugins v0.8.2 - github.com/coreos/go-iptables v0.4.2 + github.com/containernetworking/cni v0.8.0 + github.com/containernetworking/plugins v0.8.6 + github.com/coreos/go-iptables v0.4.5 github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/elazarl/goproxy v0.0.0-20190630181448-f1e96bc0f4c5 // indirect github.com/elazarl/goproxy/ext v0.0.0-20190630181448-f1e96bc0f4c5 // indirect diff --git a/go.sum b/go.sum index 0b26fc2d0c2..4c262170879 100644 --- a/go.sum +++ b/go.sum @@ -38,13 +38,19 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE= github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0 h1:BT9lpgGoH4jw3lFC7Odz2prU5ruiYKcgAjMCbgybcKI= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/plugins v0.8.2 h1:5lnwfsAYO+V7yXhysJKy3E1A2Gy9oVut031zfdOzI9w= github.com/containernetworking/plugins v0.8.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc= +github.com/containernetworking/plugins v0.8.6 h1:npZTLiMa4CRn6m5P9+1Dz4O1j0UeFbm8VYN6dlsw568= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.2 h1:KH0EwId05JwWIfb96gWvkiT2cbuOu8ygqUaB+yPAwIg= github.com/coreos/go-iptables v0.4.2/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= diff --git a/vendor/github.com/containernetworking/cni/libcni/api.go b/vendor/github.com/containernetworking/cni/libcni/api.go index 0f14d3427e9..7e52bd83873 100644 --- a/vendor/github.com/containernetworking/cni/libcni/api.go +++ b/vendor/github.com/containernetworking/cni/libcni/api.go @@ -25,6 +25,7 @@ import ( "github.com/containernetworking/cni/pkg/invoke" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/utils" "github.com/containernetworking/cni/pkg/version" ) @@ -32,6 +33,10 @@ var ( CacheDir = "/var/lib/cni" ) +const ( + CNICacheV1 = "cniCacheV1" +) + // A RuntimeConf holds the arguments to one invocation of a CNI plugin // excepting the network configuration, with the nested exception that // the `runtimeConfig` from the network configuration is included @@ -48,7 +53,7 @@ type RuntimeConf struct { // to the plugin CapabilityArgs map[string]interface{} - // A cache directory in which to library data. Defaults to CacheDir + // DEPRECATED. Will be removed in a future release. CacheDir string } @@ -70,19 +75,22 @@ type CNI interface { CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) + GetNetworkListCachedConfig(net *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) + GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error) ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error) ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error) } type CNIConfig struct { - Path []string - exec invoke.Exec + Path []string + exec invoke.Exec + cacheDir string } // CNIConfig implements the CNI interface @@ -92,9 +100,18 @@ var _ CNI = &CNIConfig{} // in the given paths and use the given exec interface to run those plugins, // or if the exec interface is not given, will use a default exec handler. func NewCNIConfig(path []string, exec invoke.Exec) *CNIConfig { + return NewCNIConfigWithCacheDir(path, "", exec) +} + +// NewCNIConfigWithCacheDir returns a new CNIConfig object that will search for plugins +// in the given paths use the given exec interface to run those plugins, +// or if the exec interface is not given, will use a default exec handler. +// The given cache directory will be used for temporary data storage when needed. +func NewCNIConfigWithCacheDir(path []string, cacheDir string, exec invoke.Exec) *CNIConfig { return &CNIConfig{ - Path: path, - exec: exec, + Path: path, + cacheDir: cacheDir, + exec: exec, } } @@ -165,33 +182,122 @@ func (c *CNIConfig) ensureExec() invoke.Exec { return c.exec } -func getResultCacheFilePath(netName string, rt *RuntimeConf) string { - cacheDir := rt.CacheDir - if cacheDir == "" { - cacheDir = CacheDir +type cachedInfo struct { + Kind string `json:"kind"` + ContainerID string `json:"containerId"` + Config []byte `json:"config"` + IfName string `json:"ifName"` + NetworkName string `json:"networkName"` + CniArgs [][2]string `json:"cniArgs,omitempty"` + CapabilityArgs map[string]interface{} `json:"capabilityArgs,omitempty"` + RawResult map[string]interface{} `json:"result,omitempty"` + Result types.Result `json:"-"` +} + +// getCacheDir returns the cache directory in this order: +// 1) global cacheDir from CNIConfig object +// 2) deprecated cacheDir from RuntimeConf object +// 3) fall back to default cache directory +func (c *CNIConfig) getCacheDir(rt *RuntimeConf) string { + if c.cacheDir != "" { + return c.cacheDir + } + if rt.CacheDir != "" { + return rt.CacheDir + } + return CacheDir +} + +func (c *CNIConfig) getCacheFilePath(netName string, rt *RuntimeConf) (string, error) { + if netName == "" || rt.ContainerID == "" || rt.IfName == "" { + return "", fmt.Errorf("cache file path requires network name (%q), container ID (%q), and interface name (%q)", netName, rt.ContainerID, rt.IfName) } - return filepath.Join(cacheDir, "results", fmt.Sprintf("%s-%s-%s", netName, rt.ContainerID, rt.IfName)) + return filepath.Join(c.getCacheDir(rt), "results", fmt.Sprintf("%s-%s-%s", netName, rt.ContainerID, rt.IfName)), nil } -func setCachedResult(result types.Result, netName string, rt *RuntimeConf) error { +func (c *CNIConfig) cacheAdd(result types.Result, config []byte, netName string, rt *RuntimeConf) error { + cached := cachedInfo{ + Kind: CNICacheV1, + ContainerID: rt.ContainerID, + Config: config, + IfName: rt.IfName, + NetworkName: netName, + CniArgs: rt.Args, + CapabilityArgs: rt.CapabilityArgs, + } + + // We need to get type.Result into cachedInfo as JSON map + // Marshal to []byte, then Unmarshal into cached.RawResult data, err := json.Marshal(result) if err != nil { return err } - fname := getResultCacheFilePath(netName, rt) + + err = json.Unmarshal(data, &cached.RawResult) + if err != nil { + return err + } + + newBytes, err := json.Marshal(&cached) + if err != nil { + return err + } + + fname, err := c.getCacheFilePath(netName, rt) + if err != nil { + return err + } if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil { return err } - return ioutil.WriteFile(fname, data, 0600) + + return ioutil.WriteFile(fname, newBytes, 0600) } -func delCachedResult(netName string, rt *RuntimeConf) error { - fname := getResultCacheFilePath(netName, rt) +func (c *CNIConfig) cacheDel(netName string, rt *RuntimeConf) error { + fname, err := c.getCacheFilePath(netName, rt) + if err != nil { + // Ignore error + return nil + } return os.Remove(fname) } -func getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) { - fname := getResultCacheFilePath(netName, rt) +func (c *CNIConfig) getCachedConfig(netName string, rt *RuntimeConf) ([]byte, *RuntimeConf, error) { + var bytes []byte + + fname, err := c.getCacheFilePath(netName, rt) + if err != nil { + return nil, nil, err + } + bytes, err = ioutil.ReadFile(fname) + if err != nil { + // Ignore read errors; the cached result may not exist on-disk + return nil, nil, nil + } + + unmarshaled := cachedInfo{} + if err := json.Unmarshal(bytes, &unmarshaled); err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal cached network %q config: %v", netName, err) + } + if unmarshaled.Kind != CNICacheV1 { + return nil, nil, fmt.Errorf("read cached network %q config has wrong kind: %v", netName, unmarshaled.Kind) + } + + newRt := *rt + if unmarshaled.CniArgs != nil { + newRt.Args = unmarshaled.CniArgs + } + newRt.CapabilityArgs = unmarshaled.CapabilityArgs + + return unmarshaled.Config, &newRt, nil +} + +func (c *CNIConfig) getLegacyCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) { + fname, err := c.getCacheFilePath(netName, rt) + if err != nil { + return nil, err + } data, err := ioutil.ReadFile(fname) if err != nil { // Ignore read errors; the cached result may not exist on-disk @@ -222,16 +328,73 @@ func getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, return result, err } +func (c *CNIConfig) getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) { + fname, err := c.getCacheFilePath(netName, rt) + if err != nil { + return nil, err + } + fdata, err := ioutil.ReadFile(fname) + if err != nil { + // Ignore read errors; the cached result may not exist on-disk + return nil, nil + } + + cachedInfo := cachedInfo{} + if err := json.Unmarshal(fdata, &cachedInfo); err != nil || cachedInfo.Kind != CNICacheV1 { + return c.getLegacyCachedResult(netName, cniVersion, rt) + } + + newBytes, err := json.Marshal(&cachedInfo.RawResult) + if err != nil { + return nil, fmt.Errorf("failed to marshal cached network %q config: %v", netName, err) + } + + // Read the version of the cached result + decoder := version.ConfigDecoder{} + resultCniVersion, err := decoder.Decode(newBytes) + if err != nil { + return nil, err + } + + // Ensure we can understand the result + result, err := version.NewResult(resultCniVersion, newBytes) + if err != nil { + return nil, err + } + + // Convert to the config version to ensure plugins get prevResult + // in the same version as the config. The cached result version + // should match the config version unless the config was changed + // while the container was running. + result, err = result.GetAsVersion(cniVersion) + if err != nil && resultCniVersion != cniVersion { + return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err) + } + return result, err +} + // GetNetworkListCachedResult returns the cached Result of the previous -// previous AddNetworkList() operation for a network list, or an error. +// AddNetworkList() operation for a network list, or an error. func (c *CNIConfig) GetNetworkListCachedResult(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) { - return getCachedResult(list.Name, list.CNIVersion, rt) + return c.getCachedResult(list.Name, list.CNIVersion, rt) } // GetNetworkCachedResult returns the cached Result of the previous -// previous AddNetwork() operation for a network, or an error. +// AddNetwork() operation for a network, or an error. func (c *CNIConfig) GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) { - return getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) + return c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) +} + +// GetNetworkListCachedConfig copies the input RuntimeConf to output +// RuntimeConf with fields updated with info from the cached Config. +func (c *CNIConfig) GetNetworkListCachedConfig(list *NetworkConfigList, rt *RuntimeConf) ([]byte, *RuntimeConf, error) { + return c.getCachedConfig(list.Name, rt) +} + +// GetNetworkCachedConfig copies the input RuntimeConf to output +// RuntimeConf with fields updated with info from the cached Config. +func (c *CNIConfig) GetNetworkCachedConfig(net *NetworkConfig, rt *RuntimeConf) ([]byte, *RuntimeConf, error) { + return c.getCachedConfig(net.Network.Name, rt) } func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) { @@ -240,6 +403,15 @@ func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net if err != nil { return nil, err } + if err := utils.ValidateContainerID(rt.ContainerID); err != nil { + return nil, err + } + if err := utils.ValidateNetworkName(name); err != nil { + return nil, err + } + if err := utils.ValidateInterfaceName(rt.IfName); err != nil { + return nil, err + } newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt) if err != nil { @@ -260,7 +432,7 @@ func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList, } } - if err = setCachedResult(result, list.Name, rt); err != nil { + if err = c.cacheAdd(result, list.Bytes, list.Name, rt); err != nil { return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err) } @@ -295,7 +467,7 @@ func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigLis return nil } - cachedResult, err := getCachedResult(list.Name, list.CNIVersion, rt) + cachedResult, err := c.getCachedResult(list.Name, list.CNIVersion, rt) if err != nil { return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err) } @@ -332,7 +504,7 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList, if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil { return err } else if gtet { - cachedResult, err = getCachedResult(list.Name, list.CNIVersion, rt) + cachedResult, err = c.getCachedResult(list.Name, list.CNIVersion, rt) if err != nil { return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err) } @@ -344,7 +516,7 @@ func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList, return err } } - _ = delCachedResult(list.Name, rt) + _ = c.cacheDel(list.Name, rt) return nil } @@ -356,7 +528,7 @@ func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *Runt return nil, err } - if err = setCachedResult(result, net.Network.Name, rt); err != nil { + if err = c.cacheAdd(result, net.Bytes, net.Network.Name, rt); err != nil { return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err) } @@ -372,7 +544,7 @@ func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *Ru return fmt.Errorf("configuration version %q does not support the CHECK command", net.Network.CNIVersion) } - cachedResult, err := getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) + cachedResult, err := c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) if err != nil { return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err) } @@ -387,7 +559,7 @@ func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *Runt if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil { return err } else if gtet { - cachedResult, err = getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) + cachedResult, err = c.getCachedResult(net.Network.Name, net.Network.CNIVersion, rt) if err != nil { return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err) } @@ -396,7 +568,7 @@ func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *Runt if err := c.delNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt); err != nil { return err } - _ = delCachedResult(net.Network.Name, rt) + _ = c.cacheDel(net.Network.Name, rt) return nil } @@ -455,10 +627,14 @@ func (c *CNIConfig) ValidateNetwork(ctx context.Context, net *NetworkConfig) ([] // validatePlugin checks that an individual plugin's configuration is sane func (c *CNIConfig) validatePlugin(ctx context.Context, pluginName, expectedVersion string) error { - pluginPath, err := invoke.FindInPath(pluginName, c.Path) + c.ensureExec() + pluginPath, err := c.exec.FindInPath(pluginName, c.Path) if err != nil { return err } + if expectedVersion == "" { + expectedVersion = "0.1.0" + } vi, err := invoke.GetVersionInfo(ctx, pluginPath, c.exec) if err != nil { diff --git a/vendor/github.com/containernetworking/cni/libcni/conf.go b/vendor/github.com/containernetworking/cni/libcni/conf.go index ea56c509d01..d8920cf8cd5 100644 --- a/vendor/github.com/containernetworking/cni/libcni/conf.go +++ b/vendor/github.com/containernetworking/cni/libcni/conf.go @@ -114,11 +114,11 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) { for i, conf := range plugins { newBytes, err := json.Marshal(conf) if err != nil { - return nil, fmt.Errorf("Failed to marshal plugin config %d: %v", i, err) + return nil, fmt.Errorf("failed to marshal plugin config %d: %v", i, err) } netConf, err := ConfFromBytes(newBytes) if err != nil { - return nil, fmt.Errorf("Failed to parse plugin config %d: %v", i, err) + return nil, fmt.Errorf("failed to parse plugin config %d: %v", i, err) } list.Plugins = append(list.Plugins, netConf) } diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go index 913528c1d59..3cdb4bc8dad 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go @@ -32,7 +32,7 @@ type inherited struct{} var inheritArgsFromEnv inherited -func (_ *inherited) AsEnv() []string { +func (*inherited) AsEnv() []string { return nil } @@ -60,8 +60,8 @@ func (args *Args) AsEnv() []string { pluginArgsStr = stringify(args.PluginArgs) } - // Duplicated values which come first will be overrided, so we must put the - // custom values in the end to avoid being overrided by the process environments. + // Duplicated values which come first will be overridden, so we must put the + // custom values in the end to avoid being overridden by the process environments. env = append(env, "CNI_COMMAND="+args.Command, "CNI_CONTAINERID="+args.ContainerID, diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go index ad8498ba27d..5ab5cc88576 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go @@ -21,6 +21,8 @@ import ( "fmt" "io" "os/exec" + "strings" + "time" "github.com/containernetworking/cni/pkg/types" ) @@ -31,30 +33,54 @@ type RawExec struct { func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) { stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} c := exec.CommandContext(ctx, pluginPath) c.Env = environ c.Stdin = bytes.NewBuffer(stdinData) c.Stdout = stdout - c.Stderr = e.Stderr - if err := c.Run(); err != nil { - return nil, pluginErr(err, stdout.Bytes()) + c.Stderr = stderr + + // Retry the command on "text file busy" errors + for i := 0; i <= 5; i++ { + err := c.Run() + + // Command succeeded + if err == nil { + break + } + + // If the plugin is currently about to be written, then we wait a + // second and try it again + if strings.Contains(err.Error(), "text file busy") { + time.Sleep(time.Second) + continue + } + + // All other errors except than the busy text file + return nil, e.pluginErr(err, stdout.Bytes(), stderr.Bytes()) } + // Copy stderr to caller's buffer in case plugin printed to both + // stdout and stderr for some reason. Ignore failures as stderr is + // only informational. + if e.Stderr != nil && stderr.Len() > 0 { + _, _ = stderr.WriteTo(e.Stderr) + } return stdout.Bytes(), nil } -func pluginErr(err error, output []byte) error { - if _, ok := err.(*exec.ExitError); ok { - emsg := types.Error{} - if len(output) == 0 { - emsg.Msg = "netplugin failed with no error message" - } else if perr := json.Unmarshal(output, &emsg); perr != nil { - emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr) +func (e *RawExec) pluginErr(err error, stdout, stderr []byte) error { + emsg := types.Error{} + if len(stdout) == 0 { + if len(stderr) == 0 { + emsg.Msg = fmt.Sprintf("netplugin failed with no error message: %v", err) + } else { + emsg.Msg = fmt.Sprintf("netplugin failed: %q", string(stderr)) } - return &emsg + } else if perr := json.Unmarshal(stdout, &emsg); perr != nil { + emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(stdout), perr) } - - return err + return &emsg } func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) { diff --git a/vendor/github.com/containernetworking/cni/pkg/skel/skel.go b/vendor/github.com/containernetworking/cni/pkg/skel/skel.go index af56b8a1c50..da42db55943 100644 --- a/vendor/github.com/containernetworking/cni/pkg/skel/skel.go +++ b/vendor/github.com/containernetworking/cni/pkg/skel/skel.go @@ -27,6 +27,7 @@ import ( "strings" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/utils" "github.com/containernetworking/cni/pkg/version" ) @@ -53,16 +54,7 @@ type dispatcher struct { type reqForCmdEntry map[string]bool -// internal only error to indicate lack of required environment variables -type missingEnvError struct { - msg string -} - -func (e missingEnvError) Error() string { - return e.msg -} - -func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) { +func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, *types.Error) { var cmd, contID, netns, ifName, args, path string vars := []struct { @@ -138,7 +130,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) { if len(argsMissing) > 0 { joined := strings.Join(argsMissing, ",") - return "", nil, missingEnvError{fmt.Sprintf("required env variables [%s] missing", joined)} + return "", nil, types.NewError(types.ErrInvalidEnvironmentVariables, fmt.Sprintf("required env variables [%s] missing", joined), "") } if cmd == "VERSION" { @@ -147,7 +139,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) { stdinData, err := ioutil.ReadAll(t.Stdin) if err != nil { - return "", nil, fmt.Errorf("error reading from stdin: %v", err) + return "", nil, types.NewError(types.ErrIOFailure, fmt.Sprintf("error reading from stdin: %v", err), "") } cmdArgs := &CmdArgs{ @@ -161,39 +153,39 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) { return cmd, cmdArgs, nil } -func createTypedError(f string, args ...interface{}) *types.Error { - return &types.Error{ - Code: 100, - Msg: fmt.Sprintf(f, args...), - } -} - -func (t *dispatcher) checkVersionAndCall(cmdArgs *CmdArgs, pluginVersionInfo version.PluginInfo, toCall func(*CmdArgs) error) error { +func (t *dispatcher) checkVersionAndCall(cmdArgs *CmdArgs, pluginVersionInfo version.PluginInfo, toCall func(*CmdArgs) error) *types.Error { configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData) if err != nil { - return err + return types.NewError(types.ErrDecodingFailure, err.Error(), "") } verErr := t.VersionReconciler.Check(configVersion, pluginVersionInfo) if verErr != nil { - return &types.Error{ - Code: types.ErrIncompatibleCNIVersion, - Msg: "incompatible CNI versions", - Details: verErr.Details(), + return types.NewError(types.ErrIncompatibleCNIVersion, "incompatible CNI versions", verErr.Details()) + } + + if err = toCall(cmdArgs); err != nil { + if e, ok := err.(*types.Error); ok { + // don't wrap Error in Error + return e } + return types.NewError(types.ErrInternal, err.Error(), "") } - return toCall(cmdArgs) + return nil } -func validateConfig(jsonBytes []byte) error { +func validateConfig(jsonBytes []byte) *types.Error { var conf struct { Name string `json:"name"` } if err := json.Unmarshal(jsonBytes, &conf); err != nil { - return fmt.Errorf("error reading network config: %s", err) + return types.NewError(types.ErrDecodingFailure, fmt.Sprintf("error unmarshall network config: %v", err), "") } if conf.Name == "" { - return fmt.Errorf("missing network name") + return types.NewError(types.ErrInvalidNetworkConfig, "missing network name", "") + } + if err := utils.ValidateNetworkName(conf.Name); err != nil { + return err } return nil } @@ -202,17 +194,22 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error, cmd, cmdArgs, err := t.getCmdArgsFromEnv() if err != nil { // Print the about string to stderr when no command is set - if _, ok := err.(missingEnvError); ok && t.Getenv("CNI_COMMAND") == "" && about != "" { - fmt.Fprintln(t.Stderr, about) + if err.Code == types.ErrInvalidEnvironmentVariables && t.Getenv("CNI_COMMAND") == "" && about != "" { + _, _ = fmt.Fprintln(t.Stderr, about) return nil } - return createTypedError(err.Error()) + return err } if cmd != "VERSION" { - err = validateConfig(cmdArgs.StdinData) - if err != nil { - return createTypedError(err.Error()) + if err = validateConfig(cmdArgs.StdinData); err != nil { + return err + } + if err = utils.ValidateContainerID(cmdArgs.ContainerID); err != nil { + return err + } + if err = utils.ValidateInterfaceName(cmdArgs.IfName); err != nil { + return err } } @@ -222,45 +219,37 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdCheck, cmdDel func(_ *CmdArgs) error, case "CHECK": configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData) if err != nil { - return createTypedError(err.Error()) + return types.NewError(types.ErrDecodingFailure, err.Error(), "") } if gtet, err := version.GreaterThanOrEqualTo(configVersion, "0.4.0"); err != nil { - return createTypedError(err.Error()) + return types.NewError(types.ErrDecodingFailure, err.Error(), "") } else if !gtet { - return &types.Error{ - Code: types.ErrIncompatibleCNIVersion, - Msg: "config version does not allow CHECK", - } + return types.NewError(types.ErrIncompatibleCNIVersion, "config version does not allow CHECK", "") } for _, pluginVersion := range versionInfo.SupportedVersions() { gtet, err := version.GreaterThanOrEqualTo(pluginVersion, configVersion) if err != nil { - return createTypedError(err.Error()) + return types.NewError(types.ErrDecodingFailure, err.Error(), "") } else if gtet { if err := t.checkVersionAndCall(cmdArgs, versionInfo, cmdCheck); err != nil { - return createTypedError(err.Error()) + return err } return nil } } - return &types.Error{ - Code: types.ErrIncompatibleCNIVersion, - Msg: "plugin version does not allow CHECK", - } + return types.NewError(types.ErrIncompatibleCNIVersion, "plugin version does not allow CHECK", "") case "DEL": err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdDel) case "VERSION": - err = versionInfo.Encode(t.Stdout) + if err := versionInfo.Encode(t.Stdout); err != nil { + return types.NewError(types.ErrIOFailure, err.Error(), "") + } default: - return createTypedError("unknown CNI_COMMAND: %v", cmd) + return types.NewError(types.ErrInvalidEnvironmentVariables, fmt.Sprintf("unknown CNI_COMMAND: %v", cmd), "") } if err != nil { - if e, ok := err.(*types.Error); ok { - // don't wrap Error in Error - return e - } - return createTypedError(err.Error()) + return err } return nil } diff --git a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go index 53256167fad..36f31678a8e 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go @@ -86,20 +86,6 @@ func (r *Result) PrintTo(writer io.Writer) error { return err } -// String returns a formatted string in the form of "[IP4: $1,][ IP6: $2,] DNS: $3" where -// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the -// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string. -func (r *Result) String() string { - var str string - if r.IP4 != nil { - str = fmt.Sprintf("IP4:%+v, ", *r.IP4) - } - if r.IP6 != nil { - str += fmt.Sprintf("IP6:%+v, ", *r.IP6) - } - return fmt.Sprintf("%sDNS:%+v", str, r.DNS) -} - // IPConfig contains values necessary to configure an interface type IPConfig struct { IP net.IPNet diff --git a/vendor/github.com/containernetworking/cni/pkg/types/args.go b/vendor/github.com/containernetworking/cni/pkg/types/args.go index bd8640fc969..4eac6489947 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/args.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/args.go @@ -36,7 +36,7 @@ func (b *UnmarshallableBool) UnmarshalText(data []byte) error { case "0", "false": *b = false default: - return fmt.Errorf("Boolean unmarshal error: invalid input %s", s) + return fmt.Errorf("boolean unmarshal error: invalid input %s", s) } return nil } diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go index 7267a2e6d1f..754cc6e722e 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go @@ -207,23 +207,6 @@ func (r *Result) PrintTo(writer io.Writer) error { return err } -// String returns a formatted string in the form of "[Interfaces: $1,][ IP: $2,] DNS: $3" where -// $1 represents the receiver's Interfaces, $2 represents the receiver's IP addresses and $3 the -// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string. -func (r *Result) String() string { - var str string - if len(r.Interfaces) > 0 { - str += fmt.Sprintf("Interfaces:%+v, ", r.Interfaces) - } - if len(r.IPs) > 0 { - str += fmt.Sprintf("IP:%+v, ", r.IPs) - } - if len(r.Routes) > 0 { - str += fmt.Sprintf("Routes:%+v, ", r.Routes) - } - return fmt.Sprintf("%sDNS:%+v", str, r.DNS) -} - // Convert this old version result to the current CNI version result func (r *Result) Convert() (*Result, error) { return r, nil diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go index d0d11006a05..3fa757a5d22 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/types.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/types.go @@ -16,7 +16,6 @@ package types import ( "encoding/json" - "errors" "fmt" "io" "net" @@ -101,9 +100,6 @@ type Result interface { // Prints the result in JSON format to provided writer PrintTo(writer io.Writer) error - - // Returns a JSON string representation of the result - String() string } func PrintResult(result Result, version string) error { @@ -134,9 +130,16 @@ func (r *Route) String() string { // Well known error codes // see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes const ( - ErrUnknown uint = iota // 0 - ErrIncompatibleCNIVersion // 1 - ErrUnsupportedField // 2 + ErrUnknown uint = iota // 0 + ErrIncompatibleCNIVersion // 1 + ErrUnsupportedField // 2 + ErrUnknownContainer // 3 + ErrInvalidEnvironmentVariables // 4 + ErrIOFailure // 5 + ErrDecodingFailure // 6 + ErrInvalidNetworkConfig // 7 + ErrTryAgainLater uint = 11 + ErrInternal uint = 999 ) type Error struct { @@ -145,6 +148,14 @@ type Error struct { Details string `json:"details,omitempty"` } +func NewError(code uint, msg, details string) *Error { + return &Error{ + Code: code, + Msg: msg, + Details: details, + } +} + func (e *Error) Error() string { details := "" if e.Details != "" { @@ -194,6 +205,3 @@ func prettyPrint(obj interface{}) error { _, err = os.Stdout.Write(data) return err } - -// NotImplementedError is used to indicate that a method is not implemented for the given platform -var NotImplementedError = errors.New("Not Implemented") diff --git a/vendor/github.com/containernetworking/cni/pkg/utils/utils.go b/vendor/github.com/containernetworking/cni/pkg/utils/utils.go new file mode 100644 index 00000000000..b8ec3887459 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/utils/utils.go @@ -0,0 +1,84 @@ +// Copyright 2019 CNI 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. + +package utils + +import ( + "bytes" + "fmt" + "regexp" + "unicode" + + "github.com/containernetworking/cni/pkg/types" +) + +const ( + // cniValidNameChars is the regexp used to validate valid characters in + // containerID and networkName + cniValidNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.\-]` + + // maxInterfaceNameLength is the length max of a valid interface name + maxInterfaceNameLength = 15 +) + +var cniReg = regexp.MustCompile(`^` + cniValidNameChars + `*$`) + +// ValidateContainerID will validate that the supplied containerID is not empty does not contain invalid characters +func ValidateContainerID(containerID string) *types.Error { + + if containerID == "" { + return types.NewError(types.ErrUnknownContainer, "missing containerID", "") + } + if !cniReg.MatchString(containerID) { + return types.NewError(types.ErrInvalidEnvironmentVariables, "invalid characters in containerID", containerID) + } + return nil +} + +// ValidateNetworkName will validate that the supplied networkName does not contain invalid characters +func ValidateNetworkName(networkName string) *types.Error { + + if networkName == "" { + return types.NewError(types.ErrInvalidNetworkConfig, "missing network name:", "") + } + if !cniReg.MatchString(networkName) { + return types.NewError(types.ErrInvalidNetworkConfig, "invalid characters found in network name", networkName) + } + return nil +} + +// ValidateInterfaceName will validate the interface name based on the three rules below +// 1. The name must not be empty +// 2. The name must be less than 16 characters +// 3. The name must not be "." or ".." +// 3. The name must not contain / or : or any whitespace characters +// ref to https://github.com/torvalds/linux/blob/master/net/core/dev.c#L1024 +func ValidateInterfaceName(ifName string) *types.Error { + if len(ifName) == 0 { + return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is empty", "") + } + if len(ifName) > maxInterfaceNameLength { + return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is too long", fmt.Sprintf("interface name should be less than %d characters", maxInterfaceNameLength+1)) + } + if ifName == "." || ifName == ".." { + return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name is . or ..", "") + } + for _, r := range bytes.Runes([]byte(ifName)) { + if r == '/' || r == ':' || unicode.IsSpace(r) { + return types.NewError(types.ErrInvalidEnvironmentVariables, "interface name contains / or : or whitespace characters", "") + } + } + + return nil +} diff --git a/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go index 31ad5f622fe..a34f97170e3 100644 --- a/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go +++ b/vendor/github.com/containernetworking/plugins/pkg/ns/ns_linux.go @@ -178,7 +178,16 @@ func (ns *netNS) Do(toRun func(NetNS) error) error { if err = ns.Set(); err != nil { return fmt.Errorf("error switching to ns %v: %v", ns.file.Name(), err) } - defer threadNS.Set() // switch back + defer func() { + err := threadNS.Set() // switch back + if err == nil { + // Unlock the current thread only when we successfully switched back + // to the original namespace; otherwise leave the thread locked which + // will force the runtime to scrap the current thread, that is maybe + // not as optimal but at least always safe to do. + runtime.UnlockOSThread() + } + }() return toRun(hostNS) } @@ -193,6 +202,10 @@ func (ns *netNS) Do(toRun func(NetNS) error) error { var wg sync.WaitGroup wg.Add(1) + // Start the callback in a new green thread so that if we later fail + // to switch the namespace back to the original one, we can safely + // leave the thread locked to die without a risk of the current thread + // left lingering with incorrect namespace. var innerError error go func() { defer wg.Done() diff --git a/vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go b/vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go index fe06d2d99db..7ee47e1ce3c 100644 --- a/vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go +++ b/vendor/github.com/containernetworking/plugins/pkg/utils/sysctl/sysctl_linux.go @@ -35,7 +35,7 @@ func Sysctl(name string, params ...string) (string, error) { } func getSysctl(name string) (string, error) { - fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) + fullName := filepath.Join("/proc/sys", toNormalName(name)) fullName = filepath.Clean(fullName) data, err := ioutil.ReadFile(fullName) if err != nil { @@ -46,7 +46,7 @@ func getSysctl(name string) (string, error) { } func setSysctl(name, value string) (string, error) { - fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) + fullName := filepath.Join("/proc/sys", toNormalName(name)) fullName = filepath.Clean(fullName) if err := ioutil.WriteFile(fullName, []byte(value), 0644); err != nil { return "", err @@ -54,3 +54,27 @@ func setSysctl(name, value string) (string, error) { return getSysctl(name) } + +// Normalize names by using slash as separator +// Sysctl names can use dots or slashes as separator: +// - if dots are used, dots and slashes are interchanged. +// - if slashes are used, slashes and dots are left intact. +// Separator in use is determined by first occurrence. +func toNormalName(name string) string { + interchange := false + for _, c := range name { + if c == '.' { + interchange = true + break + } + if c == '/' { + break + } + } + + if interchange { + r := strings.NewReplacer(".", "/", "/", ".") + return r.Replace(name) + } + return name +} diff --git a/vendor/github.com/coreos/go-iptables/iptables/iptables.go b/vendor/github.com/coreos/go-iptables/iptables/iptables.go index 2ed875bb58f..1074275b020 100644 --- a/vendor/github.com/coreos/go-iptables/iptables/iptables.go +++ b/vendor/github.com/coreos/go-iptables/iptables/iptables.go @@ -48,9 +48,13 @@ func (e *Error) Error() string { // IsNotExist returns true if the error is due to the chain or rule not existing func (e *Error) IsNotExist() bool { - return e.ExitStatus() == 1 && - (e.msg == fmt.Sprintf("%s: Bad rule (does a matching rule exist in that chain?).\n", getIptablesCommand(e.proto)) || - e.msg == fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(e.proto))) + if e.ExitStatus() != 1 { + return false + } + cmdIptables := getIptablesCommand(e.proto) + msgNoRuleExist := fmt.Sprintf("%s: Bad rule (does a matching rule exist in that chain?).\n", cmdIptables) + msgNoChainExist := fmt.Sprintf("%s: No chain/target/match by that name.\n", cmdIptables) + return strings.Contains(e.msg, msgNoRuleExist) || strings.Contains(e.msg, msgNoChainExist) } // Protocol to differentiate between IPv4 and IPv6 @@ -101,7 +105,13 @@ func NewWithProtocol(proto Protocol) (*IPTables, error) { return nil, err } vstring, err := getIptablesVersionString(path) + if err != nil { + return nil, fmt.Errorf("could not get iptables version: %v", err) + } v1, v2, v3, mode, err := extractIptablesVersion(vstring) + if err != nil { + return nil, fmt.Errorf("failed to extract iptables version from [%s]: %v", vstring, err) + } checkPresent, waitPresent, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3) @@ -348,18 +358,6 @@ func (ipt *IPTables) executeList(args []string) ([]string, error) { rules = rules[:len(rules)-1] } - // nftables mode doesn't return an error code when listing a non-existent - // chain. Patch that up. - if len(rules) == 0 && ipt.mode == "nf_tables" { - v := 1 - return nil, &Error{ - cmd: exec.Cmd{Args: args}, - msg: fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(ipt.proto)), - proto: ipt.proto, - exitStatus: &v, - } - } - for i, rule := range rules { rules[i] = filterRuleOutput(rule) } @@ -437,6 +435,7 @@ func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error { } ul, err := fmu.tryLock() if err != nil { + syscall.Close(fmu.fd) return err } defer ul.Unlock() diff --git a/vendor/modules.txt b/vendor/modules.txt index 73144d0ff21..9fe14ffafb1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2,22 +2,27 @@ github.com/armon/go-radix # github.com/beorn7/perks v1.0.1 github.com/beorn7/perks/quantile -# github.com/containernetworking/cni v0.7.1 +# github.com/containernetworking/cni v0.8.0 +## explicit github.com/containernetworking/cni/libcni github.com/containernetworking/cni/pkg/invoke github.com/containernetworking/cni/pkg/skel github.com/containernetworking/cni/pkg/types github.com/containernetworking/cni/pkg/types/020 github.com/containernetworking/cni/pkg/types/current +github.com/containernetworking/cni/pkg/utils github.com/containernetworking/cni/pkg/version -# github.com/containernetworking/plugins v0.8.2 +# github.com/containernetworking/plugins v0.8.6 +## explicit github.com/containernetworking/plugins/pkg/ns github.com/containernetworking/plugins/pkg/utils/sysctl -# github.com/coreos/go-iptables v0.4.2 +# github.com/coreos/go-iptables v0.4.5 +## explicit github.com/coreos/go-iptables/iptables # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew # github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 +## explicit github.com/dgryski/go-farm # github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 github.com/docker/spdystream @@ -26,21 +31,31 @@ github.com/docker/spdystream/spdy github.com/eapache/channels # github.com/eapache/queue v1.1.0 github.com/eapache/queue +# github.com/elazarl/goproxy v0.0.0-20190630181448-f1e96bc0f4c5 +## explicit +# github.com/elazarl/goproxy/ext v0.0.0-20190630181448-f1e96bc0f4c5 +## explicit # github.com/emicklei/go-restful v2.11.1+incompatible +## explicit github.com/emicklei/go-restful github.com/emicklei/go-restful/log # github.com/evanphx/json-patch v4.5.0+incompatible github.com/evanphx/json-patch # github.com/fsnotify/fsnotify v1.4.7 github.com/fsnotify/fsnotify +# github.com/go-ini/ini v1.42.0 +## explicit # github.com/go-logr/logr v0.1.0 github.com/go-logr/logr +# github.com/go-logr/zapr v0.1.1 +## explicit # github.com/gogo/protobuf v1.3.0 github.com/gogo/protobuf/proto github.com/gogo/protobuf/sortkeys # github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 github.com/golang/groupcache/lru # github.com/golang/protobuf v1.3.2 +## explicit github.com/golang/protobuf/proto github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes/any @@ -61,6 +76,8 @@ github.com/google/uuid github.com/googleapis/gnostic/OpenAPIv2 github.com/googleapis/gnostic/compiler github.com/googleapis/gnostic/extensions +# github.com/hashicorp/go-version v1.2.0 +## explicit # github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/golang-lru github.com/hashicorp/golang-lru/simplelru @@ -82,17 +99,25 @@ github.com/hpcloud/tail/util github.com/hpcloud/tail/watch github.com/hpcloud/tail/winfile # github.com/imdario/mergo v0.3.7 +## explicit github.com/imdario/mergo # github.com/intel/multus-cni v0.0.0-20200313031649-eaf6ff6e20bb +## explicit github.com/intel/multus-cni/logging github.com/intel/multus-cni/types # github.com/json-iterator/go v1.1.9 github.com/json-iterator/go # github.com/juju/errors v0.0.0-20190207033735-e65537c515d7 +## explicit github.com/juju/errors +# github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 +## explicit +# github.com/kelseyhightower/envconfig v1.4.0 +## explicit # github.com/konsorten/go-windows-terminal-sequences v1.0.2 github.com/konsorten/go-windows-terminal-sequences # github.com/kubesphere/porter v0.1.1 +## explicit github.com/kubesphere/porter/pkg/bgp/apiutil # github.com/magiconair/properties v1.8.1 github.com/magiconair/properties @@ -105,10 +130,13 @@ github.com/modern-go/concurrent # github.com/modern-go/reflect2 v1.0.1 github.com/modern-go/reflect2 # github.com/moul/http2curl v1.0.0 +## explicit github.com/moul/http2curl # github.com/oilbeater/go-ping v0.0.0-20200413021620-332b7197c5b5 +## explicit github.com/oilbeater/go-ping # github.com/onsi/ginkgo v1.12.0 +## explicit github.com/onsi/ginkgo github.com/onsi/ginkgo/config github.com/onsi/ginkgo/internal/codelocation @@ -128,6 +156,7 @@ github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty github.com/onsi/ginkgo/types # github.com/onsi/gomega v1.9.0 +## explicit github.com/onsi/gomega github.com/onsi/gomega/format github.com/onsi/gomega/internal/assertion @@ -141,6 +170,7 @@ github.com/onsi/gomega/matchers/support/goraph/node github.com/onsi/gomega/matchers/support/goraph/util github.com/onsi/gomega/types # github.com/osrg/gobgp v0.0.0-20190401195721-805d02fdfbc5 +## explicit github.com/osrg/gobgp/api github.com/osrg/gobgp/internal/pkg/apiutil github.com/osrg/gobgp/internal/pkg/config @@ -152,17 +182,26 @@ github.com/osrg/gobgp/pkg/packet/mrt github.com/osrg/gobgp/pkg/packet/rtr github.com/osrg/gobgp/pkg/server # github.com/parnurzeal/gorequest v0.2.15 +## explicit github.com/parnurzeal/gorequest # github.com/pelletier/go-toml v1.4.0 github.com/pelletier/go-toml # github.com/pkg/errors v0.8.1 github.com/pkg/errors # github.com/projectcalico/felix v3.6.1+incompatible +## explicit github.com/projectcalico/felix/dispatcher github.com/projectcalico/felix/ip github.com/projectcalico/felix/ipsets github.com/projectcalico/felix/labelindex +# github.com/projectcalico/go-json v0.0.0-20161128004156-6219dc7339ba +## explicit +# github.com/projectcalico/go-yaml v0.0.0-20161201183616-955bc3e451ef +## explicit +# github.com/projectcalico/go-yaml-wrapper v0.0.0-20161127220527-598e54215bee +## explicit # github.com/projectcalico/libcalico-go v0.0.0-20190305235709-3d935c3b8b86 +## explicit github.com/projectcalico/libcalico-go/lib/apis/v1 github.com/projectcalico/libcalico-go/lib/apis/v1/unversioned github.com/projectcalico/libcalico-go/lib/apis/v3 @@ -180,6 +219,7 @@ github.com/projectcalico/libcalico-go/lib/selector/parser github.com/projectcalico/libcalico-go/lib/selector/tokenizer github.com/projectcalico/libcalico-go/lib/set # github.com/prometheus/client_golang v1.1.0 +## explicit github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promhttp @@ -195,6 +235,7 @@ github.com/prometheus/procfs/internal/fs # github.com/satori/go.uuid v0.0.0-20180103174451-36e9d2ebbde5 github.com/satori/go.uuid # github.com/sirupsen/logrus v1.4.2 +## explicit github.com/sirupsen/logrus # github.com/spf13/afero v1.2.2 github.com/spf13/afero @@ -204,12 +245,15 @@ github.com/spf13/cast # github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/jwalterweatherman # github.com/spf13/pflag v1.0.5 +## explicit github.com/spf13/pflag # github.com/spf13/viper v1.6.3 +## explicit github.com/spf13/viper # github.com/subosito/gotenv v1.2.0 github.com/subosito/gotenv # github.com/vishvananda/netlink v1.0.0 +## explicit github.com/vishvananda/netlink github.com/vishvananda/netlink/nl # github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f @@ -280,6 +324,7 @@ google.golang.org/appengine/urlfetch # google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 google.golang.org/genproto/googleapis/rpc/status # google.golang.org/grpc v1.23.0 +## explicit google.golang.org/grpc google.golang.org/grpc/balancer google.golang.org/grpc/balancer/base @@ -324,6 +369,7 @@ gopkg.in/tomb.v1 # gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 # k8s.io/api v0.0.0-20190703205437-39734b2a72fe +## explicit k8s.io/api/admission/v1beta1 k8s.io/api/admissionregistration/v1beta1 k8s.io/api/apps/v1 @@ -365,6 +411,7 @@ k8s.io/api/storage/v1beta1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1 # k8s.io/apimachinery v0.0.0-20190703205208-4cfb76a8bf76 +## explicit k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/meta k8s.io/apimachinery/pkg/api/resource @@ -413,6 +460,7 @@ k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect # k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible => k8s.io/client-go v0.0.0-20190620085101-78d2af792bab +## explicit k8s.io/client-go/discovery k8s.io/client-go/discovery/fake k8s.io/client-go/dynamic @@ -571,17 +619,21 @@ k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue # k8s.io/klog v1.0.0 +## explicit k8s.io/klog k8s.io/klog/klogr # k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c k8s.io/kube-openapi/pkg/util/proto # k8s.io/sample-controller v0.0.0-20190326030654-b8f621986e45 +## explicit k8s.io/sample-controller/pkg/signals # k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a +## explicit k8s.io/utils/buffer k8s.io/utils/integer k8s.io/utils/trace # sigs.k8s.io/controller-runtime v0.2.0-beta.5 => sigs.k8s.io/controller-runtime v0.2.0-beta.4 +## explicit sigs.k8s.io/controller-runtime sigs.k8s.io/controller-runtime/pkg/builder sigs.k8s.io/controller-runtime/pkg/cache @@ -618,3 +670,5 @@ sigs.k8s.io/controller-runtime/pkg/webhook/internal/certwatcher sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics # sigs.k8s.io/yaml v1.1.0 sigs.k8s.io/yaml +# k8s.io/client-go => k8s.io/client-go v0.0.0-20190620085101-78d2af792bab +# sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.2.0-beta.4