forked from juju/juju
/
instance_information.go
94 lines (82 loc) · 2.8 KB
/
instance_information.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
90
91
92
93
94
// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package cloud
import (
"github.com/juju/errors"
"gopkg.in/juju/names.v2"
"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/core/constraints"
"github.com/juju/juju/environs"
"github.com/juju/juju/state/stateenvirons"
)
// EnvironConfigGetter implements environs.EnvironConfigGetter
// in terms of a *state.State.
type cloudEnvironConfigGetter struct {
Backend
region string
}
// CloudSpec implements environs.EnvironConfigGetter.
func (g cloudEnvironConfigGetter) CloudSpec() (environs.CloudSpec, error) {
model, err := g.Model()
if err != nil {
return environs.CloudSpec{}, errors.Trace(err)
}
cloudName := model.Cloud()
regionName := g.region
credentialTag, _ := model.CloudCredential()
return stateenvirons.CloudSpec(g.Backend, cloudName, regionName, credentialTag)
}
// InstanceTypes returns instance type information for the cloud and region
// in which the current model is deployed.
func (api *CloudAPI) InstanceTypes(cons params.CloudInstanceTypesConstraints) (params.InstanceTypesResults, error) {
return instanceTypes(api, environs.GetEnviron, cons)
}
type environGetFunc func(st environs.EnvironConfigGetter, newEnviron environs.NewEnvironFunc) (environs.Environ, error)
func instanceTypes(api *CloudAPI,
environGet environGetFunc,
cons params.CloudInstanceTypesConstraints,
) (params.InstanceTypesResults, error) {
m, err := api.ctlrBackend.Model()
if err != nil {
return params.InstanceTypesResults{}, errors.Trace(err)
}
result := make([]params.InstanceTypesResult, len(cons.Constraints))
// TODO(perrito666) Cache the results to avoid excessive querying of the cloud.
// TODO(perrito666) Add Region<>Cloud validation.
for i, cons := range cons.Constraints {
value := constraints.Value{}
if cons.Constraints != nil {
value = *cons.Constraints
}
backend := cloudEnvironConfigGetter{
Backend: api.backend,
region: cons.CloudRegion,
}
cloudTag, err := names.ParseCloudTag(cons.CloudTag)
if err != nil {
result[i] = params.InstanceTypesResult{Error: common.ServerError(err)}
continue
}
if m.Cloud() != cloudTag.Id() {
result[i] = params.InstanceTypesResult{Error: common.ServerError(errors.NotValidf("asking %s cloud information to %s cloud", cloudTag.Id(), m.Cloud()))}
continue
}
env, err := environGet(backend, environs.New)
if err != nil {
return params.InstanceTypesResults{}, errors.Trace(err)
}
itCons := common.NewInstanceTypeConstraints(
env,
api.callContext,
value,
)
it, err := common.InstanceTypes(itCons)
if err != nil {
result[i] = params.InstanceTypesResult{Error: common.ServerError(err)}
continue
}
result[i] = it
}
return params.InstanceTypesResults{Results: result}, nil
}