forked from juju/juju
/
environ.go
181 lines (154 loc) · 4.71 KB
/
environ.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Copyright 2013 Joyent Inc.
// Licensed under the AGPLv3, see LICENCE file for details.
package joyent
import (
"fmt"
"strings"
"sync"
"github.com/joyent/gosdc/cloudapi"
"github.com/juju/errors"
"github.com/juju/version"
"github.com/juju/juju/constraints"
"github.com/juju/juju/environs"
"github.com/juju/juju/environs/config"
"github.com/juju/juju/environs/simplestreams"
"github.com/juju/juju/environs/tags"
"github.com/juju/juju/instance"
"github.com/juju/juju/provider/common"
)
// This file contains the core of the Joyent Environ implementation.
type joyentEnviron struct {
name string
cloud environs.CloudSpec
compute *joyentCompute
lock sync.Mutex // protects ecfg
ecfg *environConfig
}
// newEnviron create a new Joyent environ instance from config.
func newEnviron(cloud environs.CloudSpec, cfg *config.Config) (*joyentEnviron, error) {
env := &joyentEnviron{
name: cfg.Name(),
cloud: cloud,
}
if err := env.SetConfig(cfg); err != nil {
return nil, err
}
var err error
env.compute, err = newCompute(cloud)
if err != nil {
return nil, err
}
return env, nil
}
func (env *joyentEnviron) SetName(envName string) {
env.name = envName
}
func (*joyentEnviron) Provider() environs.EnvironProvider {
return providerInstance
}
// PrecheckInstance is defined on the state.Prechecker interface.
func (env *joyentEnviron) PrecheckInstance(series string, cons constraints.Value, placement string) error {
if placement != "" {
return fmt.Errorf("unknown placement directive: %s", placement)
}
if !cons.HasInstanceType() {
return nil
}
// Constraint has an instance-type constraint so let's see if it is valid.
instanceTypes, err := env.listInstanceTypes()
if err != nil {
return err
}
for _, instanceType := range instanceTypes {
if instanceType.Name == *cons.InstanceType {
return nil
}
}
return fmt.Errorf("invalid Joyent instance %q specified", *cons.InstanceType)
}
func (env *joyentEnviron) SetConfig(cfg *config.Config) error {
env.lock.Lock()
defer env.lock.Unlock()
ecfg, err := providerInstance.newConfig(cfg)
if err != nil {
return err
}
env.ecfg = ecfg
return nil
}
func (env *joyentEnviron) Config() *config.Config {
return env.Ecfg().Config
}
// Create is part of the Environ interface.
func (env *joyentEnviron) Create(environs.CreateParams) error {
if err := verifyCredentials(env); err != nil {
return errors.Trace(err)
}
return nil
}
func (env *joyentEnviron) PrepareForBootstrap(ctx environs.BootstrapContext) error {
if ctx.ShouldVerifyCredentials() {
if err := verifyCredentials(env); err != nil {
return errors.Trace(err)
}
}
return nil
}
func (env *joyentEnviron) Bootstrap(ctx environs.BootstrapContext, args environs.BootstrapParams) (*environs.BootstrapResult, error) {
return common.Bootstrap(ctx, env, args)
}
func (env *joyentEnviron) ControllerInstances(controllerUUID string) ([]instance.Id, error) {
instanceIds := []instance.Id{}
filter := cloudapi.NewFilter()
filter.Set(tagKey("group"), "juju")
filter.Set(tagKey(tags.JujuModel), controllerUUID)
filter.Set(tagKey(tags.JujuIsController), "true")
machines, err := env.compute.cloudapi.ListMachines(filter)
if err != nil || len(machines) == 0 {
return nil, environs.ErrNotBootstrapped
}
for _, m := range machines {
if strings.EqualFold(m.State, "provisioning") || strings.EqualFold(m.State, "running") {
copy := m
ji := &joyentInstance{machine: ©, env: env}
instanceIds = append(instanceIds, ji.Id())
}
}
return instanceIds, nil
}
// AdoptResources is part of the Environ interface.
func (env *joyentEnviron) AdoptResources(controllerUUID string, fromVersion version.Number) error {
// This provider doesn't track instance -> controller.
return nil
}
func (env *joyentEnviron) Destroy() error {
return errors.Trace(common.Destroy(env))
}
// DestroyController implements the Environ interface.
func (env *joyentEnviron) DestroyController(controllerUUID string) error {
// TODO(wallyworld): destroy hosted model resources
return env.Destroy()
}
func (env *joyentEnviron) Ecfg() *environConfig {
env.lock.Lock()
defer env.lock.Unlock()
return env.ecfg
}
// MetadataLookupParams returns parameters which are used to query simplestreams metadata.
func (env *joyentEnviron) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) {
if region == "" {
region = env.cloud.Region
}
return &simplestreams.MetadataLookupParams{
Series: config.PreferredSeries(env.Ecfg()),
Region: region,
Endpoint: env.cloud.Endpoint,
}, nil
}
// Region is specified in the HasRegion interface.
func (env *joyentEnviron) Region() (simplestreams.CloudSpec, error) {
return simplestreams.CloudSpec{
Region: env.cloud.Region,
Endpoint: env.cloud.Endpoint,
}, nil
}