Merge lp:~wallyworld/juju-core/fix-instance-type-matching into lp:~go-bot/juju-core/trunk

Proposed by Ian Booth
Status: Merged
Approved by: Ian Booth
Approved revision: no longer in the source branch.
Merged at revision: 2323
Proposed branch: lp:~wallyworld/juju-core/fix-instance-type-matching
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 231 lines (+94/-55)
4 files modified
environs/instances/instancetype.go (+38/-40)
environs/instances/instancetype_test.go (+53/-12)
provider/ec2/image_test.go (+1/-1)
provider/openstack/local_test.go (+2/-2)
To merge this branch: bzr merge lp:~wallyworld/juju-core/fix-instance-type-matching
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+204159@code.launchpad.net

Commit message

Fix instance type selection

Instance type selection will, by default, choose
an instance with enough memory for mong (1024M).
That is unless the user has specified a memory
constraint. If no matching instances are found,
an error is returned. Previously, instead of
an error an arbitary instance with 1024M would
be chosen.

It's perhaps easiest to see the behaviour by
looking at the tests in instancetype_test. With
the old code, several of the tests fail, especially
the memory ones where other constraints are used also.

Description of the change

Fix instance type selection

Instance type selection will, by default, choose
an instance with enough memory for mong (1024M).
That is unless the user has specified a memory
constraint. If no matching instances are found,
an error is returned. Previously, instead of
an error an arbitary instance with 1024M would
be chosen.

It's perhaps easiest to see the behaviour by
looking at the tests in instancetype_test. With
the old code, several of the tests fail, especially
the memory ones where other constraints are used also.

BTW - I tested on Canonistack and EC2. On Canonistack, the default instance
selection was m1.tiny (512MB) but this branch fixes that so that now
cpu1-ram1-disk10-ephemeral20 (1024MB) is used. On EC2, attempting to deploy with
cpu-cores=9000 results in an error.

https://codereview.appspot.com/58950043/

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) wrote :

Reviewers: mp+204159_code.launchpad.net,

Message:
Please take a look.

Description:
Fix instance type selection

Instance type selection will, by default, choose
an instance with enough memory for mong (1024M).
That is unless the user has specified a memory
constraint. If no matching instances are found,
an error is returned. Previously, instead of
an error an arbitary instance with 1024M would
be chosen.

It's perhaps easiest to see the behaviour by
looking at the tests in instancetype_test. With
the old code, several of the tests fail, especially
the memory ones where other constraints are used also.

https://code.launchpad.net/~wallyworld/juju-core/fix-instance-type-matching/+merge/204159

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/58950043/

Affected files (+86, -40 lines):
   A [revision details]
   M environs/instances/instancetype.go
   M environs/instances/instancetype_test.go

Revision history for this message
Ian Booth (wallyworld) wrote :
Revision history for this message
Ian Booth (wallyworld) wrote :
Revision history for this message
Dimiter Naydenov (dimitern) wrote :

LGTM with some suggestions.

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype.go
File environs/instances/instancetype.go (right):

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype.go#newcode98
environs/instances/instancetype.go:98: // (previously an instance type
with largest available memory was returned even if it didn't
I don't think we need to explain how it was previously.

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype.go#newcode105
environs/instances/instancetype.go:105: minMemCons := ic.Constraints
Why not just:
cons.Mem = uint64(minMemoryHeuristic)
?

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go
File environs/instances/instancetype_test.go (right):

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go#newcode155
environs/instances/instancetype_test.go:155: about: "small mem
specified, use that even though less than needed for mongodb",
I think if the user overrode our minimum memory heuristic, we should at
least print out a warning, saying bootstrap might fail due to
insufficient memory for mongo.

https://codereview.appspot.com/58950043/

Revision history for this message
Ian Booth (wallyworld) wrote :

Please take a look.

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype.go
File environs/instances/instancetype.go (right):

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype.go#newcode98
environs/instances/instancetype.go:98: // (previously an instance type
with largest available memory was returned even if it didn't
On 2014/02/10 08:27:13, dimitern wrote:
> I don't think we need to explain how it was previously.

Done.

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype.go#newcode98
environs/instances/instancetype.go:98: // (previously an instance type
with largest available memory was returned even if it didn't
On 2014/02/10 08:27:13, dimitern wrote:
> I don't think we need to explain how it was previously.

Done.

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype.go#newcode105
environs/instances/instancetype.go:105: minMemCons := ic.Constraints
On 2014/02/10 08:27:13, dimitern wrote:
> Why not just:
> cons.Mem = uint64(minMemoryHeuristic)
> ?

Yeah, i refactored some stuff and left it in a bad state. Fixed. It does
need to be a pointer but there's no need for the intermediate object.

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go
File environs/instances/instancetype_test.go (right):

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go#newcode155
environs/instances/instancetype_test.go:155: about: "small mem
specified, use that even though less than needed for mongodb",
On 2014/02/10 08:27:13, dimitern wrote:
> I think if the user overrode our minimum memory heuristic, we should
at least
> print out a warning, saying bootstrap might fail due to insufficient
memory for
> mongo.

Not sure about that. The user could also specify poorly speced systems
for charms and we don't emit anything there. This behaviour, allowing
the user to specify small memory, is not new - the tests are just being
improved. We have never in the past emitted a warning AFAIK.

https://codereview.appspot.com/58950043/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go
File environs/instances/instancetype_test.go (right):

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go#newcode155
environs/instances/instancetype_test.go:155: about: "small mem
specified, use that even though less than needed for mongodb",
On 2014/02/11 00:39:04, wallyworld wrote:
> On 2014/02/10 08:27:13, dimitern wrote:
> > I think if the user overrode our minimum memory heuristic, we should
at least
> > print out a warning, saying bootstrap might fail due to insufficient
memory
> for
> > mongo.

> Not sure about that. The user could also specify poorly speced systems
for
> charms and we don't emit anything there. This behaviour, allowing the
user to
> specify small memory, is not new - the tests are just being improved.
We have
> never in the past emitted a warning AFAIK.

It's true we never said anything, but it's the UX improvement an
important goal? An overly conservative user might pick 256M so it's
cheap, but then will get frustrated why he can't bootstrap (perhaps
without a nice error in the log).

https://codereview.appspot.com/58950043/

Revision history for this message
William Reade (fwereade) wrote :

LGTM, but an explicit tie-breaker would be really nice.

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go
File environs/instances/instancetype_test.go (right):

https://codereview.appspot.com/58950043/diff/40001/environs/instances/instancetype_test.go#newcode155
environs/instances/instancetype_test.go:155: about: "small mem
specified, use that even though less than needed for mongodb",
On 2014/02/11 09:59:57, dimitern wrote:
> On 2014/02/11 00:39:04, wallyworld wrote:
> > On 2014/02/10 08:27:13, dimitern wrote:
> > > I think if the user overrode our minimum memory heuristic, we
should at
> least
> > > print out a warning, saying bootstrap might fail due to
insufficient memory
> > for
> > > mongo.
> >
> > Not sure about that. The user could also specify poorly speced
systems for
> > charms and we don't emit anything there. This behaviour, allowing
the user to
> > specify small memory, is not new - the tests are just being
improved. We have
> > never in the past emitted a warning AFAIK.

> It's true we never said anything, but it's the UX improvement an
important goal?
> An overly conservative user might pick 256M so it's cheap, but then
will get
> frustrated why he can't bootstrap (perhaps without a nice error in the
log).

We *might* want to do this on a state server (although really we should
just take what we *know* we need in that case) but this isn't the right
layer IMO. They asked explicitly, and they got it ;).

https://codereview.appspot.com/58950043/diff/60001/environs/instances/instancetype.go
File environs/instances/instancetype.go (right):

https://codereview.appspot.com/58950043/diff/60001/environs/instances/instancetype.go#newcode99
environs/instances/instancetype.go:99: // - if no matches and no mem
constraint specified, try again and return any matching instance
"any": would be nice to tie-break equal-greatest-memory machines by cost

https://codereview.appspot.com/58950043/

Revision history for this message
Ian Booth (wallyworld) wrote :

I added a cost based tie breaker

https://codereview.appspot.com/58950043/diff/60001/environs/instances/instancetype.go
File environs/instances/instancetype.go (right):

https://codereview.appspot.com/58950043/diff/60001/environs/instances/instancetype.go#newcode99
environs/instances/instancetype.go:99: // - if no matches and no mem
constraint specified, try again and return any matching instance
On 2014/02/13 15:19:21, fwereade wrote:
> "any": would be nice to tie-break equal-greatest-memory machines by
cost

Done.

https://codereview.appspot.com/58950043/

Revision history for this message
Go Bot (go-bot) wrote :
Download full text (45.2 KiB)

The attempt to merge lp:~wallyworld/juju-core/fix-instance-type-matching into lp:juju-core failed. Below is the output from the failed tests.

ok launchpad.net/juju-core 0.017s
ok launchpad.net/juju-core/agent 1.194s
ok launchpad.net/juju-core/agent/tools 0.213s
ok launchpad.net/juju-core/bzr 6.780s
ok launchpad.net/juju-core/cert 3.008s
ok launchpad.net/juju-core/charm 0.573s
? launchpad.net/juju-core/charm/hooks [no test files]
? launchpad.net/juju-core/charm/testing [no test files]
ok launchpad.net/juju-core/cloudinit 0.037s
ok launchpad.net/juju-core/cloudinit/sshinit 1.142s
ok launchpad.net/juju-core/cmd 0.222s
ok launchpad.net/juju-core/cmd/charm-admin 0.872s
? launchpad.net/juju-core/cmd/charmd [no test files]
? launchpad.net/juju-core/cmd/charmload [no test files]
ok launchpad.net/juju-core/cmd/juju 231.353s
ok launchpad.net/juju-core/cmd/jujud 53.685s
ok launchpad.net/juju-core/cmd/plugins/juju-metadata 10.742s
? launchpad.net/juju-core/cmd/plugins/juju-restore [no test files]
ok launchpad.net/juju-core/constraints 0.026s
ok launchpad.net/juju-core/container 0.052s
ok launchpad.net/juju-core/container/factory 0.052s
ok launchpad.net/juju-core/container/kvm 0.286s
ok launchpad.net/juju-core/container/kvm/mock 0.039s
? launchpad.net/juju-core/container/kvm/testing [no test files]
ok launchpad.net/juju-core/container/lxc 0.322s
? launchpad.net/juju-core/container/lxc/mock [no test files]
? launchpad.net/juju-core/container/lxc/testing [no test files]
? launchpad.net/juju-core/container/testing [no test files]
ok launchpad.net/juju-core/downloader 5.270s
ok launchpad.net/juju-core/environs 3.016s
ok launchpad.net/juju-core/environs/bootstrap 4.429s
ok launchpad.net/juju-core/environs/cloudinit 0.673s
ok launchpad.net/juju-core/environs/config 2.480s
ok launchpad.net/juju-core/environs/configstore 0.039s
ok launchpad.net/juju-core/environs/filestorage 0.031s
ok launchpad.net/juju-core/environs/httpstorage 0.969s
ok launchpad.net/juju-core/environs/imagemetadata 0.640s
? launchpad.net/juju-core/environs/imagemetadata/testing [no test files]
ok launchpad.net/juju-core/environs/instances 0.060s
ok launchpad.net/juju-core/environs/jujutest 0.226s
ok launchpad.net/juju-core/environs/manual 8.993s
ok launchpad.net/juju-core/environs/simplestreams 0.354s
? launchpad.net/juju-core/environs/simplestreams/testing [no test files]
ok launchpad.net/juju-core/environs/sshstorage 1.253s
ok launchpad.net/juju-core/environs/storage 1.158s
ok launchpad.net/juju-core/environs/sync 33.514s
ok launchpad.net/juju-core/environs/testing 0.199s
ok launchpad.net/juju-core/environs/tools 6.880s
? launchpad.net/juju-core/environs/tools/testing [no test files]
ok launchpad.net/juju-core/errors 0.016s
ok launchpad.net/juju-core/instance 0.028s
? launchpad.net/juju-core/instance/testing [no test files]
ok launchpad.net/juju-core/juju 23.377s
ok launchpad.net/juju-core/juju/osenv 0.019s
? launchpad.net/juju-core/juju/testing [no test files]
ok launchpad.net/juju-core/log 0.015s
ok launchpad.net/juju-core/log/syslog 0.023s
ok launchpad.net/juj...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'environs/instances/instancetype.go'
2--- environs/instances/instancetype.go 2013-09-27 18:08:05 +0000
3+++ environs/instances/instancetype.go 2014-02-14 01:03:32 +0000
4@@ -74,52 +74,44 @@
5 // minMemoryHeuristic is the assumed minimum amount of memory (in MB) we prefer in order to run a server (1GB)
6 const minMemoryHeuristic = 1024
7
8+// matchingTypesForConstraint returns instance types from allTypes which match cons.
9+func matchingTypesForConstraint(allTypes []InstanceType, cons constraints.Value) []InstanceType {
10+ var matchingTypes []InstanceType
11+ for _, itype := range allTypes {
12+ itype, ok := itype.match(cons)
13+ if !ok {
14+ continue
15+ }
16+ matchingTypes = append(matchingTypes, itype)
17+ }
18+ return matchingTypes
19+}
20+
21 // getMatchingInstanceTypes returns all instance types matching ic.Constraints and available
22 // in ic.Region, sorted by increasing region-specific cost (if known).
23 func getMatchingInstanceTypes(ic *InstanceConstraint, allInstanceTypes []InstanceType) ([]InstanceType, error) {
24- cons := ic.Constraints
25 region := ic.Region
26 var itypes []InstanceType
27
28- // Iterate over allInstanceTypes, finding matching ones.
29- for _, itype := range allInstanceTypes {
30- itype, ok := itype.match(cons)
31- if !ok {
32- continue
33- }
34- itypes = append(itypes, itype)
35+ // Rules used to select instance types:
36+ // - non memory constraints like cpu-cores etc are always honoured
37+ // - if no mem constraint specified, try opinionated default with enough mem to run a server.
38+ // - if no matches and no mem constraint specified, try again and return any matching instance
39+ // with the largest memory
40+ cons := ic.Constraints
41+ if ic.Constraints.Mem == nil {
42+ minMem := uint64(minMemoryHeuristic)
43+ cons.Mem = &minMem
44 }
45+ itypes = matchingTypesForConstraint(allInstanceTypes, cons)
46
47- if len(itypes) == 0 {
48- // No matching instance types were found, so the fallback is to:
49- // 1. Sort by memory and find the smallest matching both the required architecture
50- // and our own heuristic: minimum amount of memory required to run a realistic server, or
51- // 2. Sort by memory in reverse order and return the largest one, which will hopefully work,
52- // albeit not the best match
53- archCons := constraints.Value{Arch: ic.Constraints.Arch}
54- for _, itype := range allInstanceTypes {
55- itype, ok := itype.match(archCons)
56- if !ok {
57- continue
58- }
59- itypes = append(itypes, itype)
60- }
61- sort.Sort(byMemory(itypes))
62- var fallbackType *InstanceType
63- // 1. check for smallest instance type that can realistically run a server
64- for _, itype := range itypes {
65- if itype.Mem >= minMemoryHeuristic {
66- itcopy := itype
67- fallbackType = &itcopy
68- break
69- }
70- }
71- if fallbackType == nil && len(itypes) > 0 {
72- // 2. just get the one with the largest memory
73- fallbackType = &itypes[len(itypes)-1]
74- }
75- if fallbackType != nil {
76- itypes = []InstanceType{*fallbackType}
77+ // No matches using opinionated default, so if no mem constraint specified,
78+ // look for matching instance with largest memory.
79+ if len(itypes) == 0 && ic.Constraints.Mem == nil {
80+ itypes = matchingTypesForConstraint(allInstanceTypes, ic.Constraints)
81+ if len(itypes) > 0 {
82+ sort.Sort(byMemory(itypes))
83+ itypes = []InstanceType{itypes[len(itypes)-1]}
84 }
85 }
86 // If we have matching instance types, we can return those, sorted by cost.
87@@ -129,7 +121,7 @@
88 }
89
90 // No luck, so report the error.
91- return nil, fmt.Errorf("no instance types in %s matching constraints %q", region, cons)
92+ return nil, fmt.Errorf("no instance types in %s matching constraints %q", region, ic.Constraints)
93 }
94
95 // tagsMatch returns if the tags in wanted all exist in have.
96@@ -185,5 +177,11 @@
97 func (s byMemory) Len() int { return len(s) }
98 func (s byMemory) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
99 func (s byMemory) Less(i, j int) bool {
100- return s[i].Mem < s[j].Mem
101+ inst0, inst1 := &s[i], &s[j]
102+ if inst0.Mem != inst1.Mem {
103+ return s[i].Mem < s[j].Mem
104+ }
105+ // Memory is equal, so use cost as a tie breaker.
106+ // Result is in descending order of cost so instance with lowest cost is used.
107+ return inst0.Cost > inst1.Cost
108 }
109
110=== modified file 'environs/instances/instancetype_test.go'
111--- environs/instances/instancetype_test.go 2013-09-20 02:53:59 +0000
112+++ environs/instances/instancetype_test.go 2014-02-14 01:03:32 +0000
113@@ -140,24 +140,59 @@
114 arches: []string{"arm"},
115 },
116 {
117- about: "fallback instance type, enough memory for mongodb",
118- cons: "mem=8G",
119- itypesToUse: []InstanceType{
120+ about: "enough memory for mongodb if mem not specified",
121+ cons: "cpu-cores=4",
122+ itypesToUse: []InstanceType{
123+ {Id: "5", Name: "it-5", Arches: []string{"amd64"}, Mem: 1024, CpuCores: 2},
124+ {Id: "4", Name: "it-4", Arches: []string{"amd64"}, Mem: 2048, CpuCores: 4},
125+ {Id: "3", Name: "it-3", Arches: []string{"amd64"}, Mem: 1024, CpuCores: 4},
126+ {Id: "2", Name: "it-2", Arches: []string{"amd64"}, Mem: 256, CpuCores: 4},
127+ {Id: "1", Name: "it-1", Arches: []string{"amd64"}, Mem: 512, CpuCores: 4},
128+ },
129+ expectedItypes: []string{"it-3", "it-4"},
130+ },
131+ {
132+ about: "small mem specified, use that even though less than needed for mongodb",
133+ cons: "mem=300M",
134+ itypesToUse: []InstanceType{
135+ {Id: "3", Name: "it-3", Arches: []string{"amd64"}, Mem: 2048},
136+ {Id: "2", Name: "it-2", Arches: []string{"amd64"}, Mem: 256},
137+ {Id: "1", Name: "it-1", Arches: []string{"amd64"}, Mem: 512},
138+ },
139+ expectedItypes: []string{"it-1", "it-3"},
140+ },
141+ {
142+ about: "mem specified and match found",
143+ cons: "mem=4G arch=amd64",
144+ itypesToUse: []InstanceType{
145+ {Id: "4", Name: "it-4", Arches: []string{"arm"}, Mem: 8096},
146 {Id: "3", Name: "it-3", Arches: []string{"amd64"}, Mem: 4096},
147 {Id: "2", Name: "it-2", Arches: []string{"amd64"}, Mem: 2048},
148 {Id: "1", Name: "it-1", Arches: []string{"amd64"}, Mem: 512},
149 },
150+ expectedItypes: []string{"it-3"},
151+ },
152+ {
153+ about: "largest mem available matching other constraints if mem not specified",
154+ cons: "cpu-cores=4",
155+ itypesToUse: []InstanceType{
156+ {Id: "3", Name: "it-3", Arches: []string{"amd64"}, Mem: 1024, CpuCores: 2},
157+ {Id: "2", Name: "it-2", Arches: []string{"amd64"}, Mem: 256, CpuCores: 4},
158+ {Id: "1", Name: "it-1", Arches: []string{"amd64"}, Mem: 512, CpuCores: 4},
159+ },
160+ expectedItypes: []string{"it-1"},
161+ },
162+ {
163+ about: "largest mem available matching other constraints if mem not specified, cost is tie breaker",
164+ cons: "cpu-cores=4",
165+ itypesToUse: []InstanceType{
166+ {Id: "4", Name: "it-4", Arches: []string{"amd64"}, Mem: 1024, CpuCores: 2},
167+ {Id: "3", Name: "it-3", Arches: []string{"amd64"}, Mem: 256, CpuCores: 4},
168+ {Id: "2", Name: "it-2", Arches: []string{"amd64"}, Mem: 512, CpuCores: 4, Cost: 50},
169+ {Id: "1", Name: "it-1", Arches: []string{"amd64"}, Mem: 512, CpuCores: 4, Cost: 100},
170+ },
171 expectedItypes: []string{"it-2"},
172 },
173- {
174- about: "fallback instance type, not enough memory for mongodb",
175- cons: "mem=4G",
176- itypesToUse: []InstanceType{
177- {Id: "2", Name: "it-2", Arches: []string{"amd64"}, Mem: 256},
178- {Id: "1", Name: "it-1", Arches: []string{"amd64"}, Mem: 512},
179- },
180- expectedItypes: []string{"it-1"},
181- },
182 }
183
184 func constraint(region, cons string) *InstanceConstraint {
185@@ -195,6 +230,12 @@
186
187 _, err = getMatchingInstanceTypes(constraint("test", "arch=i386 mem=8G"), instanceTypes)
188 c.Check(err, gc.ErrorMatches, `no instance types in test matching constraints "arch=i386 mem=8192M"`)
189+
190+ _, err = getMatchingInstanceTypes(constraint("test", "cpu-cores=9000"), instanceTypes)
191+ c.Check(err, gc.ErrorMatches, `no instance types in test matching constraints "cpu-cores=9000"`)
192+
193+ _, err = getMatchingInstanceTypes(constraint("test", "mem=90000M"), instanceTypes)
194+ c.Check(err, gc.ErrorMatches, `no instance types in test matching constraints "mem=90000M"`)
195 }
196
197 var instanceTypeMatchTests = []struct {
198
199=== modified file 'provider/ec2/image_test.go'
200--- provider/ec2/image_test.go 2014-01-29 00:14:51 +0000
201+++ provider/ec2/image_test.go 2014-02-14 01:03:32 +0000
202@@ -94,7 +94,7 @@
203 series: "precise",
204 arches: both,
205 cons: "cpu-power=",
206- itype: "t1.micro",
207+ itype: "m1.small",
208 image: "ami-00000033",
209 }, {
210 series: "precise",
211
212=== modified file 'provider/openstack/local_test.go'
213--- provider/openstack/local_test.go 2014-01-29 06:45:16 +0000
214+++ provider/openstack/local_test.go 2014-02-14 01:03:32 +0000
215@@ -530,7 +530,7 @@
216 c.Assert(err, gc.IsNil)
217 c.Assert(stateData.StateInstances, gc.HasLen, 1)
218
219- expectedHardware := instance.MustParseHardware("arch=amd64 cpu-cores=1 mem=512M")
220+ expectedHardware := instance.MustParseHardware("arch=amd64 cpu-cores=1 mem=2G")
221 insts, err := env.AllInstances()
222 c.Assert(err, gc.IsNil)
223 c.Assert(insts, gc.HasLen, 1)
224@@ -609,7 +609,7 @@
225 env := s.Open(c)
226
227 // An error occurs if no suitable image is found.
228- _, err := openstack.FindInstanceSpec(env, "saucy", "amd64", "mem=8G")
229+ _, err := openstack.FindInstanceSpec(env, "saucy", "amd64", "mem=1G")
230 c.Assert(err, gc.ErrorMatches, `no "saucy" images in some-region with arches \[amd64\]`)
231 }
232

Subscribers

People subscribed via source and target branches

to status/vote changes: