Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ec2 refactor, unit test correction #72

Merged
merged 8 commits into from
Jun 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func infoers() map[string]productinfo.ProductInfoer {

switch p {
case recommender.Ec2:
infoer, err = ec2.NewEc2Infoer(ec2.NewPricing(ec2.NewConfig()), viper.GetString(prometheusAddressFlag), viper.GetString(prometheusQueryFlag))
infoer, err = ec2.NewEc2Infoer(viper.GetString(prometheusAddressFlag), viper.GetString(prometheusQueryFlag))
case recommender.Gce:
infoer, err = gce.NewGceInfoer(viper.GetString(gceApiKeyFlag), viper.GetString(gceProjectIdFlag))
case recommender.Azure:
Expand Down
55 changes: 27 additions & 28 deletions productinfo/ec2/productinfo_ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,34 @@ type PricingSource interface {

// Ec2Infoer encapsulates the data and operations needed to access external resources
type Ec2Infoer struct {
pricing PricingSource
session *session.Session
prometheus v1.API
promQuery string
pricingSvc PricingSource
session *session.Session
prometheus v1.API
promQuery string
ec2Describer func(region string) Ec2Describer
}

// Ec2Describer interface for operations describing EC2 artifacts. (a subset of the Ec2 cli operations iused by this app)
type Ec2Describer interface {
DescribeAvailabilityZones(input *ec2.DescribeAvailabilityZonesInput) (*ec2.DescribeAvailabilityZonesOutput, error)
DescribeSpotPriceHistoryPages(input *ec2.DescribeSpotPriceHistoryInput, fn func(*ec2.DescribeSpotPriceHistoryOutput, bool) bool) error
}

// NewEc2Infoer creates a new instance of the infoer
func NewEc2Infoer(pricing PricingSource, prom string, pq string) (*Ec2Infoer, error) {
func NewEc2Infoer(promAddr string, pq string) (*Ec2Infoer, error) {
s, err := session.NewSession()

if err != nil {
log.WithError(err).Error("Error creating AWS session")
return nil, err
}
var promApi v1.API
if prom == "" {
if promAddr == "" {
log.Warn("Prometheus API address is not set, fallback to direct API access.")
promApi = nil
} else {
promClient, err := api.NewClient(api.Config{
Address: prom,
Address: promAddr,
})
if err != nil {
log.WithError(err).Warn("Error creating Prometheus client, fallback to direct API access.")
Expand All @@ -66,29 +74,21 @@ func NewEc2Infoer(pricing PricingSource, prom string, pq string) (*Ec2Infoer, er
}
}

const defaultPricingRegion = "us-east-1"
return &Ec2Infoer{
pricing: pricing,
pricingSvc: pricing.New(s, aws.NewConfig().WithRegion(defaultPricingRegion)),
session: s,
prometheus: promApi,
promQuery: pq,
ec2Describer: func(region string) Ec2Describer {
return ec2.New(s, aws.NewConfig().WithRegion(region))
},
}, nil
}

// NewPricing creates a new PricingSource with the given configuration
func NewPricing(cfg *aws.Config) PricingSource {

s, err := session.NewSession(cfg)
if err != nil {
log.Fatalf("could not create session. error: [%s]", err.Error())
}

pr := pricing.New(s, cfg)
return pr
}

// NewConfig creates a new Config instance and returns a pointer to it
func NewConfig() *aws.Config {
return &aws.Config{Region: aws.String("us-east-1")}
return aws.NewConfig()
}

// Initialize is not needed on EC2 because price info is changing frequently
Expand All @@ -99,7 +99,7 @@ func (e *Ec2Infoer) Initialize() (map[string]map[string]productinfo.Price, error
// GetAttributeValues gets the AttributeValues for the given attribute name
// Delegates to the underlying PricingSource instance and unifies (transforms) the response
func (e *Ec2Infoer) GetAttributeValues(attribute string) (productinfo.AttrValues, error) {
apiValues, err := e.pricing.GetAttributeValues(e.newAttributeValuesInput(attribute))
apiValues, err := e.pricingSvc.GetAttributeValues(e.newAttributeValuesInput(attribute))
if err != nil {
return nil, err
}
Expand All @@ -126,7 +126,7 @@ func (e *Ec2Infoer) GetProducts(regionId string, attrKey string, attrValue produ
var vms []productinfo.VmInfo
log.Debugf("Getting available instance types from AWS API. [region=%s, %s=%s]", regionId, attrKey, attrValue.StrValue)

products, err := e.pricing.GetProducts(e.newGetProductsInput(regionId, attrKey, attrValue))
products, err := e.pricingSvc.GetProducts(e.newGetProductsInput(regionId, attrKey, attrValue))

if err != nil {
return nil, err
Expand Down Expand Up @@ -328,14 +328,14 @@ func (e *Ec2Infoer) GetRegions() (map[string]string, error) {

// GetZones returns the availability zones in a region
func (e *Ec2Infoer) GetZones(region string) ([]string, error) {

var zones []string
ec2Svc := ec2.New(e.session, &aws.Config{Region: aws.String(region)})
azs, err := ec2Svc.DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{})
azs, err := e.ec2Describer(region).DescribeAvailabilityZones(&ec2.DescribeAvailabilityZonesInput{})
if err != nil {
return nil, err
}
for _, az := range azs.AvailabilityZones {
if *az.State == "available" {
if *az.State == ec2.AvailabilityZoneStateAvailable {
zones = append(zones, *az.ZoneName)
}
}
Expand Down Expand Up @@ -377,8 +377,7 @@ func (e *Ec2Infoer) getSpotPricesFromPrometheus(region string) (map[string]produ

func (e *Ec2Infoer) getCurrentSpotPrices(region string) (map[string]productinfo.SpotPriceInfo, error) {
priceInfo := make(map[string]productinfo.SpotPriceInfo)
ec2Svc := ec2.New(e.session, &aws.Config{Region: aws.String(region)})
err := ec2Svc.DescribeSpotPriceHistoryPages(&ec2.DescribeSpotPriceHistoryInput{
err := e.ec2Describer(region).DescribeSpotPriceHistoryPages(&ec2.DescribeSpotPriceHistoryInput{
StartTime: aws.Time(time.Now()),
ProductDescriptions: []*string{aws.String("Linux/UNIX")},
}, func(history *ec2.DescribeSpotPriceHistoryOutput, lastPage bool) bool {
Expand Down
Loading