mirror of https://github.com/k3s-io/k3s
Fix AWS region vs zone
We were specifying a region, but naming it as a zone in util.sh The zone matters just as much as the region, e.g. for EBS volumes. We also change the config to require a Zone, not a Region. But we fallback to get the information from the metadata service.pull/6/head
parent
d7c2786e22
commit
583892da2d
|
@ -14,8 +14,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# TODO: the zone isn't quite piped into all the right places...
|
AWS_ZONE=${KUBE_AWS_ZONE:-us-west-2a}
|
||||||
ZONE=${KUBE_AWS_ZONE:-us-west-2}
|
|
||||||
MASTER_SIZE=${MASTER_SIZE:-t2.micro}
|
MASTER_SIZE=${MASTER_SIZE:-t2.micro}
|
||||||
MINION_SIZE=${MINION_SIZE:-t2.micro}
|
MINION_SIZE=${MINION_SIZE:-t2.micro}
|
||||||
NUM_MINIONS=${NUM_MINIONS:-4}
|
NUM_MINIONS=${NUM_MINIONS:-4}
|
||||||
|
|
|
@ -14,8 +14,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# TODO: this isn't quite piped into all the right places...
|
AWS_ZONE=${KUBE_AWS_ZONE:-us-west-2a}
|
||||||
ZONE=${KUBE_AWS_ZONE:-us-west-2}
|
|
||||||
MASTER_SIZE=${MASTER_SIZE:-t2.micro}
|
MASTER_SIZE=${MASTER_SIZE:-t2.micro}
|
||||||
MINION_SIZE=${MINION_SIZE:-t2.micro}
|
MINION_SIZE=${MINION_SIZE:-t2.micro}
|
||||||
NUM_MINIONS=${NUM_MINIONS:-2}
|
NUM_MINIONS=${NUM_MINIONS:-2}
|
||||||
|
|
|
@ -5,6 +5,10 @@ specific to AWS are documented in this file, for cross-provider options see TODO
|
||||||
|
|
||||||
This is a work-in-progress; not all options are documented yet!
|
This is a work-in-progress; not all options are documented yet!
|
||||||
|
|
||||||
|
## KUBE_AWS_ZONE
|
||||||
|
|
||||||
|
The AWS availability to deploy to. Defaults to us-west-2a.
|
||||||
|
|
||||||
## AWS_IMAGE
|
## AWS_IMAGE
|
||||||
|
|
||||||
The AMI to use. If not specified, the image will be selected based on the AWS region.
|
The AMI to use. If not specified, the image will be selected based on the AWS region.
|
||||||
|
|
|
@ -28,7 +28,7 @@ EOF
|
||||||
|
|
||||||
cat <<EOF > /etc/aws.conf
|
cat <<EOF > /etc/aws.conf
|
||||||
[Global]
|
[Global]
|
||||||
Region = ${AWS_ZONE}
|
Zone = ${AWS_ZONE}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Auto accept all keys from minions that try to join
|
# Auto accept all keys from minions that try to join
|
||||||
|
|
|
@ -21,7 +21,10 @@
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
|
||||||
source "${KUBE_ROOT}/cluster/aws/${KUBE_CONFIG_FILE-"config-default.sh"}"
|
source "${KUBE_ROOT}/cluster/aws/${KUBE_CONFIG_FILE-"config-default.sh"}"
|
||||||
|
|
||||||
export AWS_DEFAULT_REGION=${ZONE}
|
# This removes the final character in bash (somehow)
|
||||||
|
AWS_REGION=${AWS_ZONE%?}
|
||||||
|
|
||||||
|
export AWS_DEFAULT_REGION=${AWS_REGION}
|
||||||
AWS_CMD="aws --output json ec2"
|
AWS_CMD="aws --output json ec2"
|
||||||
AWS_ELB_CMD="aws --output json elb"
|
AWS_ELB_CMD="aws --output json elb"
|
||||||
|
|
||||||
|
@ -105,7 +108,7 @@ function detect-image () {
|
||||||
# See here: http://cloud-images.ubuntu.com/locator/ec2/ for other images
|
# See here: http://cloud-images.ubuntu.com/locator/ec2/ for other images
|
||||||
# This will need to be updated from time to time as amis are deprecated
|
# This will need to be updated from time to time as amis are deprecated
|
||||||
if [[ -z "${AWS_IMAGE-}" ]]; then
|
if [[ -z "${AWS_IMAGE-}" ]]; then
|
||||||
case "${ZONE}" in
|
case "${AWS_REGION}" in
|
||||||
ap-northeast-1)
|
ap-northeast-1)
|
||||||
AWS_IMAGE=ami-93876e93
|
AWS_IMAGE=ami-93876e93
|
||||||
;;
|
;;
|
||||||
|
@ -428,7 +431,7 @@ function kube-up {
|
||||||
echo "readonly NODE_INSTANCE_PREFIX='${INSTANCE_PREFIX}-minion'"
|
echo "readonly NODE_INSTANCE_PREFIX='${INSTANCE_PREFIX}-minion'"
|
||||||
echo "readonly SERVER_BINARY_TAR_URL='${SERVER_BINARY_TAR_URL}'"
|
echo "readonly SERVER_BINARY_TAR_URL='${SERVER_BINARY_TAR_URL}'"
|
||||||
echo "readonly SALT_TAR_URL='${SALT_TAR_URL}'"
|
echo "readonly SALT_TAR_URL='${SALT_TAR_URL}'"
|
||||||
echo "readonly AWS_ZONE='${ZONE}'"
|
echo "readonly AWS_ZONE='${AWS_ZONE}'"
|
||||||
echo "readonly MASTER_HTPASSWD='${htpasswd}'"
|
echo "readonly MASTER_HTPASSWD='${htpasswd}'"
|
||||||
echo "readonly PORTAL_NET='${PORTAL_NET}'"
|
echo "readonly PORTAL_NET='${PORTAL_NET}'"
|
||||||
echo "readonly ENABLE_CLUSTER_MONITORING='${ENABLE_CLUSTER_MONITORING:-false}'"
|
echo "readonly ENABLE_CLUSTER_MONITORING='${ENABLE_CLUSTER_MONITORING:-false}'"
|
||||||
|
|
|
@ -38,7 +38,10 @@ import (
|
||||||
type EC2 interface {
|
type EC2 interface {
|
||||||
// Query EC2 for instances matching the filter
|
// Query EC2 for instances matching the filter
|
||||||
Instances(instIds []string, filter *ec2InstanceFilter) (resp *ec2.InstancesResp, err error)
|
Instances(instIds []string, filter *ec2InstanceFilter) (resp *ec2.InstancesResp, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abstraction over the AWS metadata service
|
||||||
|
type AWSMetadata interface {
|
||||||
// Query the EC2 metadata service (used to discover instance-id etc)
|
// Query the EC2 metadata service (used to discover instance-id etc)
|
||||||
GetMetaData(key string) ([]byte, error)
|
GetMetaData(key string) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
@ -54,7 +57,7 @@ type AWSCloud struct {
|
||||||
type AWSCloudConfig struct {
|
type AWSCloudConfig struct {
|
||||||
Global struct {
|
Global struct {
|
||||||
// TODO: Is there any use for this? We can get it from the instance metadata service
|
// TODO: Is there any use for this? We can get it from the instance metadata service
|
||||||
Region string
|
Zone string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +92,11 @@ func (self *GoamzEC2) Instances(instanceIds []string, filter *ec2InstanceFilter)
|
||||||
return self.ec2.Instances(instanceIds, goamzFilter)
|
return self.ec2.Instances(instanceIds, goamzFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *GoamzEC2) GetMetaData(key string) ([]byte, error) {
|
type goamzMetadata struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements AWSMetadata.GetMetaData
|
||||||
|
func (self *goamzMetadata) GetMetaData(key string) ([]byte, error) {
|
||||||
v, err := aws.GetMetaData(key)
|
v, err := aws.GetMetaData(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error querying AWS metadata for key %s: %v", key, err)
|
return nil, fmt.Errorf("Error querying AWS metadata for key %s: %v", key, err)
|
||||||
|
@ -101,7 +108,8 @@ type AuthFunc func() (auth aws.Auth, err error)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cloudprovider.RegisterCloudProvider("aws", func(config io.Reader) (cloudprovider.Interface, error) {
|
cloudprovider.RegisterCloudProvider("aws", func(config io.Reader) (cloudprovider.Interface, error) {
|
||||||
return newAWSCloud(config, getAuth)
|
metadata := &goamzMetadata{}
|
||||||
|
return newAWSCloud(config, getAuth, metadata)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +118,7 @@ func getAuth() (auth aws.Auth, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// readAWSCloudConfig reads an instance of AWSCloudConfig from config reader.
|
// readAWSCloudConfig reads an instance of AWSCloudConfig from config reader.
|
||||||
func readAWSCloudConfig(config io.Reader) (*AWSCloudConfig, error) {
|
func readAWSCloudConfig(config io.Reader, metadata AWSMetadata) (*AWSCloudConfig, error) {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return nil, fmt.Errorf("no AWS cloud provider config file given")
|
return nil, fmt.Errorf("no AWS cloud provider config file given")
|
||||||
}
|
}
|
||||||
|
@ -121,16 +129,36 @@ func readAWSCloudConfig(config io.Reader) (*AWSCloudConfig, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Global.Region == "" {
|
if cfg.Global.Zone == "" {
|
||||||
return nil, fmt.Errorf("no region specified in configuration file")
|
if metadata != nil {
|
||||||
|
glog.Info("Zone not specified in configuration file; querying AWS metadata service")
|
||||||
|
cfg.Global.Zone, err = getAvailabilityZone(metadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cfg.Global.Zone == "" {
|
||||||
|
return nil, fmt.Errorf("no zone specified in configuration file")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &cfg, nil
|
return &cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAvailabilityZone(metadata AWSMetadata) (string, error) {
|
||||||
|
availabilityZoneBytes, err := metadata.GetMetaData("placement/availability-zone")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if availabilityZoneBytes == nil || len(availabilityZoneBytes) == 0 {
|
||||||
|
return "", fmt.Errorf("Unable to determine availability-zone from instance metadata")
|
||||||
|
}
|
||||||
|
return string(availabilityZoneBytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
// newAWSCloud creates a new instance of AWSCloud.
|
// newAWSCloud creates a new instance of AWSCloud.
|
||||||
func newAWSCloud(config io.Reader, authFunc AuthFunc) (*AWSCloud, error) {
|
func newAWSCloud(config io.Reader, authFunc AuthFunc, metadata AWSMetadata) (*AWSCloud, error) {
|
||||||
cfg, err := readAWSCloudConfig(config)
|
cfg, err := readAWSCloudConfig(config, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read AWS cloud provider config file: %v", err)
|
return nil, fmt.Errorf("unable to read AWS cloud provider config file: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -140,36 +168,25 @@ func newAWSCloud(config io.Reader, authFunc AuthFunc) (*AWSCloud, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We can get the region very easily from the instance-metadata service
|
zone := cfg.Global.Zone
|
||||||
region, ok := aws.Regions[cfg.Global.Region]
|
if len(zone) <= 1 {
|
||||||
|
return nil, fmt.Errorf("invalid AWS zone in config file: %s", zone)
|
||||||
|
}
|
||||||
|
regionName := zone[:len(zone)-1]
|
||||||
|
|
||||||
|
region, ok := aws.Regions[regionName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("not a valid AWS region: %s", cfg.Global.Region)
|
return nil, fmt.Errorf("not a valid AWS zone (unknown region): %s", zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &AWSCloud{
|
return &AWSCloud{
|
||||||
ec2: &GoamzEC2{ec2: ec2.New(auth, region)},
|
ec2: &GoamzEC2{ec2: ec2.New(auth, region)},
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
region: region,
|
region: region,
|
||||||
|
availabilityZone: zone,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *AWSCloud) getAvailabilityZone() (string, error) {
|
|
||||||
// TODO: Do we need sync.Mutex here?
|
|
||||||
availabilityZone := self.availabilityZone
|
|
||||||
if self.availabilityZone == "" {
|
|
||||||
availabilityZoneBytes, err := self.ec2.GetMetaData("placement/availability-zone")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if availabilityZoneBytes == nil || len(availabilityZoneBytes) == 0 {
|
|
||||||
return "", fmt.Errorf("Unable to determine availability-zone from instance metadata")
|
|
||||||
}
|
|
||||||
availabilityZone = string(availabilityZoneBytes)
|
|
||||||
self.availabilityZone = availabilityZone
|
|
||||||
}
|
|
||||||
return availabilityZone, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (aws *AWSCloud) Clusters() (cloudprovider.Clusters, bool) {
|
func (aws *AWSCloud) Clusters() (cloudprovider.Clusters, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
@ -467,12 +484,12 @@ func getResourcesByInstanceType(instanceType string) (*api.NodeResources, error)
|
||||||
|
|
||||||
// GetZone implements Zones.GetZone
|
// GetZone implements Zones.GetZone
|
||||||
func (self *AWSCloud) GetZone() (cloudprovider.Zone, error) {
|
func (self *AWSCloud) GetZone() (cloudprovider.Zone, error) {
|
||||||
availabilityZone, err := self.getAvailabilityZone()
|
if self.availabilityZone == "" {
|
||||||
if err != nil {
|
// Should be unreachable
|
||||||
return cloudprovider.Zone{}, err
|
panic("availabilityZone not set")
|
||||||
}
|
}
|
||||||
return cloudprovider.Zone{
|
return cloudprovider.Zone{
|
||||||
FailureDomain: availabilityZone,
|
FailureDomain: self.availabilityZone,
|
||||||
Region: self.region.Name,
|
Region: self.region.Name,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,27 +29,50 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadAWSCloudConfig(t *testing.T) {
|
func TestReadAWSCloudConfig(t *testing.T) {
|
||||||
_, err1 := readAWSCloudConfig(nil)
|
_, err1 := readAWSCloudConfig(nil, nil)
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
t.Errorf("Should error when no config reader is given")
|
t.Errorf("Should error when no config reader is given")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err2 := readAWSCloudConfig(strings.NewReader(""))
|
_, err2 := readAWSCloudConfig(strings.NewReader(""), nil)
|
||||||
if err2 == nil {
|
if err2 == nil {
|
||||||
t.Errorf("Should error when config is empty")
|
t.Errorf("Should error when config is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err3 := readAWSCloudConfig(strings.NewReader("[global]\n"))
|
_, err3 := readAWSCloudConfig(strings.NewReader("[global]\n"), nil)
|
||||||
if err3 == nil {
|
if err3 == nil {
|
||||||
t.Errorf("Should error when no region is specified")
|
t.Errorf("Should error when no zone is specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err4 := readAWSCloudConfig(strings.NewReader("[global]\nregion = eu-west-1"))
|
cfg, err4 := readAWSCloudConfig(strings.NewReader("[global]\nzone = eu-west-1a"), nil)
|
||||||
if err4 != nil {
|
if err4 != nil {
|
||||||
t.Errorf("Should succeed when a region is specified: %s", err4)
|
t.Errorf("Should succeed when a zone is specified: %s", err4)
|
||||||
}
|
}
|
||||||
if cfg.Global.Region != "eu-west-1" {
|
if cfg.Global.Zone != "eu-west-1a" {
|
||||||
t.Errorf("Should read region from config")
|
t.Errorf("Should read zone from config")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err5 := readAWSCloudConfig(strings.NewReader("[global]\n"), &FakeMetadata{})
|
||||||
|
if err5 == nil {
|
||||||
|
t.Errorf("Should error when no zone is specified in metadata")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err6 := readAWSCloudConfig(strings.NewReader("[global]\n"),
|
||||||
|
&FakeMetadata{availabilityZone: "eu-west-1a"})
|
||||||
|
if err6 != nil {
|
||||||
|
t.Errorf("Should succeed when getting zone from metadata: %s", err6)
|
||||||
|
}
|
||||||
|
if cfg.Global.Zone != "eu-west-1a" {
|
||||||
|
t.Errorf("Should read zone from metadata")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err7 := readAWSCloudConfig(strings.NewReader("[global]\nzone = us-east-1a"),
|
||||||
|
&FakeMetadata{availabilityZone: "eu-west-1a"})
|
||||||
|
if err7 != nil {
|
||||||
|
t.Errorf("Should succeed when zone is specified: %s", err7)
|
||||||
|
}
|
||||||
|
if cfg.Global.Zone != "us-east-1a" {
|
||||||
|
t.Errorf("Should prefer zone from config over metadata")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,29 +81,42 @@ func TestNewAWSCloud(t *testing.T) {
|
||||||
return aws.Auth{"", "", ""}, nil
|
return aws.Auth{"", "", ""}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err1 := newAWSCloud(nil, fakeAuthFunc)
|
_, err1 := newAWSCloud(nil, fakeAuthFunc, nil)
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
t.Errorf("Should error when no config reader is given")
|
t.Errorf("Should error when no config reader is given")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err2 := newAWSCloud(strings.NewReader(
|
_, err2 := newAWSCloud(strings.NewReader(
|
||||||
"[global]\nregion = blahonga"),
|
"[global]\nzone = blahonga"),
|
||||||
fakeAuthFunc)
|
fakeAuthFunc, nil)
|
||||||
if err2 == nil {
|
if err2 == nil {
|
||||||
t.Errorf("Should error when config specifies invalid region")
|
t.Errorf("Should error when config specifies invalid zone")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err3 := newAWSCloud(
|
_, err3 := newAWSCloud(
|
||||||
strings.NewReader("[global]\nregion = eu-west-1"),
|
strings.NewReader("[global]\nzone = eu-west-1a"),
|
||||||
fakeAuthFunc)
|
fakeAuthFunc, nil)
|
||||||
if err3 != nil {
|
if err3 != nil {
|
||||||
t.Errorf("Should succeed when a valid region is specified: %s", err3)
|
t.Errorf("Should succeed when a valid zone is specified: %s", err3)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err4 := newAWSCloud(strings.NewReader(
|
||||||
|
"[global]\n"),
|
||||||
|
fakeAuthFunc, &FakeMetadata{availabilityZone: "us-east-1a"})
|
||||||
|
if err4 != nil {
|
||||||
|
t.Errorf("Should success when zone is in metadata")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err5 := newAWSCloud(strings.NewReader(
|
||||||
|
"[global]\n"),
|
||||||
|
fakeAuthFunc, &FakeMetadata{})
|
||||||
|
if err5 == nil {
|
||||||
|
t.Errorf("Should error when AZ cannot be found in metadata")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FakeEC2 struct {
|
type FakeEC2 struct {
|
||||||
instances []ec2.Instance
|
instances []ec2.Instance
|
||||||
availabilityZone string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FakeEC2) Instances(instanceIds []string, filter *ec2InstanceFilter) (resp *ec2.InstancesResp, err error) {
|
func (self *FakeEC2) Instances(instanceIds []string, filter *ec2InstanceFilter) (resp *ec2.InstancesResp, err error) {
|
||||||
|
@ -95,7 +131,11 @@ func (self *FakeEC2) Instances(instanceIds []string, filter *ec2InstanceFilter)
|
||||||
{"", "", "", nil, matches}}}, nil
|
{"", "", "", nil, matches}}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FakeEC2) GetMetaData(key string) ([]byte, error) {
|
type FakeMetadata struct {
|
||||||
|
availabilityZone string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *FakeMetadata) GetMetaData(key string) ([]byte, error) {
|
||||||
if key == "placement/availability-zone" {
|
if key == "placement/availability-zone" {
|
||||||
return []byte(self.availabilityZone), nil
|
return []byte(self.availabilityZone), nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,19 +147,19 @@ func mockInstancesResp(instances []ec2.Instance) (aws *AWSCloud) {
|
||||||
availabilityZone := "us-west-2d"
|
availabilityZone := "us-west-2d"
|
||||||
return &AWSCloud{
|
return &AWSCloud{
|
||||||
ec2: &FakeEC2{
|
ec2: &FakeEC2{
|
||||||
instances: instances,
|
instances: instances,
|
||||||
availabilityZone: availabilityZone,
|
|
||||||
},
|
},
|
||||||
|
availabilityZone: availabilityZone,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockAvailabilityZone(region string, availabilityZone string) *AWSCloud {
|
func mockAvailabilityZone(region string, availabilityZone string) *AWSCloud {
|
||||||
return &AWSCloud{
|
return &AWSCloud{
|
||||||
ec2: &FakeEC2{
|
ec2: &FakeEC2{},
|
||||||
availabilityZone: availabilityZone,
|
availabilityZone: availabilityZone,
|
||||||
},
|
region: aws.Regions[region],
|
||||||
region: aws.Regions[region],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestList(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue