Enhanced detection of VPC for cloudprovider AWS

* use metadata of instance rather than hardcoded VPC name
* test coverage for retrieval of network metadata
pull/6/head
Christian Simon 2015-09-02 16:28:55 +01:00
parent 64717962cf
commit 1bfba8a590
2 changed files with 73 additions and 7 deletions

View File

@ -1281,12 +1281,41 @@ func (self *AWSCloud) TCPLoadBalancerExists(name, region string) (bool, error) {
return false, nil
}
// Retrieves instance's vpc id from metadata
func (self *AWSCloud) findVPCID() (string, error) {
metadata := self.awsServices.Metadata()
macsBytes, err := metadata.GetMetaData("network/interfaces/macs/")
if err != nil {
return "", fmt.Errorf("Could not list interfaces of the instance", err)
}
// loop over interfaces, first vpc id returned wins
for _, macPath := range strings.Split(string(macsBytes), "\n") {
if len(macPath) == 0 {
continue
}
url := fmt.Sprintf("network/interfaces/macs/%svpc-id", macPath)
vpcIDBytes, err := metadata.GetMetaData(url)
if err != nil {
continue
}
return string(vpcIDBytes), nil
}
return "", fmt.Errorf("Could not find VPC id in instance metadata")
}
// Find the kubernetes VPC
func (self *AWSCloud) findVPC() (*ec2.VPC, error) {
request := &ec2.DescribeVPCsInput{}
name := "kubernetes-vpc"
filters := []*ec2.Filter{newEc2Filter("tag:Name", name)}
// find by vpcID from metadata
vpcID, err := self.findVPCID()
if err != nil {
return nil, err
}
filters := []*ec2.Filter{newEc2Filter("vpc-id", vpcID)}
request.Filters = self.addFilters(filters)
vpcs, err := self.ec2.DescribeVPCs(request)
@ -1301,7 +1330,7 @@ func (self *AWSCloud) findVPC() (*ec2.VPC, error) {
if len(vpcs) == 1 {
return vpcs[0], nil
}
return nil, fmt.Errorf("Found multiple matching VPCs for name: %s", name)
return nil, fmt.Errorf("Found multiple matching VPCs for vpcID = %s", vpcID)
}
// Retrieves the specified security group from the AWS API, or returns nil if not found

View File

@ -104,10 +104,12 @@ func TestReadAWSCloudConfig(t *testing.T) {
}
type FakeAWSServices struct {
availabilityZone string
instances []*ec2.Instance
instanceId string
privateDnsName string
availabilityZone string
instances []*ec2.Instance
instanceId string
privateDnsName string
networkInterfacesMacs []string
networkInterfacesVpcIDs []string
ec2 *FakeEC2
elb *FakeELB
@ -123,6 +125,9 @@ func NewFakeAWSServices() *FakeAWSServices {
s.asg = &FakeASG{aws: s}
s.metadata = &FakeMetadata{aws: s}
s.networkInterfacesMacs = []string{"aa:bb:cc:dd:ee:00", "aa:bb:cc:dd:ee:01"}
s.networkInterfacesVpcIDs = []string{"vpc-mac0", "vpc-mac1"}
s.instanceId = "i-self"
s.privateDnsName = "ip-172-20-0-100.ec2.internal"
var selfInstance ec2.Instance
@ -308,12 +313,28 @@ type FakeMetadata struct {
}
func (self *FakeMetadata) GetMetaData(key string) ([]byte, error) {
networkInterfacesPrefix := "network/interfaces/macs/"
if key == "placement/availability-zone" {
return []byte(self.aws.availabilityZone), nil
} else if key == "instance-id" {
return []byte(self.aws.instanceId), nil
} else if key == "local-hostname" {
return []byte(self.aws.privateDnsName), nil
} else if strings.HasPrefix(key, networkInterfacesPrefix) {
if key == networkInterfacesPrefix {
return []byte(strings.Join(self.aws.networkInterfacesMacs, "/\n") + "/\n"), nil
} else {
keySplit := strings.Split(key, "/")
macParam := keySplit[3]
if len(keySplit) == 5 && keySplit[4] == "vpc-id" {
for i, macElem := range self.aws.networkInterfacesMacs {
if macParam == macElem {
return []byte(self.aws.networkInterfacesVpcIDs[i]), nil
}
}
}
return nil, nil
}
} else {
return nil, nil
}
@ -627,3 +648,19 @@ func TestGetRegion(t *testing.T) {
t.Errorf("Unexpected FailureDomain: %s", zone.FailureDomain)
}
}
func TestFindVPCID(t *testing.T) {
awsServices := NewFakeAWSServices()
c, err := newAWSCloud(strings.NewReader("[global]"), awsServices)
if err != nil {
t.Errorf("Error building aws cloud: %v", err)
return
}
vpcID, err := c.findVPCID()
if err != nil {
t.Errorf("Unexpected error:", err)
}
if vpcID != "vpc-mac0" {
t.Errorf("Unexpected vpcID: %s", vpcID)
}
}