github.com/jk-he/cni@v0.8.1/pkg/types/current/types_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 current_test 16 17 import ( 18 "encoding/json" 19 "github.com/containernetworking/cni/pkg/types/020" 20 "io/ioutil" 21 "net" 22 "os" 23 24 "github.com/containernetworking/cni/pkg/types" 25 "github.com/containernetworking/cni/pkg/types/current" 26 27 . "github.com/onsi/ginkgo" 28 . "github.com/onsi/gomega" 29 ) 30 31 func testResult() *current.Result { 32 ipv4, err := types.ParseCIDR("1.2.3.30/24") 33 Expect(err).NotTo(HaveOccurred()) 34 Expect(ipv4).NotTo(BeNil()) 35 36 routegwv4, routev4, err := net.ParseCIDR("15.5.6.8/24") 37 Expect(err).NotTo(HaveOccurred()) 38 Expect(routev4).NotTo(BeNil()) 39 Expect(routegwv4).NotTo(BeNil()) 40 41 ipv6, err := types.ParseCIDR("abcd:1234:ffff::cdde/64") 42 Expect(err).NotTo(HaveOccurred()) 43 Expect(ipv6).NotTo(BeNil()) 44 45 routegwv6, routev6, err := net.ParseCIDR("1111:dddd::aaaa/80") 46 Expect(err).NotTo(HaveOccurred()) 47 Expect(routev6).NotTo(BeNil()) 48 Expect(routegwv6).NotTo(BeNil()) 49 50 // Set every field of the struct to ensure source compatibility 51 return ¤t.Result{ 52 CNIVersion: "0.3.1", 53 Interfaces: []*current.Interface{ 54 { 55 Name: "eth0", 56 Mac: "00:11:22:33:44:55", 57 Sandbox: "/proc/3553/ns/net", 58 }, 59 }, 60 IPs: []*current.IPConfig{ 61 { 62 Version: "4", 63 Interface: current.Int(0), 64 Address: *ipv4, 65 Gateway: net.ParseIP("1.2.3.1"), 66 }, 67 { 68 Version: "6", 69 Interface: current.Int(0), 70 Address: *ipv6, 71 Gateway: net.ParseIP("abcd:1234:ffff::1"), 72 }, 73 }, 74 Routes: []*types.Route{ 75 {Dst: *routev4, GW: routegwv4}, 76 {Dst: *routev6, GW: routegwv6}, 77 }, 78 DNS: types.DNS{ 79 Nameservers: []string{"1.2.3.4", "1::cafe"}, 80 Domain: "acompany.com", 81 Search: []string{"somedomain.com", "otherdomain.net"}, 82 Options: []string{"foo", "bar"}, 83 }, 84 } 85 } 86 87 var _ = Describe("Current types operations", func() { 88 It("correctly encodes a 0.3.x Result", func() { 89 res := testResult() 90 91 // Redirect stdout to capture JSON result 92 oldStdout := os.Stdout 93 r, w, err := os.Pipe() 94 Expect(err).NotTo(HaveOccurred()) 95 96 os.Stdout = w 97 err = res.Print() 98 w.Close() 99 Expect(err).NotTo(HaveOccurred()) 100 101 // parse the result 102 out, err := ioutil.ReadAll(r) 103 os.Stdout = oldStdout 104 Expect(err).NotTo(HaveOccurred()) 105 106 Expect(string(out)).To(MatchJSON(`{ 107 "cniVersion": "0.3.1", 108 "interfaces": [ 109 { 110 "name": "eth0", 111 "mac": "00:11:22:33:44:55", 112 "sandbox": "/proc/3553/ns/net" 113 } 114 ], 115 "ips": [ 116 { 117 "version": "4", 118 "interface": 0, 119 "address": "1.2.3.30/24", 120 "gateway": "1.2.3.1" 121 }, 122 { 123 "version": "6", 124 "interface": 0, 125 "address": "abcd:1234:ffff::cdde/64", 126 "gateway": "abcd:1234:ffff::1" 127 } 128 ], 129 "routes": [ 130 { 131 "dst": "15.5.6.0/24", 132 "gw": "15.5.6.8" 133 }, 134 { 135 "dst": "1111:dddd::/80", 136 "gw": "1111:dddd::aaaa" 137 } 138 ], 139 "dns": { 140 "nameservers": [ 141 "1.2.3.4", 142 "1::cafe" 143 ], 144 "domain": "acompany.com", 145 "search": [ 146 "somedomain.com", 147 "otherdomain.net" 148 ], 149 "options": [ 150 "foo", 151 "bar" 152 ] 153 } 154 }`)) 155 }) 156 157 It("correctly encodes a 0.1.0 Result", func() { 158 res, err := testResult().GetAsVersion("0.1.0") 159 Expect(err).NotTo(HaveOccurred()) 160 161 // Redirect stdout to capture JSON result 162 oldStdout := os.Stdout 163 r, w, err := os.Pipe() 164 Expect(err).NotTo(HaveOccurred()) 165 166 os.Stdout = w 167 err = res.Print() 168 w.Close() 169 Expect(err).NotTo(HaveOccurred()) 170 171 // parse the result 172 out, err := ioutil.ReadAll(r) 173 os.Stdout = oldStdout 174 Expect(err).NotTo(HaveOccurred()) 175 176 Expect(string(out)).To(MatchJSON(`{ 177 "cniVersion": "0.2.0", 178 "ip4": { 179 "ip": "1.2.3.30/24", 180 "gateway": "1.2.3.1", 181 "routes": [ 182 { 183 "dst": "15.5.6.0/24", 184 "gw": "15.5.6.8" 185 } 186 ] 187 }, 188 "ip6": { 189 "ip": "abcd:1234:ffff::cdde/64", 190 "gateway": "abcd:1234:ffff::1", 191 "routes": [ 192 { 193 "dst": "1111:dddd::/80", 194 "gw": "1111:dddd::aaaa" 195 } 196 ] 197 }, 198 "dns": { 199 "nameservers": [ 200 "1.2.3.4", 201 "1::cafe" 202 ], 203 "domain": "acompany.com", 204 "search": [ 205 "somedomain.com", 206 "otherdomain.net" 207 ], 208 "options": [ 209 "foo", 210 "bar" 211 ] 212 } 213 }`)) 214 }) 215 216 It("correctly round-trips a 0.2.0 Result with route gateways", func() { 217 ipv4, err := types.ParseCIDR("1.2.3.30/24") 218 Expect(err).NotTo(HaveOccurred()) 219 Expect(ipv4).NotTo(BeNil()) 220 221 routegwv4, routev4, err := net.ParseCIDR("15.5.6.8/24") 222 Expect(err).NotTo(HaveOccurred()) 223 Expect(routev4).NotTo(BeNil()) 224 Expect(routegwv4).NotTo(BeNil()) 225 226 ipv6, err := types.ParseCIDR("abcd:1234:ffff::cdde/64") 227 Expect(err).NotTo(HaveOccurred()) 228 Expect(ipv6).NotTo(BeNil()) 229 230 routegwv6, routev6, err := net.ParseCIDR("1111:dddd::aaaa/80") 231 Expect(err).NotTo(HaveOccurred()) 232 Expect(routev6).NotTo(BeNil()) 233 Expect(routegwv6).NotTo(BeNil()) 234 235 // Set every field of the struct to ensure source compatibility 236 res := &types020.Result{ 237 CNIVersion: types020.ImplementedSpecVersion, 238 IP4: &types020.IPConfig{ 239 IP: *ipv4, 240 Gateway: net.ParseIP("1.2.3.1"), 241 Routes: []types.Route{ 242 {Dst: *routev4, GW: routegwv4}, 243 }, 244 }, 245 IP6: &types020.IPConfig{ 246 IP: *ipv6, 247 Gateway: net.ParseIP("abcd:1234:ffff::1"), 248 Routes: []types.Route{ 249 {Dst: *routev6, GW: routegwv6}, 250 }, 251 }, 252 DNS: types.DNS{ 253 Nameservers: []string{"1.2.3.4", "1::cafe"}, 254 Domain: "acompany.com", 255 Search: []string{"somedomain.com", "otherdomain.net"}, 256 Options: []string{"foo", "bar"}, 257 }, 258 } 259 260 // Convert to current 261 newRes, err := current.NewResultFromResult(res) 262 Expect(err).NotTo(HaveOccurred()) 263 // Convert back to 0.2.0 264 oldRes, err := newRes.GetAsVersion("0.2.0") 265 Expect(err).NotTo(HaveOccurred()) 266 267 // Match JSON so we can figure out what's wrong if something fails the test 268 origJson, err := json.Marshal(res) 269 Expect(err).NotTo(HaveOccurred()) 270 oldJson, err := json.Marshal(oldRes) 271 Expect(err).NotTo(HaveOccurred()) 272 Expect(oldJson).To(MatchJSON(origJson)) 273 }) 274 275 It("correctly round-trips a 0.2.0 Result without route gateways", func() { 276 ipv4, err := types.ParseCIDR("1.2.3.30/24") 277 Expect(err).NotTo(HaveOccurred()) 278 Expect(ipv4).NotTo(BeNil()) 279 280 _, routev4, err := net.ParseCIDR("15.5.6.0/24") 281 Expect(err).NotTo(HaveOccurred()) 282 Expect(routev4).NotTo(BeNil()) 283 284 ipv6, err := types.ParseCIDR("abcd:1234:ffff::cdde/64") 285 Expect(err).NotTo(HaveOccurred()) 286 Expect(ipv6).NotTo(BeNil()) 287 288 _, routev6, err := net.ParseCIDR("1111:dddd::aaaa/80") 289 Expect(err).NotTo(HaveOccurred()) 290 Expect(routev6).NotTo(BeNil()) 291 292 // Set every field of the struct to ensure source compatibility 293 res := &types020.Result{ 294 CNIVersion: types020.ImplementedSpecVersion, 295 IP4: &types020.IPConfig{ 296 IP: *ipv4, 297 Gateway: net.ParseIP("1.2.3.1"), 298 Routes: []types.Route{ 299 {Dst: *routev4}, 300 }, 301 }, 302 IP6: &types020.IPConfig{ 303 IP: *ipv6, 304 Gateway: net.ParseIP("abcd:1234:ffff::1"), 305 Routes: []types.Route{ 306 {Dst: *routev6}, 307 }, 308 }, 309 DNS: types.DNS{ 310 Nameservers: []string{"1.2.3.4", "1::cafe"}, 311 Domain: "acompany.com", 312 Search: []string{"somedomain.com", "otherdomain.net"}, 313 Options: []string{"foo", "bar"}, 314 }, 315 } 316 317 // Convert to current 318 newRes, err := current.NewResultFromResult(res) 319 Expect(err).NotTo(HaveOccurred()) 320 // Convert back to 0.2.0 321 oldRes, err := newRes.GetAsVersion("0.2.0") 322 Expect(err).NotTo(HaveOccurred()) 323 324 // Match JSON so we can figure out what's wrong if something fails the test 325 origJson, err := json.Marshal(res) 326 Expect(err).NotTo(HaveOccurred()) 327 oldJson, err := json.Marshal(oldRes) 328 Expect(err).NotTo(HaveOccurred()) 329 Expect(oldJson).To(MatchJSON(origJson)) 330 }) 331 332 It("correctly marshals and unmarshals interface index 0", func() { 333 ipc := ¤t.IPConfig{ 334 Version: "4", 335 Interface: current.Int(0), 336 Address: net.IPNet{ 337 IP: net.ParseIP("10.1.2.3"), 338 Mask: net.IPv4Mask(255, 255, 255, 0), 339 }, 340 } 341 342 jsonBytes, err := json.Marshal(ipc) 343 Expect(err).NotTo(HaveOccurred()) 344 Expect(jsonBytes).To(MatchJSON(`{ 345 "version": "4", 346 "interface": 0, 347 "address": "10.1.2.3/24" 348 }`)) 349 350 recovered := ¤t.IPConfig{} 351 Expect(json.Unmarshal(jsonBytes, &recovered)).To(Succeed()) 352 Expect(recovered).To(Equal(ipc)) 353 }) 354 355 Context("when unmarshalling json fails", func() { 356 It("returns an error", func() { 357 recovered := ¤t.IPConfig{} 358 err := json.Unmarshal([]byte(`{"address": 5}`), &recovered) 359 Expect(err).To(MatchError(HavePrefix("json: cannot unmarshal"))) 360 }) 361 }) 362 363 It("correctly marshals a missing interface index", func() { 364 ipc := ¤t.IPConfig{ 365 Version: "4", 366 Address: net.IPNet{ 367 IP: net.ParseIP("10.1.2.3"), 368 Mask: net.IPv4Mask(255, 255, 255, 0), 369 }, 370 } 371 372 json, err := json.Marshal(ipc) 373 Expect(err).NotTo(HaveOccurred()) 374 Expect(json).To(MatchJSON(`{ 375 "version": "4", 376 "address": "10.1.2.3/24" 377 }`)) 378 }) 379 })