Add EC2 Launch Template handler for ASG instanceType fetching

This commit is contained in:
Sheldon Kwok 2018-07-06 21:13:35 -07:00
parent 20293c2365
commit 4bd79c8353
3 changed files with 94 additions and 5 deletions

View File

@ -51,6 +51,8 @@ type asg struct {
curSize int
AvailabilityZones []string
LaunchTemplateName string
LaunchTemplateVersion string
LaunchConfigurationName string
Tags []*autoscaling.TagDescription
}
@ -111,6 +113,8 @@ func (m *asgCache) register(asg *asg) bool {
// from zero
existing.AvailabilityZones = asg.AvailabilityZones
existing.LaunchConfigurationName = asg.LaunchConfigurationName
existing.LaunchTemplateName = asg.LaunchTemplateName
existing.LaunchTemplateVersion = asg.LaunchTemplateVersion
existing.Tags = asg.Tags
return true
@ -287,9 +291,13 @@ func (m *asgCache) buildAsgFromAWS(g *autoscaling.Group) (*asg, error) {
MaxSize: int(aws.Int64Value(g.MaxSize)),
SupportScaleToZero: scaleToZeroSupported,
}
if verr := spec.Validate(); verr != nil {
return nil, fmt.Errorf("failed to create node group spec: %v", verr)
}
launchTemplateName, launchTemplateVersion := m.buildLaunchTemplateParams(g)
asg := &asg{
AwsRef: AwsRef{Name: spec.Name},
minSize: spec.MinSize,
@ -298,11 +306,22 @@ func (m *asgCache) buildAsgFromAWS(g *autoscaling.Group) (*asg, error) {
curSize: int(aws.Int64Value(g.DesiredCapacity)),
AvailabilityZones: aws.StringValueSlice(g.AvailabilityZones),
LaunchConfigurationName: aws.StringValue(g.LaunchConfigurationName),
LaunchTemplateName: launchTemplateName,
LaunchTemplateVersion: launchTemplateVersion,
Tags: g.Tags,
}
return asg, nil
}
func (m *asgCache) buildLaunchTemplateParams(g *autoscaling.Group) (string, string) {
if g.LaunchTemplate != nil {
return aws.StringValue(g.LaunchTemplate.LaunchTemplateName), aws.StringValue(g.LaunchTemplate.Version)
}
return "", ""
}
func (m *asgCache) buildInstanceRefFromAWS(instance *autoscaling.Instance) AwsInstanceRef {
providerID := fmt.Sprintf("aws:///%s/%s", aws.StringValue(instance.AvailabilityZone), aws.StringValue(instance.InstanceId))
return AwsInstanceRef{

View File

@ -29,6 +29,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/golang/glog"
"gopkg.in/gcfg.v1"
apiv1 "k8s.io/api/core/v1"
@ -50,6 +51,7 @@ const (
// AwsManager is handles aws communication and data caching.
type AwsManager struct {
service autoScalingWrapper
ec2 ec2Wrapper
asgCache *asgCache
lastRefresh time.Time
}
@ -93,6 +95,7 @@ func createAWSManagerInternal(
manager := &AwsManager{
service: *service,
ec2: ec2Wrapper{ec2.New(session.New())},
asgCache: cache,
}
@ -200,11 +203,6 @@ func (m *AwsManager) GetAsgNodes(ref AwsRef) ([]AwsInstanceRef, error) {
}
func (m *AwsManager) getAsgTemplate(asg *asg) (*asgTemplate, error) {
instanceTypeName, err := m.service.getInstanceTypeByLCName(asg.LaunchConfigurationName)
if err != nil {
return nil, err
}
if len(asg.AvailabilityZones) < 1 {
return nil, fmt.Errorf("Unable to get first AvailabilityZone for %s", asg.Name)
}
@ -216,6 +214,11 @@ func (m *AwsManager) getAsgTemplate(asg *asg) (*asgTemplate, error) {
glog.Warningf("Found multiple availability zones, using %s\n", az)
}
instanceTypeName, err := m.buildInstanceType(asg)
if err != nil {
return nil, err
}
return &asgTemplate{
InstanceType: InstanceTypes[instanceTypeName],
Region: region,
@ -224,6 +227,16 @@ func (m *AwsManager) getAsgTemplate(asg *asg) (*asgTemplate, error) {
}, nil
}
func (m *AwsManager) buildInstanceType(asg *asg) (string, error) {
if asg.LaunchConfigurationName != "" {
return m.service.getInstanceTypeByLCName(asg.LaunchConfigurationName)
} else if asg.LaunchTemplateName != "" && asg.LaunchTemplateVersion != "" {
return m.ec2.getInstanceTypeByLT(asg.LaunchTemplateName, asg.LaunchTemplateVersion)
}
return "", fmt.Errorf("Unable to get instance type from launch config or launch template")
}
func (m *AwsManager) buildNodeFromTemplate(asg *asg, template *asgTemplate) (*apiv1.Node, error) {
node := apiv1.Node{}
nodeName := fmt.Sprintf("%s-asg-%d", asg.Name, rand.Int63())

View File

@ -0,0 +1,57 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
)
type ec2I interface {
DescribeLaunchTemplateVersions(input *ec2.DescribeLaunchTemplateVersionsInput) (*ec2.DescribeLaunchTemplateVersionsOutput, error)
}
type ec2Wrapper struct {
ec2I
}
func (m ec2Wrapper) getInstanceTypeByLT(name string, version string) (string, error) {
params := &ec2.DescribeLaunchTemplateVersionsInput{
LaunchTemplateName: aws.String(name),
Versions: []*string{aws.String(version)},
}
describeData, err := m.DescribeLaunchTemplateVersions(params)
if err != nil {
return "", err
}
if len(describeData.LaunchTemplateVersions) == 0 {
return "", fmt.Errorf("Unable to find template versions")
}
lt := describeData.LaunchTemplateVersions[0]
instanceType := lt.LaunchTemplateData.InstanceType
if instanceType == nil {
return "", fmt.Errorf("Unable to find instance type within launch template")
}
return aws.StringValue(instanceType), nil
}