Hello community, here is the log from the commit of package cni for openSUSE:Factory checked in at 2019-07-26 12:37:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cni (Old) and /work/SRC/openSUSE:Factory/.cni.new.4126 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cni" Fri Jul 26 12:37:09 2019 rev:7 rq:716935 version:0.7.1 Changes: -------- --- /work/SRC/openSUSE:Factory/cni/cni.changes 2019-05-22 10:50:37.895351778 +0200 +++ /work/SRC/openSUSE:Factory/.cni.new.4126/cni.changes 2019-07-26 12:37:15.342027128 +0200 @@ -1,0 +2,14 @@ +Tue Jul 16 07:36:57 UTC 2019 - John Paul Adrian Glaubitz <[email protected]> + +- Update to version 0.7.1: + * Library changes: + + invoke : ensure custom envs of CNIArgs are prepended to process envs + + add GetNetworkListCachedResult to CNI interface + + delegate : allow delegation funcs override CNI_COMMAND env automatically in heritance + * Documentation & Convention changes: + + Update cnitool documentation for spec v0.4.0 + + Add cni-route-override to CNI plugin list + * Build and test changes: + + Release: bump go to v1.12 + +------------------------------------------------------------------- Old: ---- cni-0.7.0.tar.xz New: ---- cni-0.7.1.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cni.spec ++++++ --- /var/tmp/diff_new_pack.Tu1wGy/_old 2019-07-26 12:37:15.898026761 +0200 +++ /var/tmp/diff_new_pack.Tu1wGy/_new 2019-07-26 12:37:15.902026759 +0200 @@ -21,7 +21,7 @@ %define cni_doc_dir %{_docdir}/cni Name: cni -Version: 0.7.0 +Version: 0.7.1 Release: 0 Summary: Container Network Interface - networking for Linux containers License: Apache-2.0 ++++++ cni-0.7.0.tar.xz -> cni-0.7.1.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/.travis.yml new/cni-0.7.1/.travis.yml --- old/cni-0.7.0/.travis.yml 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/.travis.yml 2019-06-05 17:31:12.000000000 +0200 @@ -2,8 +2,8 @@ dist: trusty go: - - 1.10.x - 1.11.x + - 1.12.x env: matrix: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/README.md new/cni-0.7.1/README.md --- old/cni-0.7.0/README.md 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/README.md 2019-06-05 17:31:12.000000000 +0200 @@ -67,6 +67,7 @@ - [Knitter - a CNI plugin supporting multiple networking for Kubernetes](https://github.com/ZTE/Knitter) - [DANM - a CNI-compliant networking solution for TelCo workloads running on Kubernetes](https://github.com/nokia/danm) - [VMware NSX – a CNI plugin that enables automated NSX L2/L3 networking and L4/L7 Load Balancing; network isolation at the pod, node, and cluster level; and zero-trust security policy for your Kubernetes cluster.](https://docs.vmware.com/en/VMware-NSX-T/2.2/com.vmware.nsxt.ncp_kubernetes.doc/GUID-6AFA724E-BB62-4693-B95C-321E8DDEA7E1.html) +- [cni-route-override - a meta CNI plugin that override route information](https://github.com/redhat-nfvpe/cni-route-override) The CNI team also maintains some [core plugins in a separate repository](https://github.com/containernetworking/plugins). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/Vagrantfile new/cni-0.7.1/Vagrantfile --- old/cni-0.7.0/Vagrantfile 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/Vagrantfile 2019-06-05 17:31:12.000000000 +0200 @@ -12,7 +12,7 @@ apt-get update -y || (sleep 40 && apt-get update -y) apt-get install -y git - wget -qO- https://storage.googleapis.com/golang/go1.11.1.linux-amd64.tar.gz | tar -C /usr/local -xz + wget -qO- https://storage.googleapis.com/golang/go1.12.5.linux-amd64.tar.gz | tar -C /usr/local -xz echo 'export GOPATH=/go; export PATH=/usr/local/go/bin:$GOPATH/bin:$PATH' >> /root/.bashrc eval `tail -n1 /root/.bashrc` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/cnitool/README.md new/cni-0.7.1/cnitool/README.md --- old/cni-0.7.0/cnitool/README.md 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/cnitool/README.md 2019-06-05 17:31:12.000000000 +0200 @@ -21,7 +21,7 @@ Create a network configuration ``` -echo '{"cniVersion":"0.3.1","name":"myptp","type":"ptp","ipMasq":true,"ipam":{"type":"host-local","subnet":"172.16.29.0/24","routes":[{"dst":"0.0.0.0/0"}]}}' | sudo tee /etc/cni/net.d/10-myptp.conf +echo '{"cniVersion":"0.4.0","name":"myptp","type":"ptp","ipMasq":true,"ipam":{"type":"host-local","subnet":"172.16.29.0/24","routes":[{"dst":"0.0.0.0/0"}]}}' | sudo tee /etc/cni/net.d/10-myptp.conf ``` Create a network namespace. This will be called `testing`: @@ -35,6 +35,11 @@ sudo CNI_PATH=./bin cnitool add myptp /var/run/netns/testing ``` +Check whether the container's networking is as expected (ONLY for spec v0.4.0+): +``` +sudo CNI_PATH=./bin cnitool check myptp /var/run/netns/testing +``` + Test that it works: ``` sudo ip -n testing addr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/libcni/api.go new/cni-0.7.1/libcni/api.go --- old/cni-0.7.0/libcni/api.go 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/libcni/api.go 2019-06-05 17:31:12.000000000 +0200 @@ -69,6 +69,7 @@ AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) 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) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/pkg/invoke/args.go new/cni-0.7.1/pkg/invoke/args.go --- old/cni-0.7.0/pkg/invoke/args.go 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/pkg/invoke/args.go 2019-06-05 17:31:12.000000000 +0200 @@ -15,6 +15,7 @@ package invoke import ( + "fmt" "os" "strings" ) @@ -22,6 +23,8 @@ type CNIArgs interface { // For use with os/exec; i.e., return nil to inherit the // environment from this process + // For use in delegation; inherit the environment from this + // process and allow overrides AsEnv() []string } @@ -57,17 +60,17 @@ pluginArgsStr = stringify(args.PluginArgs) } - // Ensure that the custom values are first, so any value present in - // the process environment won't override them. - env = append([]string{ - "CNI_COMMAND=" + args.Command, - "CNI_CONTAINERID=" + args.ContainerID, - "CNI_NETNS=" + args.NetNS, - "CNI_ARGS=" + pluginArgsStr, - "CNI_IFNAME=" + args.IfName, - "CNI_PATH=" + args.Path, - }, env...) - return env + // 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. + env = append(env, + "CNI_COMMAND="+args.Command, + "CNI_CONTAINERID="+args.ContainerID, + "CNI_NETNS="+args.NetNS, + "CNI_ARGS="+pluginArgsStr, + "CNI_IFNAME="+args.IfName, + "CNI_PATH="+args.Path, + ) + return dedupEnv(env) } // taken from rkt/networking/net_plugin.go @@ -80,3 +83,46 @@ return strings.Join(entries, ";") } + +// DelegateArgs implements the CNIArgs interface +// used for delegation to inherit from environments +// and allow some overrides like CNI_COMMAND +var _ CNIArgs = &DelegateArgs{} + +type DelegateArgs struct { + Command string +} + +func (d *DelegateArgs) AsEnv() []string { + env := os.Environ() + + // The custom values should come in the end to override the existing + // process environment of the same key. + env = append(env, + "CNI_COMMAND="+d.Command, + ) + return dedupEnv(env) +} + +// dedupEnv returns a copy of env with any duplicates removed, in favor of later values. +// Items not of the normal environment "key=value" form are preserved unchanged. +func dedupEnv(env []string) []string { + out := make([]string, 0, len(env)) + envMap := map[string]string{} + + for _, kv := range env { + // find the first "=" in environment, if not, just keep it + eq := strings.Index(kv, "=") + if eq < 0 { + out = append(out, kv) + continue + } + envMap[kv[:eq]] = kv[eq+1:] + } + + for k, v := range envMap { + out = append(out, fmt.Sprintf("%s=%s", k, v)) + } + + return out +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/pkg/invoke/args_test.go new/cni-0.7.1/pkg/invoke/args_test.go --- old/cni-0.7.0/pkg/invoke/args_test.go 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/pkg/invoke/args_test.go 2019-06-05 17:31:12.000000000 +0200 @@ -23,9 +23,18 @@ . "github.com/onsi/gomega" ) -var _ = Describe("Args", func() { - Describe("AsEnv", func() { - It("places the CNI_ environment variables ahead of any ambient variables", func() { +var _ = Describe("CNIArgs AsEnv", func() { + Describe("Args AsEnv", func() { + BeforeEach(func() { + os.Setenv("CNI_COMMAND", "DEL") + os.Setenv("CNI_IFNAME", "eth0") + os.Setenv("CNI_CONTAINERID", "id") + os.Setenv("CNI_ARGS", "args") + os.Setenv("CNI_NETNS", "testns") + os.Setenv("CNI_PATH", "testpath") + }) + + It("places the CNI environment variables in the end to be prepended", func() { args := invoke.Args{ Command: "ADD", ContainerID: "some-container-id", @@ -37,24 +46,94 @@ IfName: "eth7", Path: "/some/cni/path", } - const numCNIEnvVars = 6 - latentVars := os.Environ() + latentEnvs := os.Environ() + numLatentEnvs := len(latentEnvs) + + cniEnvs := args.AsEnv() + Expect(len(cniEnvs)).To(Equal(numLatentEnvs)) + + Expect(inStringSlice("CNI_COMMAND=ADD", cniEnvs)).To(Equal(true)) + Expect(inStringSlice("CNI_IFNAME=eth7", cniEnvs)).To(Equal(true)) + Expect(inStringSlice("CNI_CONTAINERID=some-container-id", cniEnvs)).To(Equal(true)) + Expect(inStringSlice("CNI_NETNS=/some/netns/path", cniEnvs)).To(Equal(true)) + Expect(inStringSlice("CNI_ARGS=KEY1=VALUE1;KEY2=VALUE2", cniEnvs)).To(Equal(true)) + Expect(inStringSlice("CNI_PATH=/some/cni/path", cniEnvs)).To(Equal(true)) + + Expect(inStringSlice("CNI_COMMAND=DEL", cniEnvs)).To(Equal(false)) + Expect(inStringSlice("CNI_IFNAME=eth0", cniEnvs)).To(Equal(false)) + Expect(inStringSlice("CNI_CONTAINERID=id", cniEnvs)).To(Equal(false)) + Expect(inStringSlice("CNI_NETNS=testns", cniEnvs)).To(Equal(false)) + Expect(inStringSlice("CNI_ARGS=args", cniEnvs)).To(Equal(false)) + Expect(inStringSlice("CNI_PATH=testpath", cniEnvs)).To(Equal(false)) + }) + + AfterEach(func() { + os.Unsetenv("CNI_COMMAND") + os.Unsetenv("CNI_IFNAME") + os.Unsetenv("CNI_CONTAINERID") + os.Unsetenv("CNI_ARGS") + os.Unsetenv("CNI_NETNS") + os.Unsetenv("CNI_PATH") + }) + }) + + Describe("DelegateArgs AsEnv", func() { + BeforeEach(func() { + os.Unsetenv("CNI_COMMAND") + }) - cniEnv := args.AsEnv() - Expect(cniEnv).To(HaveLen(len(latentVars) + numCNIEnvVars)) - Expect(cniEnv[0:numCNIEnvVars]).To(Equal([]string{ - "CNI_COMMAND=ADD", - "CNI_CONTAINERID=some-container-id", - "CNI_NETNS=/some/netns/path", - "CNI_ARGS=KEY1=VALUE1;KEY2=VALUE2", - "CNI_IFNAME=eth7", - "CNI_PATH=/some/cni/path", - })) + It("override CNI_COMMAND if it already exists in environment variables", func() { + os.Setenv("CNI_COMMAND", "DEL") - for i := range latentVars { - Expect(cniEnv[numCNIEnvVars+i]).To(Equal(latentVars[i])) + delegateArgs := invoke.DelegateArgs{ + Command: "ADD", } + + latentEnvs := os.Environ() + numLatentEnvs := len(latentEnvs) + + cniEnvs := delegateArgs.AsEnv() + Expect(len(cniEnvs)).To(Equal(numLatentEnvs)) + + Expect(inStringSlice("CNI_COMMAND=ADD", cniEnvs)).To(Equal(true)) + Expect(inStringSlice("CNI_COMMAND=DEL", cniEnvs)).To(Equal(false)) + }) + + It("append CNI_COMMAND if it does not exist in environment variables", func() { + delegateArgs := invoke.DelegateArgs{ + Command: "ADD", + } + + latentEnvs := os.Environ() + numLatentEnvs := len(latentEnvs) + + cniEnvs := delegateArgs.AsEnv() + Expect(len(cniEnvs)).To(Equal(numLatentEnvs + 1)) + + Expect(inStringSlice("CNI_COMMAND=ADD", cniEnvs)).To(Equal(true)) + }) + + AfterEach(func() { + os.Unsetenv("CNI_COMMAND") + }) + }) + + Describe("inherited AsEnv", func() { + It("return nil string slice if we call AsEnv of inherited", func() { + inheritedArgs := invoke.ArgsFromEnv() + + var nilSlice []string = nil + Expect(inheritedArgs.AsEnv()).To(Equal(nilSlice)) }) }) }) + +func inStringSlice(in string, slice []string) bool { + for _, s := range slice { + if in == s { + return true + } + } + return false +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/pkg/invoke/delegate.go new/cni-0.7.1/pkg/invoke/delegate.go --- old/cni-0.7.0/pkg/invoke/delegate.go 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/pkg/invoke/delegate.go 2019-06-05 17:31:12.000000000 +0200 @@ -16,22 +16,17 @@ import ( "context" - "fmt" "os" "path/filepath" "github.com/containernetworking/cni/pkg/types" ) -func delegateCommon(expectedCommand, delegatePlugin string, exec Exec) (string, Exec, error) { +func delegateCommon(delegatePlugin string, exec Exec) (string, Exec, error) { if exec == nil { exec = defaultExec } - if os.Getenv("CNI_COMMAND") != expectedCommand { - return "", nil, fmt.Errorf("CNI_COMMAND is not " + expectedCommand) - } - paths := filepath.SplitList(os.Getenv("CNI_PATH")) pluginPath, err := exec.FindInPath(delegatePlugin, paths) if err != nil { @@ -44,32 +39,42 @@ // DelegateAdd calls the given delegate plugin with the CNI ADD action and // JSON configuration func DelegateAdd(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) (types.Result, error) { - pluginPath, realExec, err := delegateCommon("ADD", delegatePlugin, exec) + pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) if err != nil { return nil, err } - return ExecPluginWithResult(ctx, pluginPath, netconf, ArgsFromEnv(), realExec) + // DelegateAdd will override the original "CNI_COMMAND" env from process with ADD + return ExecPluginWithResult(ctx, pluginPath, netconf, delegateArgs("ADD"), realExec) } // DelegateCheck calls the given delegate plugin with the CNI CHECK action and // JSON configuration func DelegateCheck(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error { - pluginPath, realExec, err := delegateCommon("CHECK", delegatePlugin, exec) + pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) if err != nil { return err } - return ExecPluginWithoutResult(ctx, pluginPath, netconf, ArgsFromEnv(), realExec) + // DelegateCheck will override the original CNI_COMMAND env from process with CHECK + return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("CHECK"), realExec) } // DelegateDel calls the given delegate plugin with the CNI DEL action and // JSON configuration func DelegateDel(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error { - pluginPath, realExec, err := delegateCommon("DEL", delegatePlugin, exec) + pluginPath, realExec, err := delegateCommon(delegatePlugin, exec) if err != nil { return err } - return ExecPluginWithoutResult(ctx, pluginPath, netconf, ArgsFromEnv(), realExec) + // DelegateDel will override the original CNI_COMMAND env from process with DEL + return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("DEL"), realExec) +} + +// return CNIArgs used by delegation +func delegateArgs(action string) *DelegateArgs { + return &DelegateArgs{ + Command: action, + } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/pkg/invoke/delegate_test.go new/cni-0.7.1/pkg/invoke/delegate_test.go --- old/cni-0.7.0/pkg/invoke/delegate_test.go 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/pkg/invoke/delegate_test.go 2019-06-05 17:31:12.000000000 +0200 @@ -101,14 +101,23 @@ Expect(pluginInvocation.CmdArgs.IfName).To(Equal("eth7")) }) - Context("if the delegation isn't part of an existing ADD command", func() { + Context("if the ADD delegation runs on an existing non-ADD command, ", func() { BeforeEach(func() { os.Setenv("CNI_COMMAND", "NOPE") }) It("aborts and returns a useful error", func() { - _, err := invoke.DelegateAdd(ctx, pluginName, netConf, nil) - Expect(err).To(MatchError("CNI_COMMAND is not ADD")) + result, err := invoke.DelegateAdd(ctx, pluginName, netConf, nil) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(Equal(expectedResult)) + + pluginInvocation, err := debug.ReadDebug(debugFileName) + Expect(err).NotTo(HaveOccurred()) + Expect(pluginInvocation.Command).To(Equal("ADD")) + Expect(pluginInvocation.CmdArgs.IfName).To(Equal("eth7")) + + // check the original env + Expect(os.Getenv("CNI_COMMAND")).To(Equal("NOPE")) }) }) @@ -139,14 +148,22 @@ Expect(pluginInvocation.CmdArgs.IfName).To(Equal("eth7")) }) - Context("if the delegation isn't part of an existing CHECK command", func() { + Context("if the CHECK delegation runs on an existing non-CHECK command", func() { BeforeEach(func() { os.Setenv("CNI_COMMAND", "NOPE") }) It("aborts and returns a useful error", func() { err := invoke.DelegateCheck(ctx, pluginName, netConf, nil) - Expect(err).To(MatchError("CNI_COMMAND is not CHECK")) + Expect(err).NotTo(HaveOccurred()) + + pluginInvocation, err := debug.ReadDebug(debugFileName) + Expect(err).NotTo(HaveOccurred()) + Expect(pluginInvocation.Command).To(Equal("CHECK")) + Expect(pluginInvocation.CmdArgs.IfName).To(Equal("eth7")) + + // check the original env + Expect(os.Getenv("CNI_COMMAND")).To(Equal("NOPE")) }) }) @@ -177,14 +194,22 @@ Expect(pluginInvocation.CmdArgs.IfName).To(Equal("eth7")) }) - Context("if the delegation isn't part of an existing DEL command", func() { + Context("if the DEL delegation runs on an existing non-DEL command", func() { BeforeEach(func() { os.Setenv("CNI_COMMAND", "NOPE") }) It("aborts and returns a useful error", func() { err := invoke.DelegateDel(ctx, pluginName, netConf, nil) - Expect(err).To(MatchError("CNI_COMMAND is not DEL")) + Expect(err).NotTo(HaveOccurred()) + + pluginInvocation, err := debug.ReadDebug(debugFileName) + Expect(err).NotTo(HaveOccurred()) + Expect(pluginInvocation.Command).To(Equal("DEL")) + Expect(pluginInvocation.CmdArgs.IfName).To(Equal("eth7")) + + // check the original env + Expect(os.Getenv("CNI_COMMAND")).To(Equal("NOPE")) }) }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cni-0.7.0/scripts/release.sh new/cni-0.7.1/scripts/release.sh --- old/cni-0.7.0/scripts/release.sh 2019-04-26 18:00:55.000000000 +0200 +++ new/cni-0.7.1/scripts/release.sh 2019-06-05 17:31:12.000000000 +0200 @@ -14,7 +14,7 @@ mkdir -p ${SRC_DIR}/${RELEASE_DIR} mkdir -p ${OUTPUT_DIR} -docker run -i -v ${SRC_DIR}:/opt/src --rm golang:1.8-alpine \ +docker run -i -v ${SRC_DIR}:/opt/src --rm golang:1.12-alpine \ /bin/sh -xe -c "\ apk --no-cache add bash tar; cd /opt/src; umask 0022;
