github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/rpc/params/network_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package params_test
     5  
     6  import (
     7  	"encoding/json"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/core/network"
    13  	"github.com/juju/juju/rpc/params"
    14  )
    15  
    16  type (
    17  	P struct {
    18  		prot string
    19  		num  int
    20  	}
    21  	IS []interface{}
    22  	M  map[string]interface{}
    23  )
    24  
    25  type NetworkSuite struct{}
    26  
    27  var _ = gc.Suite(&NetworkSuite{})
    28  
    29  func (s *NetworkSuite) TestPortsResults(c *gc.C) {
    30  	// Convenience helpers.
    31  	mkPortsResults := func(prs ...params.PortsResult) params.PortsResults {
    32  		return params.PortsResults{
    33  			Results: prs,
    34  		}
    35  	}
    36  	mkPortsResult := func(msg, code string, ports ...P) params.PortsResult {
    37  		pr := params.PortsResult{}
    38  		if msg != "" {
    39  			pr.Error = &params.Error{Message: msg, Code: code}
    40  		}
    41  		for _, p := range ports {
    42  			pr.Ports = append(pr.Ports, params.Port{p.prot, p.num})
    43  		}
    44  		return pr
    45  	}
    46  	mkResults := func(rs ...interface{}) M {
    47  		return M{"results": rs}
    48  	}
    49  	mkResult := func(err, ports interface{}) M {
    50  		result := M{"ports": ports}
    51  		if err != nil {
    52  			result["error"] = err
    53  		}
    54  		return result
    55  	}
    56  	mkError := func(msg, code string) M {
    57  		return M{"message": msg, "code": code}
    58  	}
    59  	mkPort := func(prot string, num int) M {
    60  		return M{"protocol": prot, "number": num}
    61  	}
    62  	// Tests.
    63  	tests := []struct {
    64  		about    string
    65  		results  params.PortsResults
    66  		expected M
    67  	}{{
    68  		about:    "empty result set",
    69  		results:  mkPortsResults(),
    70  		expected: mkResults(),
    71  	}, {
    72  		about: "one error",
    73  		results: mkPortsResults(
    74  			mkPortsResult("I failed", "ERR42")),
    75  		expected: mkResults(
    76  			mkResult(mkError("I failed", "ERR42"), nil)),
    77  	}, {
    78  		about: "one succes with one port",
    79  		results: mkPortsResults(
    80  			mkPortsResult("", "", P{"tcp", 80})),
    81  		expected: mkResults(
    82  			mkResult(nil, IS{mkPort("tcp", 80)})),
    83  	}, {
    84  		about: "two results, one error and one success with two ports",
    85  		results: mkPortsResults(
    86  			mkPortsResult("I failed", "ERR42"),
    87  			mkPortsResult("", "", P{"tcp", 80}, P{"tcp", 443})),
    88  		expected: mkResults(
    89  			mkResult(mkError("I failed", "ERR42"), nil),
    90  			mkResult(nil, IS{mkPort("tcp", 80), mkPort("tcp", 443)})),
    91  	}}
    92  	for i, test := range tests {
    93  		c.Logf("\ntest %d: %s", i, test.about)
    94  		output, err := json.Marshal(test.results)
    95  		if !c.Check(err, jc.ErrorIsNil) {
    96  			continue
    97  		}
    98  		c.Logf("\nJSON output:\n%v", string(output))
    99  		c.Check(string(output), jc.JSONEquals, test.expected)
   100  	}
   101  }
   102  
   103  func (s *NetworkSuite) TestHostPort(c *gc.C) {
   104  	mkHostPort := func(v, t, s string, p int) M {
   105  		return M{
   106  			"value": v,
   107  			"type":  t,
   108  			"scope": s,
   109  			"port":  p,
   110  		}
   111  	}
   112  	tests := []struct {
   113  		about    string
   114  		hostPort params.HostPort
   115  		expected M
   116  	}{{
   117  		about: "address only value; port is 1234",
   118  		hostPort: params.HostPort{
   119  			Address: params.Address{
   120  				Value: "foo",
   121  			},
   122  			Port: 1234,
   123  		},
   124  		expected: mkHostPort("foo", "", "", 1234),
   125  	}, {
   126  		about: "address value and type; port is 1234",
   127  		hostPort: params.HostPort{
   128  			Address: params.Address{
   129  				Value: "foo",
   130  				Type:  "ipv4",
   131  			},
   132  			Port: 1234,
   133  		},
   134  		expected: mkHostPort("foo", "ipv4", "", 1234),
   135  	}, {
   136  		about: "address value, type, and network name, port is 1234",
   137  		hostPort: params.HostPort{
   138  			Address: params.Address{
   139  				Value: "foo",
   140  				Type:  "ipv4",
   141  			},
   142  			Port: 1234,
   143  		},
   144  		expected: mkHostPort("foo", "ipv4", "", 1234),
   145  	}, {
   146  		about: "address all fields, port is 1234",
   147  		hostPort: params.HostPort{
   148  			Address: params.Address{
   149  				Value: "foo",
   150  				Type:  "ipv4",
   151  				Scope: "public",
   152  			},
   153  			Port: 1234,
   154  		},
   155  		expected: mkHostPort("foo", "ipv4", "public", 1234),
   156  	}, {
   157  		about: "address all fields, port is 0",
   158  		hostPort: params.HostPort{
   159  			Address: params.Address{
   160  				Value: "foo",
   161  				Type:  "ipv4",
   162  				Scope: "public",
   163  			},
   164  			Port: 0,
   165  		},
   166  		expected: mkHostPort("foo", "ipv4", "public", 0),
   167  	}}
   168  	for i, test := range tests {
   169  		c.Logf("\ntest %d: %s", i, test.about)
   170  		output, err := json.Marshal(test.hostPort)
   171  		if !c.Check(err, jc.ErrorIsNil) {
   172  			continue
   173  		}
   174  		c.Logf("\nJSON output:\n%v", string(output))
   175  		c.Check(string(output), jc.JSONEquals, test.expected)
   176  	}
   177  }
   178  
   179  func (s *NetworkSuite) TestMachinePortRange(c *gc.C) {
   180  	mkPortRange := func(u, r string, f, t int, p string) M {
   181  		return M{
   182  			"unit-tag":     u,
   183  			"relation-tag": r,
   184  			"port-range": M{
   185  				"from-port": f,
   186  				"to-port":   t,
   187  				"protocol":  p,
   188  			},
   189  		}
   190  	}
   191  	tests := []struct {
   192  		about            string
   193  		machinePortRange params.MachinePortRange
   194  		expected         M
   195  	}{{
   196  		about: "all values",
   197  		machinePortRange: params.MachinePortRange{
   198  			UnitTag:     "foo/0",
   199  			RelationTag: "foo.db#bar.server",
   200  			PortRange: params.PortRange{
   201  				FromPort: 100,
   202  				ToPort:   200,
   203  				Protocol: "tcp",
   204  			},
   205  		},
   206  		expected: mkPortRange("foo/0", "foo.db#bar.server", 100, 200, "tcp"),
   207  	}, {
   208  		about: "only port range, missing from",
   209  		machinePortRange: params.MachinePortRange{
   210  			PortRange: params.PortRange{
   211  				ToPort:   200,
   212  				Protocol: "tcp",
   213  			},
   214  		},
   215  		expected: mkPortRange("", "", 0, 200, "tcp"),
   216  	}, {
   217  		about: "only port range, missing to",
   218  		machinePortRange: params.MachinePortRange{
   219  			PortRange: params.PortRange{
   220  				FromPort: 100,
   221  				Protocol: "tcp",
   222  			},
   223  		},
   224  		expected: mkPortRange("", "", 100, 0, "tcp"),
   225  	}, {
   226  		about: "only port range, missing protocol",
   227  		machinePortRange: params.MachinePortRange{
   228  			PortRange: params.PortRange{
   229  				FromPort: 100,
   230  				ToPort:   200,
   231  			},
   232  		},
   233  		expected: mkPortRange("", "", 100, 200, ""),
   234  	}, {
   235  		about:            "no field values",
   236  		machinePortRange: params.MachinePortRange{},
   237  		expected:         mkPortRange("", "", 0, 0, ""),
   238  	}}
   239  	for i, test := range tests {
   240  		c.Logf("\ntest %d: %s", i, test.about)
   241  		output, err := json.Marshal(test.machinePortRange)
   242  		if !c.Check(err, jc.ErrorIsNil) {
   243  			continue
   244  		}
   245  		c.Logf("\nJSON output:\n%v", string(output))
   246  		c.Check(string(output), jc.JSONEquals, test.expected)
   247  	}
   248  }
   249  
   250  func (s *NetworkSuite) TestPortRangeConvenience(c *gc.C) {
   251  	networkPortRange := network.PortRange{
   252  		FromPort: 61001,
   253  		ToPort:   61010,
   254  		Protocol: "tcp",
   255  	}
   256  	paramsPortRange := params.FromNetworkPortRange(networkPortRange)
   257  	networkPortRangeBack := paramsPortRange.NetworkPortRange()
   258  	c.Assert(networkPortRange, jc.DeepEquals, networkPortRangeBack)
   259  }
   260  
   261  func (s *NetworkSuite) TestProviderAddressConversion(c *gc.C) {
   262  	pAddrs := network.ProviderAddresses{
   263  		network.NewMachineAddress("1.2.3.4", network.WithScope(network.ScopeCloudLocal), network.WithCIDR("1.2.3.0/24")).AsProviderAddress(),
   264  		network.NewMachineAddress("1.2.3.5", network.WithScope(network.ScopeCloudLocal), network.WithSecondary(true)).AsProviderAddress(),
   265  		network.NewMachineAddress("2.3.4.5", network.WithScope(network.ScopePublic), network.WithConfigType("dhcp")).AsProviderAddress(),
   266  	}
   267  	pAddrs[0].SpaceName = "test-space"
   268  	pAddrs[0].ProviderSpaceID = "666"
   269  
   270  	addrs := params.FromProviderAddresses(pAddrs...)
   271  	c.Assert(params.ToProviderAddresses(addrs...), jc.DeepEquals, pAddrs)
   272  }
   273  
   274  func (s *NetworkSuite) TestMachineAddressConversion(c *gc.C) {
   275  	mAddrs := []network.MachineAddress{
   276  		network.NewMachineAddress("1.2.3.4", network.WithScope(network.ScopeCloudLocal), network.WithCIDR("1.2.3.0/24")),
   277  		network.NewMachineAddress("1.2.3.5", network.WithScope(network.ScopeCloudLocal), network.WithSecondary(true)),
   278  		network.NewMachineAddress("2.3.4.5", network.WithScope(network.ScopePublic), network.WithConfigType("dhcp")),
   279  	}
   280  
   281  	exp := []params.Address{
   282  		{Value: "1.2.3.4", Scope: string(network.ScopeCloudLocal), Type: string(network.IPv4Address), CIDR: "1.2.3.0/24"},
   283  		{Value: "1.2.3.5", Scope: string(network.ScopeCloudLocal), Type: string(network.IPv4Address), IsSecondary: true},
   284  		{Value: "2.3.4.5", Scope: string(network.ScopePublic), Type: string(network.IPv4Address), ConfigType: "dhcp"},
   285  	}
   286  	c.Assert(params.FromMachineAddresses(mAddrs...), jc.DeepEquals, exp)
   287  }
   288  
   289  func (s *NetworkSuite) TestProviderHostPortConversion(c *gc.C) {
   290  	pHPs := []network.ProviderHostPorts{
   291  		{
   292  			{
   293  				ProviderAddress: network.NewMachineAddress("1.2.3.4", network.WithScope(network.ScopeCloudLocal)).AsProviderAddress(),
   294  				NetPort:         1234,
   295  			},
   296  			{
   297  				ProviderAddress: network.NewMachineAddress("2.3.4.5", network.WithScope(network.ScopePublic)).AsProviderAddress(),
   298  				NetPort:         2345,
   299  			},
   300  		},
   301  		{
   302  			{
   303  				ProviderAddress: network.NewMachineAddress("3.4.5.6", network.WithScope(network.ScopeCloudLocal)).AsProviderAddress(),
   304  				NetPort:         3456,
   305  			},
   306  		},
   307  	}
   308  	pHPs[0][0].SpaceName = "test-space"
   309  	pHPs[0][0].ProviderSpaceID = "666"
   310  
   311  	hps := params.FromProviderHostsPorts(pHPs)
   312  	c.Assert(params.ToProviderHostsPorts(hps), jc.DeepEquals, pHPs)
   313  }
   314  
   315  func (s *NetworkSuite) TestMachineHostPortConversion(c *gc.C) {
   316  	hps := [][]params.HostPort{
   317  		{
   318  			{
   319  				Address: params.Address{
   320  					Value: "1.2.3.4",
   321  					Scope: string(network.ScopeCloudLocal),
   322  					Type:  string(network.IPv4Address),
   323  				},
   324  				Port: 1234,
   325  			},
   326  			{
   327  				Address: params.Address{
   328  					Value: "2.3.4.5",
   329  					Scope: string(network.ScopePublic),
   330  					Type:  string(network.IPv4Address),
   331  				},
   332  				Port: 2345,
   333  			},
   334  		},
   335  		{
   336  			{
   337  				Address: params.Address{
   338  					Value: "3.4.5.6",
   339  					Scope: string(network.ScopeCloudLocal),
   340  					Type:  string(network.IPv4Address),
   341  				},
   342  				Port: 3456,
   343  			},
   344  		},
   345  	}
   346  
   347  	exp := []network.MachineHostPorts{
   348  		{
   349  			{
   350  				MachineAddress: network.NewMachineAddress("1.2.3.4", network.WithScope(network.ScopeCloudLocal)),
   351  				NetPort:        1234,
   352  			},
   353  			{
   354  				MachineAddress: network.NewMachineAddress("2.3.4.5", network.WithScope(network.ScopePublic)),
   355  				NetPort:        2345,
   356  			},
   357  		},
   358  		{
   359  			{
   360  				MachineAddress: network.NewMachineAddress("3.4.5.6", network.WithScope(network.ScopeCloudLocal)),
   361  				NetPort:        3456,
   362  			},
   363  		},
   364  	}
   365  
   366  	c.Assert(params.ToMachineHostsPorts(hps), jc.DeepEquals, exp)
   367  }
   368  
   369  func (s *NetworkSuite) TestHostPortConversion(c *gc.C) {
   370  	mHPs := []network.MachineHostPorts{
   371  		{
   372  			{
   373  				MachineAddress: network.NewMachineAddress("1.2.3.4", network.WithScope(network.ScopeCloudLocal)),
   374  				NetPort:        1234,
   375  			},
   376  			{
   377  				MachineAddress: network.NewMachineAddress("2.3.4.5", network.WithScope(network.ScopePublic)),
   378  				NetPort:        2345,
   379  			},
   380  		},
   381  		{
   382  			{
   383  				MachineAddress: network.NewMachineAddress("3.4.5.6", network.WithScope(network.ScopeCloudLocal)),
   384  				NetPort:        3456,
   385  			},
   386  		},
   387  	}
   388  
   389  	hps := make([]network.HostPorts, len(mHPs))
   390  	for i, mHP := range mHPs {
   391  		hps[i] = mHP.HostPorts()
   392  	}
   393  
   394  	pHPs := params.FromHostsPorts(hps)
   395  	c.Assert(params.ToMachineHostsPorts(pHPs), jc.DeepEquals, mHPs)
   396  }
   397  
   398  func (s *NetworkSuite) TestSetNetworkConfigBackFillMachineOrigin(c *gc.C) {
   399  	cfg := params.SetMachineNetworkConfig{
   400  		Tag: "machine-0",
   401  		Config: []params.NetworkConfig{
   402  			{
   403  				ProviderId: "1",
   404  				// This would not happen in the wild, but serves to
   405  				// differentiate from the back-filled entries.
   406  				NetworkOrigin: params.NetworkOrigin(network.OriginProvider),
   407  			},
   408  			{ProviderId: "2"},
   409  			{ProviderId: "3"},
   410  		},
   411  	}
   412  
   413  	cfg.BackFillMachineOrigin()
   414  	c.Assert(cfg.Config, gc.DeepEquals, []params.NetworkConfig{
   415  		{
   416  			ProviderId:    "1",
   417  			NetworkOrigin: params.NetworkOrigin(network.OriginProvider),
   418  		},
   419  		{
   420  			ProviderId:    "2",
   421  			NetworkOrigin: params.NetworkOrigin(network.OriginMachine),
   422  		},
   423  		{
   424  			ProviderId:    "3",
   425  			NetworkOrigin: params.NetworkOrigin(network.OriginMachine),
   426  		},
   427  	})
   428  }
   429  
   430  func (s *NetworkSuite) TestNetworkConfigFromInterfaceMACNormalization(c *gc.C) {
   431  	in := network.InterfaceInfos{
   432  		{
   433  			// All-caps and dashes
   434  			MACAddress: "00-AA-BB-CC-DD",
   435  		},
   436  		{
   437  			// All-caps and colons
   438  			MACAddress: "00:AA:BB:CC:DD",
   439  		},
   440  		{
   441  			// Already normalized
   442  			MACAddress: "00:aa:bb:cc:dd",
   443  		},
   444  	}
   445  
   446  	got := params.NetworkConfigFromInterfaceInfo(in)
   447  	c.Assert(got, gc.DeepEquals, []params.NetworkConfig{
   448  		{
   449  			MACAddress: "00:aa:bb:cc:dd",
   450  		},
   451  		{
   452  			MACAddress: "00:aa:bb:cc:dd",
   453  		},
   454  		{
   455  			MACAddress: "00:aa:bb:cc:dd",
   456  		},
   457  	})
   458  }
   459  func (s *NetworkSuite) TestInterfaceFromNetworkConfigMACNormalization(c *gc.C) {
   460  	cfg := []params.NetworkConfig{
   461  		{
   462  			// All-caps and dashes
   463  			MACAddress:     "AA-BB-CC-DD-EE-FF",
   464  			GatewayAddress: "192.168.0.254",
   465  		},
   466  		{
   467  			// All-caps and colons
   468  			MACAddress:     "AA:BB:CC:DD:EE:FF",
   469  			GatewayAddress: "192.168.0.254",
   470  		},
   471  		{
   472  			// Already normalized
   473  			MACAddress:     "aa:bb:cc:dd:ee:ff",
   474  			GatewayAddress: "192.168.0.254",
   475  		},
   476  	}
   477  
   478  	got := params.InterfaceInfoFromNetworkConfig(cfg)
   479  	gwAddr := network.NewMachineAddress("192.168.0.254").AsProviderAddress()
   480  	c.Assert(got, gc.DeepEquals, network.InterfaceInfos{
   481  		{
   482  			MACAddress:     "aa:bb:cc:dd:ee:ff",
   483  			GatewayAddress: gwAddr,
   484  		},
   485  		{
   486  			MACAddress:     "aa:bb:cc:dd:ee:ff",
   487  			GatewayAddress: gwAddr,
   488  		},
   489  		{
   490  			MACAddress:     "aa:bb:cc:dd:ee:ff",
   491  			GatewayAddress: gwAddr,
   492  		},
   493  	})
   494  }