github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/gce/environ_network_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package gce_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	jc "github.com/juju/testing/checkers"
     9  	"google.golang.org/api/compute/v1"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/core/instance"
    13  	corenetwork "github.com/juju/juju/core/network"
    14  	"github.com/juju/juju/environs"
    15  	"github.com/juju/juju/environs/instances"
    16  	"github.com/juju/juju/provider/gce"
    17  	"github.com/juju/juju/provider/gce/google"
    18  )
    19  
    20  type environNetSuite struct {
    21  	gce.BaseSuite
    22  	NetEnv environs.NetworkingEnviron
    23  }
    24  
    25  var _ = gc.Suite(&environNetSuite{})
    26  
    27  func (s *environNetSuite) SetUpTest(c *gc.C) {
    28  	s.BaseSuite.SetUpTest(c)
    29  	netEnv, ok := environs.SupportsNetworking(s.Env)
    30  	c.Assert(ok, jc.IsTrue)
    31  	s.NetEnv = netEnv
    32  }
    33  
    34  func (s *environNetSuite) cannedData() {
    35  	s.FakeConn.Zones = []google.AvailabilityZone{
    36  		google.NewZone("a-zone", google.StatusUp, "", ""),
    37  		google.NewZone("b-zone", google.StatusUp, "", ""),
    38  	}
    39  	s.FakeConn.Networks_ = []*compute.Network{{
    40  		Id:                    9876,
    41  		Name:                  "go-team1",
    42  		AutoCreateSubnetworks: true,
    43  		SelfLink:              "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/go-team1",
    44  		Subnetworks: []string{
    45  			"https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/go-team",
    46  			"https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/us-central1/subnetworks/go-team",
    47  		},
    48  	}, {
    49  		Id:                    8765,
    50  		Name:                  "albini",
    51  		AutoCreateSubnetworks: false,
    52  		SelfLink:              "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/albini",
    53  		Subnetworks: []string{
    54  			"https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/shellac",
    55  			"https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/us-central1/subnetworks/flour",
    56  		},
    57  	}, {
    58  		Id:                    4567,
    59  		Name:                  "legacy",
    60  		AutoCreateSubnetworks: false,
    61  		IPv4Range:             "10.240.0.0/16",
    62  		SelfLink:              "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/legacy",
    63  	}}
    64  	s.FakeConn.Subnets = []*compute.Subnetwork{{
    65  		Id:          1234,
    66  		IpCidrRange: "10.0.10.0/24",
    67  		Name:        "go-team",
    68  		Network:     "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/go-team1",
    69  		Region:      "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1",
    70  		SelfLink:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/go-team",
    71  	}, {
    72  		Id:          1235,
    73  		IpCidrRange: "10.0.20.0/24",
    74  		Name:        "shellac",
    75  		Network:     "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/albini",
    76  		Region:      "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1",
    77  		SelfLink:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/shellac",
    78  	}}
    79  }
    80  
    81  func (s *environNetSuite) TestSubnetsInvalidCredentialError(c *gc.C) {
    82  	s.FakeConn.Err = gce.InvalidCredentialError
    83  	c.Assert(s.InvalidatedCredentials, jc.IsFalse)
    84  	_, err := s.NetEnv.Subnets(s.CallCtx, instance.UnknownId, nil)
    85  	c.Check(err, gc.NotNil)
    86  	c.Assert(s.InvalidatedCredentials, jc.IsTrue)
    87  }
    88  
    89  func (s *environNetSuite) TestGettingAllSubnets(c *gc.C) {
    90  	s.cannedData()
    91  
    92  	subnets, err := s.NetEnv.Subnets(s.CallCtx, instance.UnknownId, nil)
    93  	c.Assert(err, jc.ErrorIsNil)
    94  
    95  	c.Assert(subnets, gc.DeepEquals, []corenetwork.SubnetInfo{{
    96  		ProviderId:        "go-team",
    97  		ProviderNetworkId: "go-team1",
    98  		CIDR:              "10.0.10.0/24",
    99  		AvailabilityZones: []string{"a-zone", "b-zone"},
   100  		VLANTag:           0,
   101  	}, {
   102  		ProviderId:        "shellac",
   103  		ProviderNetworkId: "albini",
   104  		CIDR:              "10.0.20.0/24",
   105  		AvailabilityZones: []string{"a-zone", "b-zone"},
   106  		VLANTag:           0,
   107  	}, {
   108  		ProviderId:        "legacy",
   109  		ProviderNetworkId: "legacy",
   110  		CIDR:              "10.240.0.0/16",
   111  		AvailabilityZones: []string{"a-zone", "b-zone"},
   112  		VLANTag:           0,
   113  	}})
   114  }
   115  
   116  func (s *environNetSuite) TestSuperSubnets(c *gc.C) {
   117  	s.cannedData()
   118  
   119  	subnets, err := s.NetEnv.SuperSubnets(s.CallCtx)
   120  	c.Assert(err, jc.ErrorIsNil)
   121  
   122  	c.Assert(subnets, gc.DeepEquals, []string{
   123  		"10.0.10.0/24",
   124  		"10.0.20.0/24",
   125  		"10.240.0.0/16",
   126  	})
   127  }
   128  
   129  func (s *environNetSuite) TestRestrictingToSubnets(c *gc.C) {
   130  	s.cannedData()
   131  
   132  	subnets, err := s.NetEnv.Subnets(s.CallCtx, instance.UnknownId, []corenetwork.Id{
   133  		"shellac",
   134  	})
   135  	c.Assert(err, jc.ErrorIsNil)
   136  	c.Assert(subnets, gc.DeepEquals, []corenetwork.SubnetInfo{{
   137  		ProviderId:        "shellac",
   138  		ProviderNetworkId: "albini",
   139  		CIDR:              "10.0.20.0/24",
   140  		AvailabilityZones: []string{"a-zone", "b-zone"},
   141  		VLANTag:           0,
   142  	}})
   143  }
   144  
   145  func (s *environNetSuite) TestRestrictingToSubnetsWithMissing(c *gc.C) {
   146  	s.cannedData()
   147  
   148  	subnets, err := s.NetEnv.Subnets(s.CallCtx, instance.UnknownId, []corenetwork.Id{"shellac", "brunettes"})
   149  	c.Assert(err, gc.ErrorMatches, `subnets \["brunettes"\] not found`)
   150  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   151  	c.Assert(subnets, gc.IsNil)
   152  }
   153  
   154  func (s *environNetSuite) TestSpecificInstance(c *gc.C) {
   155  	s.cannedData()
   156  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstance(c, "moana")}
   157  
   158  	subnets, err := s.NetEnv.Subnets(s.CallCtx, "moana", nil)
   159  	c.Assert(err, jc.ErrorIsNil)
   160  
   161  	c.Assert(subnets, gc.DeepEquals, []corenetwork.SubnetInfo{{
   162  		ProviderId:        "go-team",
   163  		ProviderNetworkId: "go-team1",
   164  		CIDR:              "10.0.10.0/24",
   165  		AvailabilityZones: []string{"a-zone", "b-zone"},
   166  		VLANTag:           0,
   167  	}})
   168  }
   169  
   170  func (s *environNetSuite) TestSpecificInstanceAndRestrictedSubnets(c *gc.C) {
   171  	s.cannedData()
   172  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstance(c, "moana")}
   173  
   174  	subnets, err := s.NetEnv.Subnets(s.CallCtx, "moana", []corenetwork.Id{"go-team"})
   175  	c.Assert(err, jc.ErrorIsNil)
   176  
   177  	c.Assert(subnets, gc.DeepEquals, []corenetwork.SubnetInfo{{
   178  		ProviderId:        "go-team",
   179  		ProviderNetworkId: "go-team1",
   180  		CIDR:              "10.0.10.0/24",
   181  		AvailabilityZones: []string{"a-zone", "b-zone"},
   182  		VLANTag:           0,
   183  	}})
   184  }
   185  
   186  func (s *environNetSuite) TestSpecificInstanceAndRestrictedSubnetsWithMissing(c *gc.C) {
   187  	s.cannedData()
   188  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstance(c, "moana")}
   189  
   190  	subnets, err := s.NetEnv.Subnets(s.CallCtx, "moana", []corenetwork.Id{"go-team", "shellac"})
   191  	c.Assert(err, gc.ErrorMatches, `subnets \["shellac"\] not found`)
   192  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   193  	c.Assert(subnets, gc.IsNil)
   194  }
   195  
   196  func (s *environNetSuite) TestInterfaces(c *gc.C) {
   197  	s.cannedData()
   198  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstance(c, "moana")}
   199  
   200  	infoList, err := s.NetEnv.NetworkInterfaces(s.CallCtx, []instance.Id{"moana"})
   201  	c.Assert(err, jc.ErrorIsNil)
   202  	c.Assert(infoList, gc.HasLen, 1)
   203  	infos := infoList[0]
   204  
   205  	c.Assert(infos, gc.DeepEquals, corenetwork.InterfaceInfos{{
   206  		DeviceIndex:       0,
   207  		ProviderId:        "moana/somenetif",
   208  		ProviderSubnetId:  "go-team",
   209  		ProviderNetworkId: "go-team1",
   210  		AvailabilityZones: []string{"a-zone", "b-zone"},
   211  		InterfaceName:     "somenetif",
   212  		InterfaceType:     corenetwork.EthernetDevice,
   213  		Disabled:          false,
   214  		NoAutoStart:       false,
   215  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   216  			"10.0.10.3",
   217  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   218  			corenetwork.WithCIDR("10.0.10.0/24"),
   219  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   220  		).AsProviderAddress()},
   221  		Origin: corenetwork.OriginProvider,
   222  	}})
   223  }
   224  
   225  func (s *environNetSuite) TestNetworkInterfaceInvalidCredentialError(c *gc.C) {
   226  	s.FakeConn.Err = gce.InvalidCredentialError
   227  	c.Assert(s.InvalidatedCredentials, jc.IsFalse)
   228  	s.cannedData()
   229  	baseInst := s.NewBaseInstance(c, "moana")
   230  	// This isn't possible in GCE at the moment, but we don't want to
   231  	// break when it is.
   232  	summary := &baseInst.InstanceSummary
   233  	summary.NetworkInterfaces = append(summary.NetworkInterfaces, &compute.NetworkInterface{
   234  		Name:       "othernetif",
   235  		NetworkIP:  "10.0.20.3",
   236  		Network:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/shellac",
   237  		Subnetwork: "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/shellac",
   238  		AccessConfigs: []*compute.AccessConfig{{
   239  			Type:  "ONE_TO_ONE_NAT",
   240  			Name:  "ExternalNAT",
   241  			NatIP: "25.185.142.227",
   242  		}},
   243  	})
   244  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstanceFromBase(baseInst)}
   245  
   246  	_, err := s.NetEnv.NetworkInterfaces(s.CallCtx, []instance.Id{"moana"})
   247  	c.Check(err, gc.NotNil)
   248  	c.Assert(s.InvalidatedCredentials, jc.IsTrue)
   249  }
   250  
   251  func (s *environNetSuite) TestInterfacesForMultipleInstances(c *gc.C) {
   252  	s.cannedData()
   253  	baseInst1 := s.NewBaseInstance(c, "i-1")
   254  
   255  	// Create a second instance and patch its interface list
   256  	baseInst2 := s.NewBaseInstance(c, "i-2")
   257  	b2summary := &baseInst2.InstanceSummary
   258  	b2summary.NetworkInterfaces = []*compute.NetworkInterface{
   259  		{
   260  			Name:       "netif-0",
   261  			NetworkIP:  "10.0.10.42",
   262  			Network:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/go-team",
   263  			Subnetwork: "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/go-team",
   264  			AccessConfigs: []*compute.AccessConfig{{
   265  				Type:  "ONE_TO_ONE_NAT",
   266  				Name:  "ExternalNAT",
   267  				NatIP: "25.185.142.227",
   268  			}},
   269  		},
   270  		{
   271  			Name:       "netif-1",
   272  			NetworkIP:  "10.0.20.42",
   273  			Network:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/shellac",
   274  			Subnetwork: "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/shellac",
   275  			// No public IP
   276  		},
   277  	}
   278  	s.FakeEnviron.Insts = []instances.Instance{
   279  		s.NewInstanceFromBase(baseInst1),
   280  		s.NewInstanceFromBase(baseInst2),
   281  	}
   282  
   283  	infoLists, err := s.NetEnv.NetworkInterfaces(s.CallCtx, []instance.Id{
   284  		"i-1",
   285  		"i-2",
   286  	})
   287  	c.Assert(err, jc.ErrorIsNil)
   288  	c.Assert(infoLists, gc.HasLen, 2)
   289  
   290  	// Check interfaces for first instance
   291  	infos := infoLists[0]
   292  	c.Assert(infos, gc.DeepEquals, corenetwork.InterfaceInfos{{
   293  		DeviceIndex:       0,
   294  		ProviderId:        "i-1/somenetif",
   295  		ProviderSubnetId:  "go-team",
   296  		ProviderNetworkId: "go-team1",
   297  		AvailabilityZones: []string{"a-zone", "b-zone"},
   298  		InterfaceName:     "somenetif",
   299  		InterfaceType:     corenetwork.EthernetDevice,
   300  		Disabled:          false,
   301  		NoAutoStart:       false,
   302  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   303  			"10.0.10.3",
   304  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   305  			corenetwork.WithCIDR("10.0.10.0/24"),
   306  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   307  		).AsProviderAddress()},
   308  		Origin: corenetwork.OriginProvider,
   309  	}})
   310  
   311  	// Check interfaces for second instance
   312  	infos = infoLists[1]
   313  	c.Assert(infos, gc.DeepEquals, corenetwork.InterfaceInfos{{
   314  		DeviceIndex:       0,
   315  		ProviderId:        "i-2/netif-0",
   316  		ProviderSubnetId:  "go-team",
   317  		ProviderNetworkId: "go-team1",
   318  		AvailabilityZones: []string{"a-zone", "b-zone"},
   319  		InterfaceName:     "netif-0",
   320  		InterfaceType:     corenetwork.EthernetDevice,
   321  		Disabled:          false,
   322  		NoAutoStart:       false,
   323  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   324  			"10.0.10.42",
   325  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   326  			corenetwork.WithCIDR("10.0.10.0/24"),
   327  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   328  		).AsProviderAddress()},
   329  		ShadowAddresses: corenetwork.ProviderAddresses{
   330  			corenetwork.NewMachineAddress("25.185.142.227", corenetwork.WithScope(corenetwork.ScopePublic)).AsProviderAddress(),
   331  		},
   332  		Origin: corenetwork.OriginProvider,
   333  	}, {
   334  		DeviceIndex:       1,
   335  		ProviderId:        "i-2/netif-1",
   336  		ProviderSubnetId:  "shellac",
   337  		ProviderNetworkId: "albini",
   338  		AvailabilityZones: []string{"a-zone", "b-zone"},
   339  		InterfaceName:     "netif-1",
   340  		InterfaceType:     corenetwork.EthernetDevice,
   341  		Disabled:          false,
   342  		NoAutoStart:       false,
   343  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   344  			"10.0.20.42",
   345  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   346  			corenetwork.WithCIDR("10.0.20.0/24"),
   347  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   348  		).AsProviderAddress()},
   349  		Origin: corenetwork.OriginProvider,
   350  	}})
   351  }
   352  
   353  func (s *environNetSuite) TestPartialInterfacesForMultipleInstances(c *gc.C) {
   354  	s.cannedData()
   355  	baseInst1 := s.NewBaseInstance(c, "i-1")
   356  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstanceFromBase(baseInst1)}
   357  
   358  	infoLists, err := s.NetEnv.NetworkInterfaces(s.CallCtx, []instance.Id{"i-1", "bogus"})
   359  	c.Assert(err, gc.Equals, environs.ErrPartialInstances)
   360  	c.Assert(infoLists, gc.HasLen, 2)
   361  
   362  	// Check interfaces for first instance
   363  	infos := infoLists[0]
   364  	c.Assert(infos, gc.DeepEquals, corenetwork.InterfaceInfos{{
   365  		DeviceIndex:       0,
   366  		ProviderId:        "i-1/somenetif",
   367  		ProviderSubnetId:  "go-team",
   368  		ProviderNetworkId: "go-team1",
   369  		AvailabilityZones: []string{"a-zone", "b-zone"},
   370  		InterfaceName:     "somenetif",
   371  		InterfaceType:     corenetwork.EthernetDevice,
   372  		Disabled:          false,
   373  		NoAutoStart:       false,
   374  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   375  			"10.0.10.3",
   376  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   377  			corenetwork.WithCIDR("10.0.10.0/24"),
   378  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   379  		).AsProviderAddress()},
   380  		Origin: corenetwork.OriginProvider,
   381  	}})
   382  
   383  	// Check that the slot for the second instance is nil
   384  	c.Assert(infoLists[1], gc.IsNil, gc.Commentf("expected slot for unknown instance to be nil"))
   385  }
   386  
   387  func (s *environNetSuite) TestInterfacesMulti(c *gc.C) {
   388  	s.cannedData()
   389  	baseInst := s.NewBaseInstance(c, "moana")
   390  	// This isn't possible in GCE at the moment, but we don't want to
   391  	// break when it is.
   392  	summary := &baseInst.InstanceSummary
   393  	summary.NetworkInterfaces = append(summary.NetworkInterfaces, &compute.NetworkInterface{
   394  		Name:       "othernetif",
   395  		NetworkIP:  "10.0.20.3",
   396  		Network:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/shellac",
   397  		Subnetwork: "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/shellac",
   398  		AccessConfigs: []*compute.AccessConfig{{
   399  			Type:  "ONE_TO_ONE_NAT",
   400  			Name:  "ExternalNAT",
   401  			NatIP: "25.185.142.227",
   402  		}},
   403  	})
   404  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstanceFromBase(baseInst)}
   405  
   406  	infoList, err := s.NetEnv.NetworkInterfaces(s.CallCtx, []instance.Id{"moana"})
   407  	c.Assert(err, jc.ErrorIsNil)
   408  	c.Assert(infoList, gc.HasLen, 1)
   409  	infos := infoList[0]
   410  
   411  	c.Assert(infos, gc.DeepEquals, corenetwork.InterfaceInfos{{
   412  		DeviceIndex:       0,
   413  		ProviderId:        "moana/somenetif",
   414  		ProviderSubnetId:  "go-team",
   415  		ProviderNetworkId: "go-team1",
   416  		AvailabilityZones: []string{"a-zone", "b-zone"},
   417  		InterfaceName:     "somenetif",
   418  		InterfaceType:     corenetwork.EthernetDevice,
   419  		Disabled:          false,
   420  		NoAutoStart:       false,
   421  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   422  			"10.0.10.3",
   423  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   424  			corenetwork.WithCIDR("10.0.10.0/24"),
   425  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   426  		).AsProviderAddress()},
   427  		Origin: corenetwork.OriginProvider,
   428  	}, {
   429  		DeviceIndex:       1,
   430  		ProviderId:        "moana/othernetif",
   431  		ProviderSubnetId:  "shellac",
   432  		ProviderNetworkId: "albini",
   433  		AvailabilityZones: []string{"a-zone", "b-zone"},
   434  		InterfaceName:     "othernetif",
   435  		InterfaceType:     corenetwork.EthernetDevice,
   436  		Disabled:          false,
   437  		NoAutoStart:       false,
   438  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   439  			"10.0.20.3",
   440  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   441  			corenetwork.WithCIDR("10.0.20.0/24"),
   442  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   443  		).AsProviderAddress()},
   444  		ShadowAddresses: corenetwork.ProviderAddresses{
   445  			corenetwork.NewMachineAddress("25.185.142.227", corenetwork.WithScope(corenetwork.ScopePublic)).AsProviderAddress(),
   446  		},
   447  		Origin: corenetwork.OriginProvider,
   448  	}})
   449  }
   450  
   451  func (s *environNetSuite) TestInterfacesLegacy(c *gc.C) {
   452  	s.cannedData()
   453  	baseInst := s.NewBaseInstance(c, "moana")
   454  	// When we're using a legacy network there'll be no subnet.
   455  	summary := &baseInst.InstanceSummary
   456  	summary.NetworkInterfaces = []*compute.NetworkInterface{{
   457  		Name:       "somenetif",
   458  		NetworkIP:  "10.240.0.2",
   459  		Network:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/legacy",
   460  		Subnetwork: "",
   461  		AccessConfigs: []*compute.AccessConfig{{
   462  			Type:  "ONE_TO_ONE_NAT",
   463  			Name:  "ExternalNAT",
   464  			NatIP: "25.185.142.227",
   465  		}},
   466  	}}
   467  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstanceFromBase(baseInst)}
   468  
   469  	infoList, err := s.NetEnv.NetworkInterfaces(s.CallCtx, []instance.Id{"moana"})
   470  	c.Assert(err, jc.ErrorIsNil)
   471  	c.Assert(infoList, gc.HasLen, 1)
   472  	infos := infoList[0]
   473  
   474  	c.Assert(infos, gc.DeepEquals, corenetwork.InterfaceInfos{{
   475  		DeviceIndex:       0,
   476  		ProviderId:        "moana/somenetif",
   477  		ProviderSubnetId:  "",
   478  		ProviderNetworkId: "legacy",
   479  		AvailabilityZones: []string{"a-zone", "b-zone"},
   480  		InterfaceName:     "somenetif",
   481  		InterfaceType:     corenetwork.EthernetDevice,
   482  		Disabled:          false,
   483  		NoAutoStart:       false,
   484  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   485  			"10.240.0.2",
   486  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   487  			corenetwork.WithCIDR("10.240.0.0/16"),
   488  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   489  		).AsProviderAddress()},
   490  		ShadowAddresses: corenetwork.ProviderAddresses{
   491  			corenetwork.NewMachineAddress("25.185.142.227", corenetwork.WithScope(corenetwork.ScopePublic)).AsProviderAddress(),
   492  		},
   493  		Origin: corenetwork.OriginProvider,
   494  	}})
   495  }
   496  
   497  func (s *environNetSuite) TestInterfacesSameSubnetwork(c *gc.C) {
   498  	s.cannedData()
   499  	baseInst := s.NewBaseInstance(c, "moana")
   500  	// This isn't possible in GCE at the moment, but we don't want to
   501  	// break when it is.
   502  	summary := &baseInst.InstanceSummary
   503  	summary.NetworkInterfaces = append(summary.NetworkInterfaces, &compute.NetworkInterface{
   504  		Name:       "othernetif",
   505  		NetworkIP:  "10.0.10.4",
   506  		Network:    "https://www.googleapis.com/compute/v1/projects/sonic-youth/global/networks/go-team1",
   507  		Subnetwork: "https://www.googleapis.com/compute/v1/projects/sonic-youth/regions/asia-east1/subnetworks/go-team",
   508  		AccessConfigs: []*compute.AccessConfig{{
   509  			Type:  "ONE_TO_ONE_NAT",
   510  			Name:  "ExternalNAT",
   511  			NatIP: "25.185.142.227",
   512  		}},
   513  	})
   514  	s.FakeEnviron.Insts = []instances.Instance{s.NewInstanceFromBase(baseInst)}
   515  
   516  	infoList, err := s.NetEnv.NetworkInterfaces(s.CallCtx, []instance.Id{"moana"})
   517  	c.Assert(err, jc.ErrorIsNil)
   518  	c.Assert(infoList, gc.HasLen, 1)
   519  	infos := infoList[0]
   520  
   521  	c.Assert(infos, gc.DeepEquals, corenetwork.InterfaceInfos{{
   522  		DeviceIndex:       0,
   523  		ProviderId:        "moana/somenetif",
   524  		ProviderSubnetId:  "go-team",
   525  		ProviderNetworkId: "go-team1",
   526  		AvailabilityZones: []string{"a-zone", "b-zone"},
   527  		InterfaceName:     "somenetif",
   528  		InterfaceType:     corenetwork.EthernetDevice,
   529  		Disabled:          false,
   530  		NoAutoStart:       false,
   531  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   532  			"10.0.10.3",
   533  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   534  			corenetwork.WithCIDR("10.0.10.0/24"),
   535  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   536  		).AsProviderAddress()},
   537  		Origin: corenetwork.OriginProvider,
   538  	}, {
   539  		DeviceIndex:       1,
   540  		ProviderId:        "moana/othernetif",
   541  		ProviderSubnetId:  "go-team",
   542  		ProviderNetworkId: "go-team1",
   543  		AvailabilityZones: []string{"a-zone", "b-zone"},
   544  		InterfaceName:     "othernetif",
   545  		InterfaceType:     corenetwork.EthernetDevice,
   546  		Disabled:          false,
   547  		NoAutoStart:       false,
   548  		Addresses: corenetwork.ProviderAddresses{corenetwork.NewMachineAddress(
   549  			"10.0.10.4",
   550  			corenetwork.WithScope(corenetwork.ScopeCloudLocal),
   551  			corenetwork.WithCIDR("10.0.10.0/24"),
   552  			corenetwork.WithConfigType(corenetwork.ConfigDHCP),
   553  		).AsProviderAddress()},
   554  		ShadowAddresses: corenetwork.ProviderAddresses{
   555  			corenetwork.NewMachineAddress("25.185.142.227", corenetwork.WithScope(corenetwork.ScopePublic)).AsProviderAddress(),
   556  		},
   557  		Origin: corenetwork.OriginProvider,
   558  	}})
   559  }