forked from juju/juju
/
image.go
89 lines (83 loc) · 3.38 KB
/
image.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright 2011, 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package ec2
import (
"github.com/juju/juju/constraints"
"github.com/juju/juju/environs/imagemetadata"
"github.com/juju/juju/environs/instances"
)
// filterImages returns only that subset of the input (in the same order) that
// this provider finds suitable.
func filterImages(images []*imagemetadata.ImageMetadata, ic *instances.InstanceConstraint) []*imagemetadata.ImageMetadata {
// Gather the images for each available storage type.
imagesByStorage := make(map[string][]*imagemetadata.ImageMetadata)
for _, image := range images {
imagesByStorage[image.Storage] = append(imagesByStorage[image.Storage], image)
}
logger.Debugf("images by storage type %+v", imagesByStorage)
// If a storage constraint has been specified, use that or else default to ssd.
storageTypes := []string{ssdStorage}
if ic != nil && len(ic.Storage) > 0 {
storageTypes = ic.Storage
}
logger.Debugf("filtering storage types %+v", storageTypes)
// Return the first set of images for which we have a storage type match.
for _, storageType := range storageTypes {
if len(imagesByStorage[storageType]) > 0 {
return imagesByStorage[storageType]
}
}
// If the user specifies an image ID during bootstrap, then it will not
// have a storage type.
return imagesByStorage[""]
}
// findInstanceSpec returns an InstanceSpec satisfying the supplied instanceConstraint.
func findInstanceSpec(
controller bool,
allImageMetadata []*imagemetadata.ImageMetadata,
instanceTypes []instances.InstanceType,
ic *instances.InstanceConstraint,
) (*instances.InstanceSpec, error) {
logger.Debugf("received %d image(s)", len(allImageMetadata))
if controller {
ic.Constraints = withDefaultControllerConstraints(ic.Constraints)
} else {
ic.Constraints = withDefaultNonControllerConstraints(ic.Constraints)
}
suitableImages := filterImages(allImageMetadata, ic)
logger.Debugf("found %d suitable image(s)", len(suitableImages))
images := instances.ImageMetadataToImages(suitableImages)
return instances.FindInstanceSpec(images, ic, instanceTypes)
}
// withDefaultControllerConstraints returns the given constraints,
// updated to choose a default instance type appropriate for a
// controller machine. We use this only if the user does not specify
// any constraints that would otherwise control the instance type
// selection.
//
// At the time of writing, this will choose
// - t2.medium, for VPC
// - m3.medium, for EC2-Classic
func withDefaultControllerConstraints(cons constraints.Value) constraints.Value {
if !cons.HasInstanceType() && !cons.HasCpuCores() && !cons.HasCpuPower() && !cons.HasMem() {
var mem uint64 = 3.75 * 1024
cons.Mem = &mem
}
return cons
}
// withDefaultNonControllerConstraints returns the given constraints,
// updated to choose a default instance type appropriate for a
// non-controller machine. We use this only if the user does not
// specify an instance-type, or cpu-power.
//
// At the time of writing, this will choose the cheapest non-burstable
// instance available in the account/region. At the time of writing, that
// is, for example:
// - m3.medium (for EC2-Classic)
// - c4.large (e.g. in ap-south-1)
func withDefaultNonControllerConstraints(cons constraints.Value) constraints.Value {
if !cons.HasInstanceType() && !cons.HasCpuPower() {
cons.CpuPower = instances.CpuPower(100)
}
return cons
}