mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-01 15:58:37 +00:00
Merge pull request #22123 from justinsb/aws_awsinstance_refactor
Auto commit by PR queue bot
This commit is contained in:
commit
822374ff95
@ -194,17 +194,18 @@ type InstanceGroupInfo interface {
|
|||||||
|
|
||||||
// AWSCloud is an implementation of Interface, LoadBalancer and Instances for Amazon Web Services.
|
// AWSCloud is an implementation of Interface, LoadBalancer and Instances for Amazon Web Services.
|
||||||
type AWSCloud struct {
|
type AWSCloud struct {
|
||||||
ec2 EC2
|
ec2 EC2
|
||||||
elb ELB
|
elb ELB
|
||||||
asg ASG
|
asg ASG
|
||||||
metadata EC2Metadata
|
metadata EC2Metadata
|
||||||
cfg *AWSCloudConfig
|
cfg *AWSCloudConfig
|
||||||
availabilityZone string
|
region string
|
||||||
region string
|
vpcID string
|
||||||
|
|
||||||
filterTags map[string]string
|
filterTags map[string]string
|
||||||
|
|
||||||
// The AWS instance that we are running on
|
// The AWS instance that we are running on
|
||||||
|
// Note that we cache some state in awsInstance (mountpoints), so we must preserve the instance
|
||||||
selfAWSInstance *awsInstance
|
selfAWSInstance *awsInstance
|
||||||
|
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
@ -368,12 +369,8 @@ func (self *AWSCloud) AddSSHKeyToAllInstances(user string, keyData []byte) error
|
|||||||
return errors.New("unimplemented")
|
return errors.New("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AWSCloud) CurrentNodeName(hostname string) (string, error) {
|
func (c *AWSCloud) CurrentNodeName(hostname string) (string, error) {
|
||||||
selfInstance, err := a.getSelfAWSInstance()
|
return c.selfAWSInstance.nodeName, nil
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return selfInstance.nodeName, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of EC2.Instances
|
// Implementation of EC2.Instances
|
||||||
@ -628,28 +625,32 @@ func newAWSCloud(config io.Reader, awsServices AWSServices) (*AWSCloud, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
awsCloud := &AWSCloud{
|
awsCloud := &AWSCloud{
|
||||||
ec2: ec2,
|
ec2: ec2,
|
||||||
elb: elb,
|
elb: elb,
|
||||||
asg: asg,
|
asg: asg,
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
region: regionName,
|
region: regionName,
|
||||||
availabilityZone: zone,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selfAWSInstance, err := awsCloud.buildSelfAWSInstance()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
awsCloud.selfAWSInstance = selfAWSInstance
|
||||||
|
awsCloud.vpcID = selfAWSInstance.vpcID
|
||||||
|
|
||||||
filterTags := map[string]string{}
|
filterTags := map[string]string{}
|
||||||
if cfg.Global.KubernetesClusterTag != "" {
|
if cfg.Global.KubernetesClusterTag != "" {
|
||||||
filterTags[TagNameKubernetesCluster] = cfg.Global.KubernetesClusterTag
|
filterTags[TagNameKubernetesCluster] = cfg.Global.KubernetesClusterTag
|
||||||
} else {
|
} else {
|
||||||
selfInstance, err := awsCloud.getSelfAWSInstance()
|
// TODO: Clean up double-API query
|
||||||
|
info, err := selfAWSInstance.describeInstance()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
selfInstanceInfo, err := selfInstance.getInfo()
|
for _, tag := range info.Tags {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, tag := range selfInstanceInfo.Tags {
|
|
||||||
if orEmpty(tag.Key) == TagNameKubernetesCluster {
|
if orEmpty(tag.Key) == TagNameKubernetesCluster {
|
||||||
filterTags[TagNameKubernetesCluster] = orEmpty(tag.Value)
|
filterTags[TagNameKubernetesCluster] = orEmpty(tag.Value)
|
||||||
}
|
}
|
||||||
@ -710,15 +711,11 @@ func (aws *AWSCloud) Routes() (cloudprovider.Routes, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NodeAddresses is an implementation of Instances.NodeAddresses.
|
// NodeAddresses is an implementation of Instances.NodeAddresses.
|
||||||
func (aws *AWSCloud) NodeAddresses(name string) ([]api.NodeAddress, error) {
|
func (c *AWSCloud) NodeAddresses(name string) ([]api.NodeAddress, error) {
|
||||||
self, err := aws.getSelfAWSInstance()
|
if c.selfAWSInstance.nodeName == name || len(name) == 0 {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if self.nodeName == name || len(name) == 0 {
|
|
||||||
addresses := []api.NodeAddress{}
|
addresses := []api.NodeAddress{}
|
||||||
|
|
||||||
internalIP, err := aws.metadata.GetMetadata("local-ipv4")
|
internalIP, err := c.metadata.GetMetadata("local-ipv4")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -726,7 +723,7 @@ func (aws *AWSCloud) NodeAddresses(name string) ([]api.NodeAddress, error) {
|
|||||||
// Legacy compatibility: the private ip was the legacy host ip
|
// Legacy compatibility: the private ip was the legacy host ip
|
||||||
addresses = append(addresses, api.NodeAddress{Type: api.NodeLegacyHostIP, Address: internalIP})
|
addresses = append(addresses, api.NodeAddress{Type: api.NodeLegacyHostIP, Address: internalIP})
|
||||||
|
|
||||||
externalIP, err := aws.metadata.GetMetadata("public-ipv4")
|
externalIP, err := c.metadata.GetMetadata("public-ipv4")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//TODO: It would be nice to be able to determine the reason for the failure,
|
//TODO: It would be nice to be able to determine the reason for the failure,
|
||||||
// but the AWS client masks all failures with the same error description.
|
// but the AWS client masks all failures with the same error description.
|
||||||
@ -737,7 +734,7 @@ func (aws *AWSCloud) NodeAddresses(name string) ([]api.NodeAddress, error) {
|
|||||||
|
|
||||||
return addresses, nil
|
return addresses, nil
|
||||||
}
|
}
|
||||||
instance, err := aws.getInstanceByNodeName(name)
|
instance, err := c.getInstanceByNodeName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -770,19 +767,14 @@ func (aws *AWSCloud) NodeAddresses(name string) ([]api.NodeAddress, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExternalID returns the cloud provider ID of the specified instance (deprecated).
|
// ExternalID returns the cloud provider ID of the specified instance (deprecated).
|
||||||
func (aws *AWSCloud) ExternalID(name string) (string, error) {
|
func (c *AWSCloud) ExternalID(name string) (string, error) {
|
||||||
awsInstance, err := aws.getSelfAWSInstance()
|
if c.selfAWSInstance.nodeName == name {
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if awsInstance.nodeName == name {
|
|
||||||
// We assume that if this is run on the instance itself, the instance exists and is alive
|
// We assume that if this is run on the instance itself, the instance exists and is alive
|
||||||
return awsInstance.awsID, nil
|
return c.selfAWSInstance.awsID, nil
|
||||||
} else {
|
} else {
|
||||||
// We must verify that the instance still exists
|
// We must verify that the instance still exists
|
||||||
// Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound)
|
// Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound)
|
||||||
instance, err := aws.findInstanceByNodeName(name)
|
instance, err := c.findInstanceByNodeName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -794,18 +786,13 @@ func (aws *AWSCloud) ExternalID(name string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InstanceID returns the cloud provider ID of the specified instance.
|
// InstanceID returns the cloud provider ID of the specified instance.
|
||||||
func (aws *AWSCloud) InstanceID(name string) (string, error) {
|
func (c *AWSCloud) InstanceID(name string) (string, error) {
|
||||||
awsInstance, err := aws.getSelfAWSInstance()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the future it is possible to also return an endpoint as:
|
// In the future it is possible to also return an endpoint as:
|
||||||
// <endpoint>/<zone>/<instanceid>
|
// <endpoint>/<zone>/<instanceid>
|
||||||
if awsInstance.nodeName == name {
|
if c.selfAWSInstance.nodeName == name {
|
||||||
return "/" + awsInstance.availabilityZone + "/" + awsInstance.awsID, nil
|
return "/" + c.selfAWSInstance.availabilityZone + "/" + c.selfAWSInstance.awsID, nil
|
||||||
} else {
|
} else {
|
||||||
inst, err := aws.getInstanceByNodeName(name)
|
inst, err := c.getInstanceByNodeName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -814,16 +801,11 @@ func (aws *AWSCloud) InstanceID(name string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InstanceType returns the type of the specified instance.
|
// InstanceType returns the type of the specified instance.
|
||||||
func (aws *AWSCloud) InstanceType(name string) (string, error) {
|
func (c *AWSCloud) InstanceType(name string) (string, error) {
|
||||||
awsInstance, err := aws.getSelfAWSInstance()
|
if c.selfAWSInstance.nodeName == name {
|
||||||
if err != nil {
|
return c.selfAWSInstance.instanceType, nil
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if awsInstance.nodeName == name {
|
|
||||||
return awsInstance.instanceType, nil
|
|
||||||
} else {
|
} else {
|
||||||
inst, err := aws.getInstanceByNodeName(name)
|
inst, err := c.getInstanceByNodeName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -891,10 +873,10 @@ func (aws *AWSCloud) List(filter string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetZone implements Zones.GetZone
|
// GetZone implements Zones.GetZone
|
||||||
func (self *AWSCloud) GetZone() (cloudprovider.Zone, error) {
|
func (c *AWSCloud) GetZone() (cloudprovider.Zone, error) {
|
||||||
return cloudprovider.Zone{
|
return cloudprovider.Zone{
|
||||||
FailureDomain: self.availabilityZone,
|
FailureDomain: c.selfAWSInstance.availabilityZone,
|
||||||
Region: self.region,
|
Region: c.region,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,6 +911,12 @@ type awsInstance struct {
|
|||||||
// availability zone the instance resides in
|
// availability zone the instance resides in
|
||||||
availabilityZone string
|
availabilityZone string
|
||||||
|
|
||||||
|
// ID of VPC the instance resides in
|
||||||
|
vpcID string
|
||||||
|
|
||||||
|
// ID of subnet the instance resides in
|
||||||
|
subnetID string
|
||||||
|
|
||||||
// instance type
|
// instance type
|
||||||
instanceType string
|
instanceType string
|
||||||
|
|
||||||
@ -939,8 +927,21 @@ type awsInstance struct {
|
|||||||
deviceMappings map[mountDevice]string
|
deviceMappings map[mountDevice]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAWSInstance(ec2 EC2, awsID, nodeName, availabilityZone, instanceType string) *awsInstance {
|
// newAWSInstance creates a new awsInstance object
|
||||||
self := &awsInstance{ec2: ec2, awsID: awsID, nodeName: nodeName, availabilityZone: availabilityZone, instanceType: instanceType}
|
func newAWSInstance(ec2Service EC2, instance *ec2.Instance) *awsInstance {
|
||||||
|
az := ""
|
||||||
|
if instance.Placement != nil {
|
||||||
|
az = aws.StringValue(instance.Placement.AvailabilityZone)
|
||||||
|
}
|
||||||
|
self := &awsInstance{
|
||||||
|
ec2: ec2Service,
|
||||||
|
awsID: aws.StringValue(instance.InstanceId),
|
||||||
|
nodeName: aws.StringValue(instance.PrivateDnsName),
|
||||||
|
availabilityZone: az,
|
||||||
|
instanceType: aws.StringValue(instance.InstanceType),
|
||||||
|
vpcID: aws.StringValue(instance.VpcId),
|
||||||
|
subnetID: aws.StringValue(instance.SubnetId),
|
||||||
|
}
|
||||||
|
|
||||||
// We lazy-init deviceMappings
|
// We lazy-init deviceMappings
|
||||||
self.deviceMappings = nil
|
self.deviceMappings = nil
|
||||||
@ -956,7 +957,7 @@ func (self *awsInstance) getInstanceType() *awsInstanceType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gets the full information about this instance from the EC2 API
|
// Gets the full information about this instance from the EC2 API
|
||||||
func (self *awsInstance) getInfo() (*ec2.Instance, error) {
|
func (self *awsInstance) describeInstance() (*ec2.Instance, error) {
|
||||||
instanceID := self.awsID
|
instanceID := self.awsID
|
||||||
request := &ec2.DescribeInstancesInput{
|
request := &ec2.DescribeInstancesInput{
|
||||||
InstanceIds: []*string{&instanceID},
|
InstanceIds: []*string{&instanceID},
|
||||||
@ -992,7 +993,7 @@ func (self *awsInstance) getMountDevice(volumeID string, assign bool) (assigned
|
|||||||
|
|
||||||
// We cache both for efficiency and correctness
|
// We cache both for efficiency and correctness
|
||||||
if self.deviceMappings == nil {
|
if self.deviceMappings == nil {
|
||||||
info, err := self.getInfo()
|
info, err := self.describeInstance()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", false, err
|
||||||
}
|
}
|
||||||
@ -1073,15 +1074,22 @@ type awsDisk struct {
|
|||||||
name string
|
name string
|
||||||
// id in AWS
|
// id in AWS
|
||||||
awsID string
|
awsID string
|
||||||
// az which holds the volume
|
|
||||||
az string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAWSDisk(aws *AWSCloud, name string) (*awsDisk, error) {
|
func newAWSDisk(aws *AWSCloud, name string) (*awsDisk, error) {
|
||||||
if !strings.HasPrefix(name, "aws://") {
|
|
||||||
name = "aws://" + aws.availabilityZone + "/" + name
|
|
||||||
}
|
|
||||||
// name looks like aws://availability-zone/id
|
// name looks like aws://availability-zone/id
|
||||||
|
|
||||||
|
// The original idea of the URL-style name was to put the AZ into the
|
||||||
|
// host, so we could find the AZ immediately from the name without
|
||||||
|
// querying the API. But it turns out we don't actually need it for
|
||||||
|
// Ubernetes-Lite, as we put the AZ into the labels on the PV instead.
|
||||||
|
// However, if in future we want to support Ubernetes-Lite
|
||||||
|
// volume-awareness without using PersistentVolumes, we likely will
|
||||||
|
// want the AZ in the host.
|
||||||
|
|
||||||
|
if !strings.HasPrefix(name, "aws://") {
|
||||||
|
name = "aws://" + "" + "/" + name
|
||||||
|
}
|
||||||
url, err := url.Parse(name)
|
url, err := url.Parse(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: Maybe we should pass a URL into the Volume functions
|
// TODO: Maybe we should pass a URL into the Volume functions
|
||||||
@ -1100,19 +1108,13 @@ func newAWSDisk(aws *AWSCloud, name string) (*awsDisk, error) {
|
|||||||
if strings.Contains(awsID, "/") || !strings.HasPrefix(awsID, "vol-") {
|
if strings.Contains(awsID, "/") || !strings.HasPrefix(awsID, "vol-") {
|
||||||
return nil, fmt.Errorf("Invalid format for AWS volume (%s)", name)
|
return nil, fmt.Errorf("Invalid format for AWS volume (%s)", name)
|
||||||
}
|
}
|
||||||
az := url.Host
|
|
||||||
// TODO: Better validation?
|
disk := &awsDisk{ec2: aws.ec2, name: name, awsID: awsID}
|
||||||
// TODO: Default to our AZ? Look it up?
|
|
||||||
// TODO: Should this be a region or an AZ?
|
|
||||||
if az == "" {
|
|
||||||
return nil, fmt.Errorf("Invalid format for AWS volume (%s)", name)
|
|
||||||
}
|
|
||||||
disk := &awsDisk{ec2: aws.ec2, name: name, awsID: awsID, az: az}
|
|
||||||
return disk, nil
|
return disk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the full information about this volume from the EC2 API
|
// Gets the full information about this volume from the EC2 API
|
||||||
func (self *awsDisk) getInfo() (*ec2.Volume, error) {
|
func (self *awsDisk) describeVolume() (*ec2.Volume, error) {
|
||||||
volumeID := self.awsID
|
volumeID := self.awsID
|
||||||
|
|
||||||
request := &ec2.DescribeVolumesInput{
|
request := &ec2.DescribeVolumesInput{
|
||||||
@ -1138,7 +1140,7 @@ func (self *awsDisk) waitForAttachmentStatus(status string) error {
|
|||||||
maxAttempts := 60
|
maxAttempts := 60
|
||||||
|
|
||||||
for {
|
for {
|
||||||
info, err := self.getInfo()
|
info, err := self.describeVolume()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1191,59 +1193,44 @@ func (self *awsDisk) deleteVolume() (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the awsInstance for the EC2 instance on which we are running
|
// Builds the awsInstance for the EC2 instance on which we are running.
|
||||||
// may return nil in case of error
|
// This is called when the AWSCloud is initialized, and should not be called otherwise (because the awsInstance for the local instance is a singleton with drive mapping state)
|
||||||
func (s *AWSCloud) getSelfAWSInstance() (*awsInstance, error) {
|
func (c *AWSCloud) buildSelfAWSInstance() (*awsInstance, error) {
|
||||||
// Note that we cache some state in awsInstance (mountpoints), so we must preserve the instance
|
if c.selfAWSInstance != nil {
|
||||||
|
panic("do not call buildSelfAWSInstance directly")
|
||||||
s.mutex.Lock()
|
}
|
||||||
defer s.mutex.Unlock()
|
instanceId, err := c.metadata.GetMetadata("instance-id")
|
||||||
|
if err != nil {
|
||||||
i := s.selfAWSInstance
|
return nil, fmt.Errorf("error fetching instance-id from ec2 metadata service: %v", err)
|
||||||
if i == nil {
|
|
||||||
instanceId, err := s.metadata.GetMetadata("instance-id")
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error fetching instance-id from ec2 metadata service: %v", err)
|
|
||||||
}
|
|
||||||
// privateDnsName, err := s.metadata.GetMetadata("local-hostname")
|
|
||||||
// See #11543 - need to use ec2 API to get the privateDnsName in case of private dns zone e.g. mydomain.io
|
|
||||||
instance, err := s.getInstanceByID(instanceId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error finding instance %s: %v", instanceId, err)
|
|
||||||
}
|
|
||||||
privateDnsName := aws.StringValue(instance.PrivateDnsName)
|
|
||||||
availabilityZone, err := getAvailabilityZone(s.metadata)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error fetching availability zone from ec2 metadata service: %v", err)
|
|
||||||
}
|
|
||||||
instanceType, err := getInstanceType(s.metadata)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error fetching instance type from ec2 metadata service: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
i = newAWSInstance(s.ec2, instanceId, privateDnsName, availabilityZone, instanceType)
|
|
||||||
s.selfAWSInstance = i
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return i, nil
|
// We want to fetch the hostname via the EC2 metadata service
|
||||||
|
// (`GetMetadata("local-hostname")`): But see #11543 - we need to use
|
||||||
|
// the EC2 API to get the privateDnsName in case of a private DNS zone
|
||||||
|
// e.g. mydomain.io, because the metadata service returns the wrong
|
||||||
|
// hostname. Once we're doing that, we might as well get all our
|
||||||
|
// information from the instance returned by the EC2 API - it is a
|
||||||
|
// single API call to get all the information, and it means we don't
|
||||||
|
// have two code paths.
|
||||||
|
instance, err := c.getInstanceByID(instanceId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error finding instance %s: %v", instanceId, err)
|
||||||
|
}
|
||||||
|
return newAWSInstance(c.ec2, instance), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the awsInstance with node-name nodeName, or the 'self' instance if nodeName == ""
|
// Gets the awsInstance with node-name nodeName, or the 'self' instance if nodeName == ""
|
||||||
func (aws *AWSCloud) getAwsInstance(nodeName string) (*awsInstance, error) {
|
func (c *AWSCloud) getAwsInstance(nodeName string) (*awsInstance, error) {
|
||||||
var awsInstance *awsInstance
|
var awsInstance *awsInstance
|
||||||
var err error
|
|
||||||
if nodeName == "" {
|
if nodeName == "" {
|
||||||
awsInstance, err = aws.getSelfAWSInstance()
|
awsInstance = c.selfAWSInstance
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error getting self-instance: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
instance, err := aws.getInstanceByNodeName(nodeName)
|
instance, err := c.getInstanceByNodeName(nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error finding instance %s: %v", nodeName, err)
|
return nil, fmt.Errorf("error finding instance %s: %v", nodeName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
awsInstance = newAWSInstance(aws.ec2, orEmpty(instance.InstanceId), orEmpty(instance.PrivateDnsName), orEmpty(instance.Placement.AvailabilityZone), orEmpty(instance.InstanceType))
|
awsInstance = newAWSInstance(c.ec2, instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
return awsInstance, nil
|
return awsInstance, nil
|
||||||
@ -1382,10 +1369,13 @@ func (aws *AWSCloud) DetachDisk(diskName string, instanceName string) (string, e
|
|||||||
|
|
||||||
// Implements Volumes.CreateVolume
|
// Implements Volumes.CreateVolume
|
||||||
func (s *AWSCloud) CreateDisk(volumeOptions *VolumeOptions) (string, error) {
|
func (s *AWSCloud) CreateDisk(volumeOptions *VolumeOptions) (string, error) {
|
||||||
// TODO: Should we tag this with the cluster id (so it gets deleted when the cluster does?)
|
// Default to creating in the current zone
|
||||||
|
// TODO: Spread across zones?
|
||||||
|
createAZ := s.selfAWSInstance.availabilityZone
|
||||||
|
|
||||||
|
// TODO: Should we tag this with the cluster id (so it gets deleted when the cluster does?)
|
||||||
request := &ec2.CreateVolumeInput{}
|
request := &ec2.CreateVolumeInput{}
|
||||||
request.AvailabilityZone = &s.availabilityZone
|
request.AvailabilityZone = &createAZ
|
||||||
volSize := int64(volumeOptions.CapacityGB)
|
volSize := int64(volumeOptions.CapacityGB)
|
||||||
request.Size = &volSize
|
request.Size = &volSize
|
||||||
request.VolumeType = aws.String(DefaultVolumeType)
|
request.VolumeType = aws.String(DefaultVolumeType)
|
||||||
@ -1415,8 +1405,8 @@ func (s *AWSCloud) CreateDisk(volumeOptions *VolumeOptions) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements Volumes.DeleteDisk
|
// Implements Volumes.DeleteDisk
|
||||||
func (aws *AWSCloud) DeleteDisk(volumeName string) (bool, error) {
|
func (c *AWSCloud) DeleteDisk(volumeName string) (bool, error) {
|
||||||
awsDisk, err := newAWSDisk(aws, volumeName)
|
awsDisk, err := newAWSDisk(c, volumeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -1429,7 +1419,7 @@ func (c *AWSCloud) GetVolumeLabels(volumeName string) (map[string]string, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
info, err := awsDisk.getInfo()
|
info, err := awsDisk.describeVolume()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1810,7 +1800,7 @@ func (s *AWSCloud) ensureClusterTags(resourceID string, tags []*ec2.Tag) error {
|
|||||||
// Makes sure the security group exists.
|
// Makes sure the security group exists.
|
||||||
// For multi-cluster isolation, name must be globally unique, for example derived from the service UUID.
|
// For multi-cluster isolation, name must be globally unique, for example derived from the service UUID.
|
||||||
// Returns the security group id or error
|
// Returns the security group id or error
|
||||||
func (s *AWSCloud) ensureSecurityGroup(name string, description string, vpcID string) (string, error) {
|
func (s *AWSCloud) ensureSecurityGroup(name string, description string) (string, error) {
|
||||||
groupID := ""
|
groupID := ""
|
||||||
attempt := 0
|
attempt := 0
|
||||||
for {
|
for {
|
||||||
@ -1819,7 +1809,7 @@ func (s *AWSCloud) ensureSecurityGroup(name string, description string, vpcID st
|
|||||||
request := &ec2.DescribeSecurityGroupsInput{}
|
request := &ec2.DescribeSecurityGroupsInput{}
|
||||||
filters := []*ec2.Filter{
|
filters := []*ec2.Filter{
|
||||||
newEc2Filter("group-name", name),
|
newEc2Filter("group-name", name),
|
||||||
newEc2Filter("vpc-id", vpcID),
|
newEc2Filter("vpc-id", s.vpcID),
|
||||||
}
|
}
|
||||||
// Note that we do _not_ add our tag filters; group-name + vpc-id is the EC2 primary key.
|
// Note that we do _not_ add our tag filters; group-name + vpc-id is the EC2 primary key.
|
||||||
// However, we do check that it matches our tags.
|
// However, we do check that it matches our tags.
|
||||||
@ -1846,7 +1836,7 @@ func (s *AWSCloud) ensureSecurityGroup(name string, description string, vpcID st
|
|||||||
}
|
}
|
||||||
|
|
||||||
createRequest := &ec2.CreateSecurityGroupInput{}
|
createRequest := &ec2.CreateSecurityGroupInput{}
|
||||||
createRequest.VpcId = &vpcID
|
createRequest.VpcId = &s.vpcID
|
||||||
createRequest.GroupName = &name
|
createRequest.GroupName = &name
|
||||||
createRequest.Description = &description
|
createRequest.Description = &description
|
||||||
|
|
||||||
@ -1928,9 +1918,9 @@ func (s *AWSCloud) createTags(resourceID string, tags map[string]string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AWSCloud) listPublicSubnetIDsinVPC(vpcId string) ([]string, error) {
|
func (s *AWSCloud) listPublicSubnetIDsinVPC() ([]string, error) {
|
||||||
sRequest := &ec2.DescribeSubnetsInput{}
|
sRequest := &ec2.DescribeSubnetsInput{}
|
||||||
vpcIdFilter := newEc2Filter("vpc-id", vpcId)
|
vpcIdFilter := newEc2Filter("vpc-id", s.vpcID)
|
||||||
var filters []*ec2.Filter
|
var filters []*ec2.Filter
|
||||||
filters = append(filters, vpcIdFilter)
|
filters = append(filters, vpcIdFilter)
|
||||||
filters = s.addFilters(filters)
|
filters = s.addFilters(filters)
|
||||||
@ -2061,14 +2051,8 @@ func (s *AWSCloud) EnsureLoadBalancer(name, region string, publicIP net.IP, port
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vpcId, err := s.findVPCID()
|
|
||||||
if err != nil {
|
|
||||||
glog.Error("Error finding VPC", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct list of configured subnets
|
// Construct list of configured subnets
|
||||||
subnetIDs, err := s.listPublicSubnetIDsinVPC(vpcId)
|
subnetIDs, err := s.listPublicSubnetIDsinVPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Error("Error listing subnets in VPC: ", err)
|
glog.Error("Error listing subnets in VPC: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -2079,7 +2063,7 @@ func (s *AWSCloud) EnsureLoadBalancer(name, region string, publicIP net.IP, port
|
|||||||
{
|
{
|
||||||
sgName := "k8s-elb-" + name
|
sgName := "k8s-elb-" + name
|
||||||
sgDescription := fmt.Sprintf("Security group for Kubernetes ELB %s (%v)", name, serviceName)
|
sgDescription := fmt.Sprintf("Security group for Kubernetes ELB %s (%v)", name, serviceName)
|
||||||
securityGroupID, err = s.ensureSecurityGroup(sgName, sgDescription, vpcId)
|
securityGroupID, err = s.ensureSecurityGroup(sgName, sgDescription)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Error("Error creating load balancer security group: ", err)
|
glog.Error("Error creating load balancer security group: ", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -110,14 +110,11 @@ func TestReadAWSCloudConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FakeAWSServices struct {
|
type FakeAWSServices struct {
|
||||||
availabilityZone string
|
region string
|
||||||
instances []*ec2.Instance
|
instances []*ec2.Instance
|
||||||
instanceId string
|
selfInstance *ec2.Instance
|
||||||
privateDnsName string
|
|
||||||
networkInterfacesMacs []string
|
networkInterfacesMacs []string
|
||||||
networkInterfacesVpcIDs []string
|
networkInterfacesVpcIDs []string
|
||||||
internalIP string
|
|
||||||
externalIP string
|
|
||||||
|
|
||||||
ec2 *FakeEC2
|
ec2 *FakeEC2
|
||||||
elb *FakeELB
|
elb *FakeELB
|
||||||
@ -127,7 +124,7 @@ type FakeAWSServices struct {
|
|||||||
|
|
||||||
func NewFakeAWSServices() *FakeAWSServices {
|
func NewFakeAWSServices() *FakeAWSServices {
|
||||||
s := &FakeAWSServices{}
|
s := &FakeAWSServices{}
|
||||||
s.availabilityZone = "us-east-1a"
|
s.region = "us-east-1"
|
||||||
s.ec2 = &FakeEC2{aws: s}
|
s.ec2 = &FakeEC2{aws: s}
|
||||||
s.elb = &FakeELB{aws: s}
|
s.elb = &FakeELB{aws: s}
|
||||||
s.asg = &FakeASG{aws: s}
|
s.asg = &FakeASG{aws: s}
|
||||||
@ -136,14 +133,16 @@ func NewFakeAWSServices() *FakeAWSServices {
|
|||||||
s.networkInterfacesMacs = []string{"aa:bb:cc:dd:ee:00", "aa:bb:cc:dd:ee:01"}
|
s.networkInterfacesMacs = []string{"aa:bb:cc:dd:ee:00", "aa:bb:cc:dd:ee:01"}
|
||||||
s.networkInterfacesVpcIDs = []string{"vpc-mac0", "vpc-mac1"}
|
s.networkInterfacesVpcIDs = []string{"vpc-mac0", "vpc-mac1"}
|
||||||
|
|
||||||
s.instanceId = "i-self"
|
selfInstance := &ec2.Instance{}
|
||||||
s.privateDnsName = "ip-172-20-0-100.ec2.internal"
|
selfInstance.InstanceId = aws.String("i-self")
|
||||||
s.internalIP = "192.168.0.1"
|
selfInstance.Placement = &ec2.Placement{
|
||||||
s.externalIP = "1.2.3.4"
|
AvailabilityZone: aws.String("us-east-1a"),
|
||||||
var selfInstance ec2.Instance
|
}
|
||||||
selfInstance.InstanceId = &s.instanceId
|
selfInstance.PrivateDnsName = aws.String("ip-172-20-0-100.ec2.internal")
|
||||||
selfInstance.PrivateDnsName = &s.privateDnsName
|
selfInstance.PrivateIpAddress = aws.String("192.168.0.1")
|
||||||
s.instances = []*ec2.Instance{&selfInstance}
|
selfInstance.PublicIpAddress = aws.String("1.2.3.4")
|
||||||
|
s.selfInstance = selfInstance
|
||||||
|
s.instances = []*ec2.Instance{selfInstance}
|
||||||
|
|
||||||
var tag ec2.Tag
|
var tag ec2.Tag
|
||||||
tag.Key = aws.String(TagNameKubernetesCluster)
|
tag.Key = aws.String(TagNameKubernetesCluster)
|
||||||
@ -154,12 +153,10 @@ func NewFakeAWSServices() *FakeAWSServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *FakeAWSServices) withAz(az string) *FakeAWSServices {
|
func (s *FakeAWSServices) withAz(az string) *FakeAWSServices {
|
||||||
s.availabilityZone = az
|
if s.selfInstance.Placement == nil {
|
||||||
return s
|
s.selfInstance.Placement = &ec2.Placement{}
|
||||||
}
|
}
|
||||||
|
s.selfInstance.Placement.AvailabilityZone = aws.String(az)
|
||||||
func (s *FakeAWSServices) withInstances(instances []*ec2.Instance) *FakeAWSServices {
|
|
||||||
s.instances = instances
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +202,7 @@ func TestNewAWSCloud(t *testing.T) {
|
|||||||
awsServices AWSServices
|
awsServices AWSServices
|
||||||
|
|
||||||
expectError bool
|
expectError bool
|
||||||
zone string
|
region string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"No config reader",
|
"No config reader",
|
||||||
@ -220,14 +217,13 @@ func TestNewAWSCloud(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"Config specifies valid zone",
|
"Config specifies valid zone",
|
||||||
strings.NewReader("[global]\nzone = eu-west-1a"), NewFakeAWSServices(),
|
strings.NewReader("[global]\nzone = eu-west-1a"), NewFakeAWSServices(),
|
||||||
false, "eu-west-1a",
|
false, "eu-west-1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Gets zone from metadata when not in config",
|
"Gets zone from metadata when not in config",
|
||||||
|
|
||||||
strings.NewReader("[global]\n"),
|
strings.NewReader("[global]\n"),
|
||||||
NewFakeAWSServices(),
|
NewFakeAWSServices(),
|
||||||
false, "us-east-1a",
|
false, "us-east-1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"No zone in config or metadata",
|
"No zone in config or metadata",
|
||||||
@ -247,9 +243,9 @@ func TestNewAWSCloud(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Should succeed for case: %s, got %v", test.name, err)
|
t.Errorf("Should succeed for case: %s, got %v", test.name, err)
|
||||||
} else if c.availabilityZone != test.zone {
|
} else if c.region != test.region {
|
||||||
t.Errorf("Incorrect zone value (%s vs %s) for case: %s",
|
t.Errorf("Incorrect region value (%s vs %s) for case: %s",
|
||||||
c.availabilityZone, test.zone, test.name)
|
c.region, test.region, test.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,8 +305,8 @@ func (self *FakeEC2) DescribeInstances(request *ec2.DescribeInstancesInput) ([]*
|
|||||||
}
|
}
|
||||||
|
|
||||||
found := false
|
found := false
|
||||||
for _, instanceId := range request.InstanceIds {
|
for _, instanceID := range request.InstanceIds {
|
||||||
if *instanceId == *instance.InstanceId {
|
if *instanceID == *instance.InstanceId {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -343,16 +339,21 @@ type FakeMetadata struct {
|
|||||||
|
|
||||||
func (self *FakeMetadata) GetMetadata(key string) (string, error) {
|
func (self *FakeMetadata) GetMetadata(key string) (string, error) {
|
||||||
networkInterfacesPrefix := "network/interfaces/macs/"
|
networkInterfacesPrefix := "network/interfaces/macs/"
|
||||||
|
i := self.aws.selfInstance
|
||||||
if key == "placement/availability-zone" {
|
if key == "placement/availability-zone" {
|
||||||
return self.aws.availabilityZone, nil
|
az := ""
|
||||||
|
if i.Placement != nil {
|
||||||
|
az = aws.StringValue(i.Placement.AvailabilityZone)
|
||||||
|
}
|
||||||
|
return az, nil
|
||||||
} else if key == "instance-id" {
|
} else if key == "instance-id" {
|
||||||
return self.aws.instanceId, nil
|
return aws.StringValue(i.InstanceId), nil
|
||||||
} else if key == "local-hostname" {
|
} else if key == "local-hostname" {
|
||||||
return self.aws.privateDnsName, nil
|
return aws.StringValue(i.PrivateDnsName), nil
|
||||||
} else if key == "local-ipv4" {
|
} else if key == "local-ipv4" {
|
||||||
return self.aws.internalIP, nil
|
return aws.StringValue(i.PrivateIpAddress), nil
|
||||||
} else if key == "public-ipv4" {
|
} else if key == "public-ipv4" {
|
||||||
return self.aws.externalIP, nil
|
return aws.StringValue(i.PublicIpAddress), nil
|
||||||
} else if strings.HasPrefix(key, networkInterfacesPrefix) {
|
} else if strings.HasPrefix(key, networkInterfacesPrefix) {
|
||||||
if key == networkInterfacesPrefix {
|
if key == networkInterfacesPrefix {
|
||||||
return strings.Join(self.aws.networkInterfacesMacs, "/\n") + "/\n", nil
|
return strings.Join(self.aws.networkInterfacesMacs, "/\n") + "/\n", nil
|
||||||
@ -499,22 +500,24 @@ func (a *FakeASG) DescribeAutoScalingGroups(*autoscaling.DescribeAutoScalingGrou
|
|||||||
panic("Not implemented")
|
panic("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockInstancesResp(instances []*ec2.Instance) (*AWSCloud, *FakeAWSServices) {
|
func mockInstancesResp(selfInstance *ec2.Instance, instances []*ec2.Instance) (*AWSCloud, *FakeAWSServices) {
|
||||||
awsServices := NewFakeAWSServices().withInstances(instances)
|
awsServices := NewFakeAWSServices()
|
||||||
return &AWSCloud{
|
awsServices.instances = instances
|
||||||
ec2: awsServices.ec2,
|
awsServices.selfInstance = selfInstance
|
||||||
availabilityZone: awsServices.availabilityZone,
|
awsCloud, err := newAWSCloud(nil, awsServices)
|
||||||
metadata: &FakeMetadata{aws: awsServices},
|
if err != nil {
|
||||||
}, awsServices
|
panic(err)
|
||||||
|
}
|
||||||
|
return awsCloud, awsServices
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockAvailabilityZone(region string, availabilityZone string) *AWSCloud {
|
func mockAvailabilityZone(availabilityZone string) *AWSCloud {
|
||||||
awsServices := NewFakeAWSServices().withAz(availabilityZone)
|
awsServices := NewFakeAWSServices().withAz(availabilityZone)
|
||||||
return &AWSCloud{
|
awsCloud, err := newAWSCloud(nil, awsServices)
|
||||||
ec2: awsServices.ec2,
|
if err != nil {
|
||||||
availabilityZone: awsServices.availabilityZone,
|
panic(err)
|
||||||
region: region,
|
|
||||||
}
|
}
|
||||||
|
return awsCloud
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestList(t *testing.T) {
|
||||||
@ -532,6 +535,7 @@ func TestList(t *testing.T) {
|
|||||||
instance0.Tags = []*ec2.Tag{&tag0}
|
instance0.Tags = []*ec2.Tag{&tag0}
|
||||||
instance0.InstanceId = aws.String("instance0")
|
instance0.InstanceId = aws.String("instance0")
|
||||||
instance0.PrivateDnsName = aws.String("instance0.ec2.internal")
|
instance0.PrivateDnsName = aws.String("instance0.ec2.internal")
|
||||||
|
instance0.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
|
||||||
state0 := ec2.InstanceState{
|
state0 := ec2.InstanceState{
|
||||||
Name: aws.String("running"),
|
Name: aws.String("running"),
|
||||||
}
|
}
|
||||||
@ -545,6 +549,7 @@ func TestList(t *testing.T) {
|
|||||||
instance1.Tags = []*ec2.Tag{&tag1}
|
instance1.Tags = []*ec2.Tag{&tag1}
|
||||||
instance1.InstanceId = aws.String("instance1")
|
instance1.InstanceId = aws.String("instance1")
|
||||||
instance1.PrivateDnsName = aws.String("instance1.ec2.internal")
|
instance1.PrivateDnsName = aws.String("instance1.ec2.internal")
|
||||||
|
instance1.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
|
||||||
state1 := ec2.InstanceState{
|
state1 := ec2.InstanceState{
|
||||||
Name: aws.String("running"),
|
Name: aws.String("running"),
|
||||||
}
|
}
|
||||||
@ -558,6 +563,7 @@ func TestList(t *testing.T) {
|
|||||||
instance2.Tags = []*ec2.Tag{&tag2}
|
instance2.Tags = []*ec2.Tag{&tag2}
|
||||||
instance2.InstanceId = aws.String("instance2")
|
instance2.InstanceId = aws.String("instance2")
|
||||||
instance2.PrivateDnsName = aws.String("instance2.ec2.internal")
|
instance2.PrivateDnsName = aws.String("instance2.ec2.internal")
|
||||||
|
instance2.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
|
||||||
state2 := ec2.InstanceState{
|
state2 := ec2.InstanceState{
|
||||||
Name: aws.String("running"),
|
Name: aws.String("running"),
|
||||||
}
|
}
|
||||||
@ -571,13 +577,14 @@ func TestList(t *testing.T) {
|
|||||||
instance3.Tags = []*ec2.Tag{&tag3}
|
instance3.Tags = []*ec2.Tag{&tag3}
|
||||||
instance3.InstanceId = aws.String("instance3")
|
instance3.InstanceId = aws.String("instance3")
|
||||||
instance3.PrivateDnsName = aws.String("instance3.ec2.internal")
|
instance3.PrivateDnsName = aws.String("instance3.ec2.internal")
|
||||||
|
instance3.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
|
||||||
state3 := ec2.InstanceState{
|
state3 := ec2.InstanceState{
|
||||||
Name: aws.String("running"),
|
Name: aws.String("running"),
|
||||||
}
|
}
|
||||||
instance3.State = &state3
|
instance3.State = &state3
|
||||||
|
|
||||||
instances := []*ec2.Instance{&instance0, &instance1, &instance2, &instance3}
|
instances := []*ec2.Instance{&instance0, &instance1, &instance2, &instance3}
|
||||||
aws, _ := mockInstancesResp(instances)
|
aws, _ := mockInstancesResp(&instance0, instances)
|
||||||
|
|
||||||
table := []struct {
|
table := []struct {
|
||||||
input string
|
input string
|
||||||
@ -616,32 +623,35 @@ func TestNodeAddresses(t *testing.T) {
|
|||||||
var instance2 ec2.Instance
|
var instance2 ec2.Instance
|
||||||
|
|
||||||
//0
|
//0
|
||||||
instance0.InstanceId = aws.String("i-self")
|
instance0.InstanceId = aws.String("i-0")
|
||||||
instance0.PrivateDnsName = aws.String("instance-same.ec2.internal")
|
instance0.PrivateDnsName = aws.String("instance-same.ec2.internal")
|
||||||
instance0.PrivateIpAddress = aws.String("192.168.0.1")
|
instance0.PrivateIpAddress = aws.String("192.168.0.1")
|
||||||
instance0.PublicIpAddress = aws.String("1.2.3.4")
|
instance0.PublicIpAddress = aws.String("1.2.3.4")
|
||||||
instance0.InstanceType = aws.String("c3.large")
|
instance0.InstanceType = aws.String("c3.large")
|
||||||
|
instance0.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
|
||||||
state0 := ec2.InstanceState{
|
state0 := ec2.InstanceState{
|
||||||
Name: aws.String("running"),
|
Name: aws.String("running"),
|
||||||
}
|
}
|
||||||
instance0.State = &state0
|
instance0.State = &state0
|
||||||
|
|
||||||
//1
|
//1
|
||||||
instance1.InstanceId = aws.String("i-self")
|
instance1.InstanceId = aws.String("i-1")
|
||||||
instance1.PrivateDnsName = aws.String("instance-same.ec2.internal")
|
instance1.PrivateDnsName = aws.String("instance-same.ec2.internal")
|
||||||
instance1.PrivateIpAddress = aws.String("192.168.0.2")
|
instance1.PrivateIpAddress = aws.String("192.168.0.2")
|
||||||
instance1.InstanceType = aws.String("c3.large")
|
instance1.InstanceType = aws.String("c3.large")
|
||||||
|
instance1.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
|
||||||
state1 := ec2.InstanceState{
|
state1 := ec2.InstanceState{
|
||||||
Name: aws.String("running"),
|
Name: aws.String("running"),
|
||||||
}
|
}
|
||||||
instance1.State = &state1
|
instance1.State = &state1
|
||||||
|
|
||||||
//2
|
//2
|
||||||
instance2.InstanceId = aws.String("i-self")
|
instance2.InstanceId = aws.String("i-2")
|
||||||
instance2.PrivateDnsName = aws.String("instance-other.ec2.internal")
|
instance2.PrivateDnsName = aws.String("instance-other.ec2.internal")
|
||||||
instance2.PrivateIpAddress = aws.String("192.168.0.1")
|
instance2.PrivateIpAddress = aws.String("192.168.0.1")
|
||||||
instance2.PublicIpAddress = aws.String("1.2.3.4")
|
instance2.PublicIpAddress = aws.String("1.2.3.4")
|
||||||
instance2.InstanceType = aws.String("c3.large")
|
instance2.InstanceType = aws.String("c3.large")
|
||||||
|
instance2.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
|
||||||
state2 := ec2.InstanceState{
|
state2 := ec2.InstanceState{
|
||||||
Name: aws.String("running"),
|
Name: aws.String("running"),
|
||||||
}
|
}
|
||||||
@ -649,19 +659,19 @@ func TestNodeAddresses(t *testing.T) {
|
|||||||
|
|
||||||
instances := []*ec2.Instance{&instance0, &instance1, &instance2}
|
instances := []*ec2.Instance{&instance0, &instance1, &instance2}
|
||||||
|
|
||||||
aws1, _ := mockInstancesResp([]*ec2.Instance{})
|
aws1, _ := mockInstancesResp(&instance0, []*ec2.Instance{&instance0})
|
||||||
_, err1 := aws1.NodeAddresses("instance-mismatch.ec2.internal")
|
_, err1 := aws1.NodeAddresses("instance-mismatch.ec2.internal")
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
t.Errorf("Should error when no instance found")
|
t.Errorf("Should error when no instance found")
|
||||||
}
|
}
|
||||||
|
|
||||||
aws2, _ := mockInstancesResp(instances)
|
aws2, _ := mockInstancesResp(&instance2, instances)
|
||||||
_, err2 := aws2.NodeAddresses("instance-same.ec2.internal")
|
_, err2 := aws2.NodeAddresses("instance-same.ec2.internal")
|
||||||
if err2 == nil {
|
if err2 == nil {
|
||||||
t.Errorf("Should error when multiple instances found")
|
t.Errorf("Should error when multiple instances found")
|
||||||
}
|
}
|
||||||
|
|
||||||
aws3, _ := mockInstancesResp(instances[0:1])
|
aws3, _ := mockInstancesResp(&instance0, instances[0:1])
|
||||||
addrs3, err3 := aws3.NodeAddresses("instance-same.ec2.internal")
|
addrs3, err3 := aws3.NodeAddresses("instance-same.ec2.internal")
|
||||||
if err3 != nil {
|
if err3 != nil {
|
||||||
t.Errorf("Should not error when instance found")
|
t.Errorf("Should not error when instance found")
|
||||||
@ -673,12 +683,12 @@ func TestNodeAddresses(t *testing.T) {
|
|||||||
testHasNodeAddress(t, addrs3, api.NodeLegacyHostIP, "192.168.0.1")
|
testHasNodeAddress(t, addrs3, api.NodeLegacyHostIP, "192.168.0.1")
|
||||||
testHasNodeAddress(t, addrs3, api.NodeExternalIP, "1.2.3.4")
|
testHasNodeAddress(t, addrs3, api.NodeExternalIP, "1.2.3.4")
|
||||||
|
|
||||||
aws4, fakeServices := mockInstancesResp([]*ec2.Instance{})
|
// Fetch from metadata
|
||||||
fakeServices.externalIP = "2.3.4.5"
|
aws4, fakeServices := mockInstancesResp(&instance0, []*ec2.Instance{&instance0})
|
||||||
fakeServices.internalIP = "192.168.0.2"
|
fakeServices.selfInstance.PublicIpAddress = aws.String("2.3.4.5")
|
||||||
aws4.selfAWSInstance = &awsInstance{nodeName: fakeServices.instanceId}
|
fakeServices.selfInstance.PrivateIpAddress = aws.String("192.168.0.2")
|
||||||
|
|
||||||
addrs4, err4 := aws4.NodeAddresses(fakeServices.instanceId)
|
addrs4, err4 := aws4.NodeAddresses(*instance0.PrivateDnsName)
|
||||||
if err4 != nil {
|
if err4 != nil {
|
||||||
t.Errorf("unexpected error: %v", err4)
|
t.Errorf("unexpected error: %v", err4)
|
||||||
}
|
}
|
||||||
@ -687,7 +697,7 @@ func TestNodeAddresses(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetRegion(t *testing.T) {
|
func TestGetRegion(t *testing.T) {
|
||||||
aws := mockAvailabilityZone("us-west-2", "us-west-2e")
|
aws := mockAvailabilityZone("us-west-2e")
|
||||||
zones, ok := aws.Zones()
|
zones, ok := aws.Zones()
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("Unexpected missing zones impl")
|
t.Fatalf("Unexpected missing zones impl")
|
||||||
@ -820,8 +830,6 @@ func TestSubnetIDsinVPC(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
vpcID := "vpc-deadbeef"
|
|
||||||
|
|
||||||
// test with 3 subnets from 3 different AZs
|
// test with 3 subnets from 3 different AZs
|
||||||
subnets := make(map[int]map[string]string)
|
subnets := make(map[int]map[string]string)
|
||||||
subnets[0] = make(map[string]string)
|
subnets[0] = make(map[string]string)
|
||||||
@ -842,7 +850,7 @@ func TestSubnetIDsinVPC(t *testing.T) {
|
|||||||
}
|
}
|
||||||
awsServices.ec2.RouteTables = constructRouteTables(routeTables)
|
awsServices.ec2.RouteTables = constructRouteTables(routeTables)
|
||||||
|
|
||||||
result, err := c.listPublicSubnetIDsinVPC(vpcID)
|
result, err := c.listPublicSubnetIDsinVPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error listing subnets: %v", err)
|
t.Errorf("Error listing subnets: %v", err)
|
||||||
return
|
return
|
||||||
@ -868,7 +876,7 @@ func TestSubnetIDsinVPC(t *testing.T) {
|
|||||||
// test implicit routing table - when subnets are not explicitly linked to a table they should use main
|
// test implicit routing table - when subnets are not explicitly linked to a table they should use main
|
||||||
awsServices.ec2.RouteTables = constructRouteTables(map[string]bool{})
|
awsServices.ec2.RouteTables = constructRouteTables(map[string]bool{})
|
||||||
|
|
||||||
result, err = c.listPublicSubnetIDsinVPC(vpcID)
|
result, err = c.listPublicSubnetIDsinVPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error listing subnets: %v", err)
|
t.Errorf("Error listing subnets: %v", err)
|
||||||
return
|
return
|
||||||
@ -900,7 +908,7 @@ func TestSubnetIDsinVPC(t *testing.T) {
|
|||||||
routeTables["subnet-c0000002"] = true
|
routeTables["subnet-c0000002"] = true
|
||||||
awsServices.ec2.RouteTables = constructRouteTables(routeTables)
|
awsServices.ec2.RouteTables = constructRouteTables(routeTables)
|
||||||
|
|
||||||
result, err = c.listPublicSubnetIDsinVPC(vpcID)
|
result, err = c.listPublicSubnetIDsinVPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error listing subnets: %v", err)
|
t.Errorf("Error listing subnets: %v", err)
|
||||||
return
|
return
|
||||||
@ -928,7 +936,7 @@ func TestSubnetIDsinVPC(t *testing.T) {
|
|||||||
routeTables["subnet-d0000001"] = true
|
routeTables["subnet-d0000001"] = true
|
||||||
routeTables["subnet-d0000002"] = true
|
routeTables["subnet-d0000002"] = true
|
||||||
awsServices.ec2.RouteTables = constructRouteTables(routeTables)
|
awsServices.ec2.RouteTables = constructRouteTables(routeTables)
|
||||||
result, err = c.listPublicSubnetIDsinVPC(vpcID)
|
result, err = c.listPublicSubnetIDsinVPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error listing subnets: %v", err)
|
t.Errorf("Error listing subnets: %v", err)
|
||||||
return
|
return
|
||||||
@ -1177,7 +1185,7 @@ func TestGetVolumeLabels(t *testing.T) {
|
|||||||
awsServices.ec2.On("DescribeVolumes", expectedVolumeRequest).Return([]*ec2.Volume{
|
awsServices.ec2.On("DescribeVolumes", expectedVolumeRequest).Return([]*ec2.Volume{
|
||||||
{
|
{
|
||||||
VolumeId: volumeId,
|
VolumeId: volumeId,
|
||||||
AvailabilityZone: &awsServices.availabilityZone,
|
AvailabilityZone: aws.String("us-east-1a"),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user