github.com/jk-he/cni@v0.8.1/pkg/invoke/raw_exec_test.go (about) 1 // Copyright 2016 CNI authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package invoke_test 16 17 import ( 18 "bytes" 19 "context" 20 "io/ioutil" 21 "os" 22 23 "github.com/containernetworking/cni/pkg/invoke" 24 25 noop_debug "github.com/containernetworking/cni/plugins/test/noop/debug" 26 27 . "github.com/onsi/ginkgo" 28 . "github.com/onsi/gomega" 29 ) 30 31 var _ = Describe("RawExec", func() { 32 var ( 33 debugFileName string 34 debug *noop_debug.Debug 35 environ []string 36 stdin []byte 37 execer *invoke.RawExec 38 ctx context.Context 39 ) 40 41 const reportResult = `{ "some": "result" }` 42 43 BeforeEach(func() { 44 debugFile, err := ioutil.TempFile("", "cni_debug") 45 Expect(err).NotTo(HaveOccurred()) 46 Expect(debugFile.Close()).To(Succeed()) 47 debugFileName = debugFile.Name() 48 49 debug = &noop_debug.Debug{ 50 ReportResult: reportResult, 51 ReportStderr: "some stderr message", 52 } 53 Expect(debug.WriteDebug(debugFileName)).To(Succeed()) 54 55 environ = []string{ 56 "CNI_COMMAND=ADD", 57 "CNI_CONTAINERID=some-container-id", 58 "CNI_ARGS=DEBUG=" + debugFileName, 59 "CNI_NETNS=/some/netns/path", 60 "CNI_PATH=/some/bin/path", 61 "CNI_IFNAME=some-eth0", 62 } 63 stdin = []byte(`{"name": "raw-exec-test", "some":"stdin-json", "cniVersion": "0.3.1"}`) 64 execer = &invoke.RawExec{} 65 ctx = context.TODO() 66 }) 67 68 AfterEach(func() { 69 Expect(os.Remove(debugFileName)).To(Succeed()) 70 }) 71 72 It("runs the plugin with the given stdin and environment", func() { 73 _, err := execer.ExecPlugin(ctx, pathToPlugin, stdin, environ) 74 Expect(err).NotTo(HaveOccurred()) 75 76 debug, err := noop_debug.ReadDebug(debugFileName) 77 Expect(err).NotTo(HaveOccurred()) 78 Expect(debug.Command).To(Equal("ADD")) 79 Expect(debug.CmdArgs.StdinData).To(Equal(stdin)) 80 Expect(debug.CmdArgs.Netns).To(Equal("/some/netns/path")) 81 }) 82 83 It("returns the resulting stdout as bytes", func() { 84 resultBytes, err := execer.ExecPlugin(ctx, pathToPlugin, stdin, environ) 85 Expect(err).NotTo(HaveOccurred()) 86 87 Expect(resultBytes).To(BeEquivalentTo(reportResult)) 88 }) 89 90 Context("when the Stderr writer is set", func() { 91 var stderrBuffer *bytes.Buffer 92 93 BeforeEach(func() { 94 stderrBuffer = &bytes.Buffer{} 95 execer.Stderr = stderrBuffer 96 }) 97 98 It("forwards any stderr bytes to the Stderr writer", func() { 99 _, err := execer.ExecPlugin(ctx, pathToPlugin, stdin, environ) 100 Expect(err).NotTo(HaveOccurred()) 101 102 Expect(stderrBuffer.String()).To(Equal("some stderr message")) 103 }) 104 }) 105 106 Context("when the plugin errors", func() { 107 BeforeEach(func() { 108 debug.ReportResult = "" 109 }) 110 111 Context("and writes valid error JSON to stdout", func() { 112 It("wraps and returns the error", func() { 113 debug.ReportError = "banana" 114 Expect(debug.WriteDebug(debugFileName)).To(Succeed()) 115 _, err := execer.ExecPlugin(ctx, pathToPlugin, stdin, environ) 116 Expect(err).To(HaveOccurred()) 117 Expect(err).To(MatchError("banana")) 118 }) 119 }) 120 121 Context("and writes to stderr", func() { 122 It("returns an error message with stderr output", func() { 123 debug.ExitWithCode = 1 124 Expect(debug.WriteDebug(debugFileName)).To(Succeed()) 125 _, err := execer.ExecPlugin(ctx, pathToPlugin, stdin, environ) 126 Expect(err).To(HaveOccurred()) 127 Expect(err).To(MatchError(`netplugin failed: "some stderr message"`)) 128 }) 129 }) 130 }) 131 132 Context("when the plugin errors with no output on stdout or stderr", func() { 133 It("returns the exec error message", func() { 134 debug.ExitWithCode = 1 135 debug.ReportResult = "" 136 debug.ReportStderr = "" 137 Expect(debug.WriteDebug(debugFileName)).To(Succeed()) 138 _, err := execer.ExecPlugin(ctx, pathToPlugin, stdin, environ) 139 Expect(err).To(HaveOccurred()) 140 Expect(err).To(MatchError("netplugin failed with no error message: exit status 1")) 141 }) 142 }) 143 144 Context("when the system is unable to execute the plugin", func() { 145 It("returns the error", func() { 146 _, err := execer.ExecPlugin(ctx, "/tmp/some/invalid/plugin/path", stdin, environ) 147 Expect(err).To(HaveOccurred()) 148 Expect(err).To(MatchError(ContainSubstring("/tmp/some/invalid/plugin/path"))) 149 }) 150 }) 151 })