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 &current.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 := &current.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 := &current.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 := &current.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 := &current.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  })