github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/apiserver/testing/stub_network.go (about)

     1  package testing
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"strconv"
     7  	"strings"
     8  
     9  	gc "gopkg.in/check.v1"
    10  
    11  	"github.com/juju/juju/apiserver/common"
    12  	"github.com/juju/juju/apiserver/params"
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/juju/environs/config"
    15  	"github.com/juju/juju/instance"
    16  	"github.com/juju/juju/network"
    17  	providercommon "github.com/juju/juju/provider/common"
    18  	coretesting "github.com/juju/juju/testing"
    19  	"github.com/juju/testing"
    20  	"github.com/juju/utils"
    21  	"github.com/juju/utils/set"
    22  )
    23  
    24  type StubNetwork struct {
    25  }
    26  
    27  var (
    28  	// SharedStub records all method calls to any of the stubs.
    29  	SharedStub = &testing.Stub{}
    30  
    31  	BackingInstance                = &StubBacking{Stub: SharedStub}
    32  	ProviderInstance               = &StubProvider{Stub: SharedStub}
    33  	EnvironInstance                = &StubEnviron{Stub: SharedStub}
    34  	ZonedEnvironInstance           = &StubZonedEnviron{Stub: SharedStub}
    35  	NetworkingEnvironInstance      = &StubNetworkingEnviron{Stub: SharedStub}
    36  	ZonedNetworkingEnvironInstance = &StubZonedNetworkingEnviron{Stub: SharedStub}
    37  )
    38  
    39  const (
    40  	StubProviderType               = "stub-provider"
    41  	StubEnvironName                = "stub-environ"
    42  	StubZonedEnvironName           = "stub-zoned-environ"
    43  	StubNetworkingEnvironName      = "stub-networking-environ"
    44  	StubZonedNetworkingEnvironName = "stub-zoned-networking-environ"
    45  )
    46  
    47  func (s StubNetwork) SetUpSuite(c *gc.C) {
    48  	ProviderInstance.Zones = []providercommon.AvailabilityZone{
    49  		&FakeZone{"zone1", true},
    50  		&FakeZone{"zone2", false},
    51  		&FakeZone{"zone3", true},
    52  		&FakeZone{"zone4", false},
    53  		&FakeZone{"zone4", false}, // duplicates are ignored
    54  	}
    55  	ProviderInstance.Subnets = []network.SubnetInfo{{
    56  		CIDR:              "10.10.0.0/24",
    57  		ProviderId:        "sn-zadf00d",
    58  		AvailabilityZones: []string{"zone1"},
    59  		AllocatableIPLow:  net.ParseIP("10.10.0.10"),
    60  		AllocatableIPHigh: net.ParseIP("10.10.0.100"),
    61  	}, {
    62  		CIDR:              "2001:db8::/32",
    63  		ProviderId:        "sn-ipv6",
    64  		AvailabilityZones: []string{"zone1", "zone3"},
    65  	}, {
    66  		// no CIDR or provider id -> cached, but cannot be added
    67  		CIDR:       "",
    68  		ProviderId: "",
    69  	}, {
    70  		// no CIDR, just provider id -> cached, but can only be added by id
    71  		CIDR:       "",
    72  		ProviderId: "sn-empty",
    73  	}, {
    74  		// invalid CIDR and provider id -> cannot be added, but is cached
    75  		CIDR:       "invalid",
    76  		ProviderId: "sn-invalid",
    77  	}, {
    78  		// incorrectly specified CIDR, with provider id -> cached, cannot be added
    79  		CIDR:       "0.1.2.3/4",
    80  		ProviderId: "sn-awesome",
    81  	}, {
    82  		// no zones, no provider-id -> cached, but can only be added by CIDR
    83  		CIDR: "10.20.0.0/16",
    84  	}, {
    85  		// with zones, duplicate provider-id -> overwritten by the last
    86  		// subnet with the same provider id when caching.
    87  		CIDR:              "10.99.88.0/24",
    88  		ProviderId:        "sn-deadbeef",
    89  		AvailabilityZones: []string{"zone1", "zone2"},
    90  	}, {
    91  		// no zones
    92  		CIDR:       "10.42.0.0/16",
    93  		ProviderId: "sn-42",
    94  	}, {
    95  		// in an unavailable zone, duplicate CIDR -> cannot be added, but is cached
    96  		CIDR:              "10.10.0.0/24",
    97  		ProviderId:        "sn-deadbeef",
    98  		AvailabilityZones: []string{"zone2"},
    99  	}, {
   100  		CIDR:              "10.30.1.0/24",
   101  		ProviderId:        "vlan-42",
   102  		VLANTag:           42,
   103  		AvailabilityZones: []string{"zone3"},
   104  	}}
   105  
   106  	environs.RegisterProvider(StubProviderType, ProviderInstance)
   107  }
   108  
   109  type errReturner func() error
   110  
   111  // FakeSpace implements common.BackingSpace for testing.
   112  type FakeSpace struct {
   113  	SpaceName string
   114  	SubnetIds []string
   115  	Public    bool
   116  	NextErr   errReturner
   117  }
   118  
   119  var _ common.BackingSpace = (*FakeSpace)(nil)
   120  
   121  func (f *FakeSpace) Name() string {
   122  	return f.SpaceName
   123  }
   124  
   125  func (f *FakeSpace) Subnets() (bs []common.BackingSubnet, err error) {
   126  	outputSubnets := []common.BackingSubnet{}
   127  
   128  	if err = f.NextErr(); err != nil {
   129  		return outputSubnets, err
   130  	}
   131  
   132  	for _, subnetId := range f.SubnetIds {
   133  		providerId := "provider-" + subnetId
   134  
   135  		// Pick the third element of the IP address and use this to
   136  		// decide how we construct the Subnet. It provides variation of
   137  		// test data.
   138  		first, err := strconv.Atoi(strings.Split(subnetId, ".")[2])
   139  		if err != nil {
   140  			return outputSubnets, err
   141  		}
   142  		vlantag := 0
   143  		zones := []string{"foo"}
   144  		status := "in-use"
   145  		if first%2 == 1 {
   146  			vlantag = 23
   147  			zones = []string{"bar", "bam"}
   148  			status = ""
   149  		}
   150  
   151  		backing := common.BackingSubnetInfo{
   152  			CIDR:              subnetId,
   153  			SpaceName:         f.SpaceName,
   154  			ProviderId:        providerId,
   155  			VLANTag:           vlantag,
   156  			AvailabilityZones: zones,
   157  			Status:            status,
   158  		}
   159  		outputSubnets = append(outputSubnets, &FakeSubnet{info: backing})
   160  	}
   161  
   162  	return outputSubnets, nil
   163  }
   164  
   165  func (f *FakeSpace) ProviderId() (netID network.Id) {
   166  	return
   167  }
   168  
   169  func (f *FakeSpace) Zones() []string {
   170  	return []string{""}
   171  }
   172  
   173  func (f *FakeSpace) Life() (life params.Life) {
   174  	return
   175  }
   176  
   177  // GoString implements fmt.GoStringer.
   178  func (f *FakeSpace) GoString() string {
   179  	return fmt.Sprintf("&FakeSpace{%q}", f.SpaceName)
   180  }
   181  
   182  // StubMethodCall is like testing.StubCall, but includes the receiver
   183  // as well.
   184  type StubMethodCall struct {
   185  	Receiver interface{}
   186  	FuncName string
   187  	Args     []interface{}
   188  }
   189  
   190  // BackingCall makes it easy to check method calls on BackingInstance.
   191  func BackingCall(name string, args ...interface{}) StubMethodCall {
   192  	return StubMethodCall{
   193  		Receiver: BackingInstance,
   194  		FuncName: name,
   195  		Args:     args,
   196  	}
   197  }
   198  
   199  // ProviderCall makes it easy to check method calls on ProviderInstance.
   200  func ProviderCall(name string, args ...interface{}) StubMethodCall {
   201  	return StubMethodCall{
   202  		Receiver: ProviderInstance,
   203  		FuncName: name,
   204  		Args:     args,
   205  	}
   206  }
   207  
   208  // EnvironCall makes it easy to check method calls on EnvironInstance.
   209  func EnvironCall(name string, args ...interface{}) StubMethodCall {
   210  	return StubMethodCall{
   211  		Receiver: EnvironInstance,
   212  		FuncName: name,
   213  		Args:     args,
   214  	}
   215  }
   216  
   217  // ZonedEnvironCall makes it easy to check method calls on
   218  // ZonedEnvironInstance.
   219  func ZonedEnvironCall(name string, args ...interface{}) StubMethodCall {
   220  	return StubMethodCall{
   221  		Receiver: ZonedEnvironInstance,
   222  		FuncName: name,
   223  		Args:     args,
   224  	}
   225  }
   226  
   227  // NetworkingEnvironCall makes it easy to check method calls on
   228  // NetworkingEnvironInstance.
   229  func NetworkingEnvironCall(name string, args ...interface{}) StubMethodCall {
   230  	return StubMethodCall{
   231  		Receiver: NetworkingEnvironInstance,
   232  		FuncName: name,
   233  		Args:     args,
   234  	}
   235  }
   236  
   237  // ZonedNetworkingEnvironCall makes it easy to check method calls on
   238  // ZonedNetworkingEnvironInstance.
   239  func ZonedNetworkingEnvironCall(name string, args ...interface{}) StubMethodCall {
   240  	return StubMethodCall{
   241  		Receiver: ZonedNetworkingEnvironInstance,
   242  		FuncName: name,
   243  		Args:     args,
   244  	}
   245  }
   246  
   247  // CheckMethodCalls works like testing.Stub.CheckCalls, but also
   248  // checks the receivers.
   249  func CheckMethodCalls(c *gc.C, stub *testing.Stub, calls ...StubMethodCall) {
   250  	receivers := make([]interface{}, len(calls))
   251  	for i, call := range calls {
   252  		receivers[i] = call.Receiver
   253  	}
   254  	stub.CheckReceivers(c, receivers...)
   255  	c.Check(stub.Calls(), gc.HasLen, len(calls))
   256  	for i, call := range calls {
   257  		stub.CheckCall(c, i, call.FuncName, call.Args...)
   258  	}
   259  }
   260  
   261  // FakeZone implements providercommon.AvailabilityZone for testing.
   262  type FakeZone struct {
   263  	ZoneName      string
   264  	ZoneAvailable bool
   265  }
   266  
   267  var _ providercommon.AvailabilityZone = (*FakeZone)(nil)
   268  
   269  func (f *FakeZone) Name() string {
   270  	return f.ZoneName
   271  }
   272  
   273  func (f *FakeZone) Available() bool {
   274  	return f.ZoneAvailable
   275  }
   276  
   277  // GoString implements fmt.GoStringer.
   278  func (f *FakeZone) GoString() string {
   279  	return fmt.Sprintf("&FakeZone{%q, %v}", f.ZoneName, f.ZoneAvailable)
   280  }
   281  
   282  // FakeSubnet implements common.BackingSubnet for testing.
   283  type FakeSubnet struct {
   284  	info common.BackingSubnetInfo
   285  }
   286  
   287  var _ common.BackingSubnet = (*FakeSubnet)(nil)
   288  
   289  // GoString implements fmt.GoStringer.
   290  func (f *FakeSubnet) GoString() string {
   291  	return fmt.Sprintf("&FakeSubnet{%#v}", f.info)
   292  }
   293  
   294  func (f *FakeSubnet) Status() string {
   295  	return f.info.Status
   296  }
   297  
   298  func (f *FakeSubnet) CIDR() string {
   299  	return f.info.CIDR
   300  }
   301  
   302  func (f *FakeSubnet) AvailabilityZones() []string {
   303  	return f.info.AvailabilityZones
   304  }
   305  
   306  func (f *FakeSubnet) ProviderId() string {
   307  	return f.info.ProviderId
   308  }
   309  
   310  func (f *FakeSubnet) VLANTag() int {
   311  	return f.info.VLANTag
   312  }
   313  
   314  func (f *FakeSubnet) SpaceName() string {
   315  	return f.info.SpaceName
   316  }
   317  
   318  func (f *FakeSubnet) Life() params.Life {
   319  	return f.info.Life
   320  }
   321  
   322  // ResetStub resets all recorded calls and errors of the given stub.
   323  func ResetStub(stub *testing.Stub) {
   324  	*stub = testing.Stub{}
   325  }
   326  
   327  // StubBacking implements common.NetworkBacking and records calls to its
   328  // methods.
   329  type StubBacking struct {
   330  	*testing.Stub
   331  
   332  	EnvConfig *config.Config
   333  
   334  	Zones   []providercommon.AvailabilityZone
   335  	Spaces  []common.BackingSpace
   336  	Subnets []common.BackingSubnet
   337  }
   338  
   339  var _ common.NetworkBacking = (*StubBacking)(nil)
   340  
   341  type SetUpFlag bool
   342  
   343  const (
   344  	WithZones      SetUpFlag = true
   345  	WithoutZones   SetUpFlag = false
   346  	WithSpaces     SetUpFlag = true
   347  	WithoutSpaces  SetUpFlag = false
   348  	WithSubnets    SetUpFlag = true
   349  	WithoutSubnets SetUpFlag = false
   350  )
   351  
   352  func (sb *StubBacking) SetUp(c *gc.C, envName string, withZones, withSpaces, withSubnets SetUpFlag) {
   353  	// This method must be called at the beginning of each test, which
   354  	// needs access to any of the mocks, to reset the recorded calls
   355  	// and errors, as well as to initialize the mocks as needed.
   356  	ResetStub(sb.Stub)
   357  
   358  	// Make sure we use the stub provider.
   359  	extraAttrs := coretesting.Attrs{
   360  		"uuid": utils.MustNewUUID().String(),
   361  		"type": StubProviderType,
   362  		"name": envName,
   363  	}
   364  	sb.EnvConfig = coretesting.CustomEnvironConfig(c, extraAttrs)
   365  	sb.Zones = []providercommon.AvailabilityZone{}
   366  	if withZones {
   367  		sb.Zones = make([]providercommon.AvailabilityZone, len(ProviderInstance.Zones))
   368  		copy(sb.Zones, ProviderInstance.Zones)
   369  	}
   370  	sb.Spaces = []common.BackingSpace{}
   371  	if withSpaces {
   372  		// Note that full subnet data is generated from the SubnetIds in
   373  		// FakeSpace.Subnets().
   374  		sb.Spaces = []common.BackingSpace{
   375  			&FakeSpace{
   376  				SpaceName: "default",
   377  				SubnetIds: []string{"192.168.0.0/24", "192.168.3.0/24"},
   378  				NextErr:   sb.NextErr},
   379  			&FakeSpace{
   380  				SpaceName: "dmz",
   381  				SubnetIds: []string{"192.168.1.0/24"},
   382  				NextErr:   sb.NextErr},
   383  			&FakeSpace{
   384  				SpaceName: "private",
   385  				SubnetIds: []string{"192.168.2.0/24"},
   386  				NextErr:   sb.NextErr},
   387  			&FakeSpace{
   388  				SpaceName: "private",
   389  				SubnetIds: []string{"192.168.2.0/24"},
   390  				NextErr:   sb.NextErr}, // duplicates are ignored when caching spaces.
   391  		}
   392  	}
   393  	sb.Subnets = []common.BackingSubnet{}
   394  	if withSubnets {
   395  		info0 := common.BackingSubnetInfo{
   396  			CIDR:              ProviderInstance.Subnets[0].CIDR,
   397  			ProviderId:        string(ProviderInstance.Subnets[0].ProviderId),
   398  			AllocatableIPLow:  ProviderInstance.Subnets[0].AllocatableIPLow.String(),
   399  			AllocatableIPHigh: ProviderInstance.Subnets[0].AllocatableIPHigh.String(),
   400  			AvailabilityZones: ProviderInstance.Subnets[0].AvailabilityZones,
   401  			SpaceName:         "private",
   402  		}
   403  		info1 := common.BackingSubnetInfo{
   404  			CIDR:              ProviderInstance.Subnets[1].CIDR,
   405  			ProviderId:        string(ProviderInstance.Subnets[1].ProviderId),
   406  			AvailabilityZones: ProviderInstance.Subnets[1].AvailabilityZones,
   407  			SpaceName:         "dmz",
   408  		}
   409  
   410  		sb.Subnets = []common.BackingSubnet{
   411  			&FakeSubnet{info0},
   412  			&FakeSubnet{info1},
   413  		}
   414  	}
   415  }
   416  
   417  func (sb *StubBacking) EnvironConfig() (*config.Config, error) {
   418  	sb.MethodCall(sb, "EnvironConfig")
   419  	if err := sb.NextErr(); err != nil {
   420  		return nil, err
   421  	}
   422  	return sb.EnvConfig, nil
   423  }
   424  
   425  func (sb *StubBacking) AvailabilityZones() ([]providercommon.AvailabilityZone, error) {
   426  	sb.MethodCall(sb, "AvailabilityZones")
   427  	if err := sb.NextErr(); err != nil {
   428  		return nil, err
   429  	}
   430  	return sb.Zones, nil
   431  }
   432  
   433  func (sb *StubBacking) SetAvailabilityZones(zones []providercommon.AvailabilityZone) error {
   434  	sb.MethodCall(sb, "SetAvailabilityZones", zones)
   435  	return sb.NextErr()
   436  }
   437  
   438  func (sb *StubBacking) AllSpaces() ([]common.BackingSpace, error) {
   439  	sb.MethodCall(sb, "AllSpaces")
   440  	if err := sb.NextErr(); err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	// Filter duplicates.
   445  	seen := set.Strings{}
   446  	output := []common.BackingSpace{}
   447  	for _, space := range sb.Spaces {
   448  		if seen.Contains(space.Name()) {
   449  			continue
   450  		}
   451  		seen.Add(space.Name())
   452  		output = append(output, space)
   453  	}
   454  	return output, nil
   455  }
   456  
   457  func (sb *StubBacking) AllSubnets() ([]common.BackingSubnet, error) {
   458  	sb.MethodCall(sb, "AllSubnets")
   459  	if err := sb.NextErr(); err != nil {
   460  		return nil, err
   461  	}
   462  
   463  	// Filter duplicates.
   464  	seen := set.Strings{}
   465  	output := []common.BackingSubnet{}
   466  	for _, subnet := range sb.Subnets {
   467  		if seen.Contains(subnet.CIDR()) {
   468  			continue
   469  		}
   470  		seen.Add(subnet.CIDR())
   471  		output = append(output, subnet)
   472  	}
   473  	return output, nil
   474  }
   475  
   476  func (sb *StubBacking) AddSubnet(subnetInfo common.BackingSubnetInfo) (common.BackingSubnet, error) {
   477  	sb.MethodCall(sb, "AddSubnet", subnetInfo)
   478  	if err := sb.NextErr(); err != nil {
   479  		return nil, err
   480  	}
   481  	fs := &FakeSubnet{info: subnetInfo}
   482  	sb.Subnets = append(sb.Subnets, fs)
   483  	return fs, nil
   484  }
   485  
   486  func (sb *StubBacking) AddSpace(name string, subnets []string, public bool) error {
   487  	sb.MethodCall(sb, "AddSpace", name, subnets, public)
   488  	if err := sb.NextErr(); err != nil {
   489  		return err
   490  	}
   491  	fs := &FakeSpace{SpaceName: name, SubnetIds: subnets, Public: public}
   492  	sb.Spaces = append(sb.Spaces, fs)
   493  	return nil
   494  }
   495  
   496  // GoString implements fmt.GoStringer.
   497  func (se *StubBacking) GoString() string {
   498  	return "&StubBacking{}"
   499  }
   500  
   501  // StubProvider implements a subset of environs.EnvironProvider
   502  // methods used in tests.
   503  type StubProvider struct {
   504  	*testing.Stub
   505  
   506  	Zones   []providercommon.AvailabilityZone
   507  	Subnets []network.SubnetInfo
   508  
   509  	environs.EnvironProvider // panic on any not implemented method call.
   510  }
   511  
   512  var _ environs.EnvironProvider = (*StubProvider)(nil)
   513  
   514  func (sp *StubProvider) Open(cfg *config.Config) (environs.Environ, error) {
   515  	sp.MethodCall(sp, "Open", cfg)
   516  	if err := sp.NextErr(); err != nil {
   517  		return nil, err
   518  	}
   519  	switch cfg.Name() {
   520  	case StubEnvironName:
   521  		return EnvironInstance, nil
   522  	case StubZonedEnvironName:
   523  		return ZonedEnvironInstance, nil
   524  	case StubNetworkingEnvironName:
   525  		return NetworkingEnvironInstance, nil
   526  	case StubZonedNetworkingEnvironName:
   527  		return ZonedNetworkingEnvironInstance, nil
   528  	}
   529  	panic("unexpected environment name: " + cfg.Name())
   530  }
   531  
   532  // GoString implements fmt.GoStringer.
   533  func (se *StubProvider) GoString() string {
   534  	return "&StubProvider{}"
   535  }
   536  
   537  // StubEnviron is used in tests where environs.Environ is needed.
   538  type StubEnviron struct {
   539  	*testing.Stub
   540  
   541  	environs.Environ // panic on any not implemented method call
   542  }
   543  
   544  var _ environs.Environ = (*StubEnviron)(nil)
   545  
   546  // GoString implements fmt.GoStringer.
   547  func (se *StubEnviron) GoString() string {
   548  	return "&StubEnviron{}"
   549  }
   550  
   551  // StubZonedEnviron is used in tests where providercommon.ZonedEnviron
   552  // is needed.
   553  type StubZonedEnviron struct {
   554  	*testing.Stub
   555  
   556  	providercommon.ZonedEnviron // panic on any not implemented method call
   557  }
   558  
   559  var _ providercommon.ZonedEnviron = (*StubZonedEnviron)(nil)
   560  
   561  func (se *StubZonedEnviron) AvailabilityZones() ([]providercommon.AvailabilityZone, error) {
   562  	se.MethodCall(se, "AvailabilityZones")
   563  	if err := se.NextErr(); err != nil {
   564  		return nil, err
   565  	}
   566  	return ProviderInstance.Zones, nil
   567  }
   568  
   569  // GoString implements fmt.GoStringer.
   570  func (se *StubZonedEnviron) GoString() string {
   571  	return "&StubZonedEnviron{}"
   572  }
   573  
   574  // StubNetworkingEnviron is used in tests where
   575  // environs.NetworkingEnviron is needed.
   576  type StubNetworkingEnviron struct {
   577  	*testing.Stub
   578  
   579  	environs.NetworkingEnviron // panic on any not implemented method call
   580  }
   581  
   582  var _ environs.NetworkingEnviron = (*StubNetworkingEnviron)(nil)
   583  
   584  func (se *StubNetworkingEnviron) Subnets(instId instance.Id, subIds []network.Id) ([]network.SubnetInfo, error) {
   585  	se.MethodCall(se, "Subnets", instId, subIds)
   586  	if err := se.NextErr(); err != nil {
   587  		return nil, err
   588  	}
   589  	return ProviderInstance.Subnets, nil
   590  }
   591  
   592  // GoString implements fmt.GoStringer.
   593  func (se *StubNetworkingEnviron) GoString() string {
   594  	return "&StubNetworkingEnviron{}"
   595  }
   596  
   597  // StubZonedNetworkingEnviron is used in tests where features from
   598  // both environs.Networking and providercommon.ZonedEnviron are
   599  // needed.
   600  type StubZonedNetworkingEnviron struct {
   601  	*testing.Stub
   602  
   603  	// panic on any not implemented method call
   604  	providercommon.ZonedEnviron
   605  	environs.Networking
   606  }
   607  
   608  // GoString implements fmt.GoStringer.
   609  func (se *StubZonedNetworkingEnviron) GoString() string {
   610  	return "&StubZonedNetworkingEnviron{}"
   611  }
   612  
   613  func (se *StubZonedNetworkingEnviron) SupportsSpaces() (bool, error) {
   614  	se.MethodCall(se, "SupportsSpaces")
   615  	if err := se.NextErr(); err != nil {
   616  		return false, err
   617  	}
   618  	return true, nil
   619  }
   620  
   621  func (se *StubZonedNetworkingEnviron) Subnets(instId instance.Id, subIds []network.Id) ([]network.SubnetInfo, error) {
   622  	se.MethodCall(se, "Subnets", instId, subIds)
   623  	if err := se.NextErr(); err != nil {
   624  		return nil, err
   625  	}
   626  	return ProviderInstance.Subnets, nil
   627  }
   628  
   629  func (se *StubZonedNetworkingEnviron) AvailabilityZones() ([]providercommon.AvailabilityZone, error) {
   630  	se.MethodCall(se, "AvailabilityZones")
   631  	if err := se.NextErr(); err != nil {
   632  		return nil, err
   633  	}
   634  	return ProviderInstance.Zones, nil
   635  }