forked from juju/juju
/
environ.go
364 lines (310 loc) · 11.2 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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
// Copyright 2020 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package ecs
import (
"sync"
"github.com/DavinZhang/juju/docker"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs/ecsiface"
jujuclock "github.com/juju/clock"
"github.com/juju/errors"
"github.com/juju/names/v4"
"github.com/juju/version/v2"
"github.com/DavinZhang/juju/caas"
"github.com/DavinZhang/juju/core/annotations"
"github.com/DavinZhang/juju/core/application"
"github.com/DavinZhang/juju/core/watcher"
"github.com/DavinZhang/juju/environs"
"github.com/DavinZhang/juju/environs/cloudspec"
"github.com/DavinZhang/juju/environs/config"
envcontext "github.com/DavinZhang/juju/environs/context"
)
type environ struct {
name string
clusterName string
clock jujuclock.Clock
// modelUUID is the UUID of the model this client acts on.
modelUUID string
controllerUUID string
lock sync.Mutex
envCfgUnlocked *config.Config
awsCfgUnlocked *aws.Config
clientUnlocked ecsiface.ECSAPI
newECSClient newECSClientFunc
}
type newECSClientFunc func(*aws.Config) (ecsiface.ECSAPI, error)
//go:generate go run github.com/golang/mock/mockgen -package mocks -destination mocks/ecs_mock.go github.com/aws/aws-sdk-go/service/ecs/ecsiface ECSAPI
func newEnviron(
controllerUUID string,
clusterName string,
clock jujuclock.Clock,
envCfg *config.Config,
awsCfg *aws.Config,
newECSClient func(*aws.Config) (ecsiface.ECSAPI, error),
) (_ *environ, err error) {
if controllerUUID == "" {
return nil, errors.NotValidf("controllerUUID is required")
}
if clusterName == "" {
return nil, errors.NotValidf("clusterName is required")
}
newCfg, err := providerInstance.newConfig(envCfg)
if err != nil {
return nil, errors.Trace(err)
}
modelUUID := newCfg.UUID()
if modelUUID == "" {
return nil, errors.NotValidf("modelUUID is required")
}
env := &environ{
name: envCfg.Name(),
clusterName: clusterName,
clock: clock,
modelUUID: modelUUID,
controllerUUID: controllerUUID,
envCfgUnlocked: envCfg,
awsCfgUnlocked: awsCfg,
newECSClient: newECSClient,
}
if env.clientUnlocked, err = newECSClient(awsCfg); err != nil {
return nil, errors.Trace(err)
}
return env, nil
}
func (env *environ) client() ecsiface.ECSAPI {
env.lock.Lock()
defer env.lock.Unlock()
client := env.clientUnlocked
return client
}
// APIVersion returns the version info for the cluster.
func (env *environ) APIVersion() (string, error) {
// TODO(ecs)
return "", nil
}
// Version returns cluster version information.
func (env *environ) Version() (ver *version.Number, err error) {
// TODO(ecs)
return nil, nil
}
// Provider is part of the Broker interface.
func (*environ) Provider() caas.ContainerEnvironProvider {
return providerInstance
}
// SetCloudSpec is specified in the environs.Environ interface.
func (env *environ) SetCloudSpec(spec cloudspec.CloudSpec) (err error) {
env.lock.Lock()
defer env.lock.Unlock()
// env.clusterName = ???
if env.awsCfgUnlocked, err = cloudSpecToAWSConfig(spec); err != nil {
return errors.Annotate(err, "validating cloud spec")
}
if env.clientUnlocked, err = newECSClient(env.awsCfgUnlocked); err != nil {
return errors.Trace(err)
}
return nil
}
// Config returns environ config.
func (env *environ) Config() *config.Config {
env.lock.Lock()
defer env.lock.Unlock()
cfg := env.envCfgUnlocked
return cfg
}
// SetConfig is specified in the Environ interface.
func (env *environ) SetConfig(cfg *config.Config) error {
env.lock.Lock()
defer env.lock.Unlock()
newCfg, err := providerInstance.newConfig(cfg)
if err != nil {
return errors.Trace(err)
}
env.name = newCfg.Config.Name()
env.envCfgUnlocked = newCfg.Config
return nil
}
// CheckCloudCredentials verifies the the cloud credentials provided to the
// broker are functioning.
func (env *environ) CheckCloudCredentials() error {
// TODO(ecs)
return nil
}
// AnnotateUnit annotates the specified pod (name or uid) with a unit tag.
func (env *environ) AnnotateUnit(appName string, mode caas.DeploymentMode, podName string, unit names.UnitTag) error {
// TODO(ecs)
return nil
}
// PrepareForBootstrap prepares for bootstraping a controller.
func (env *environ) PrepareForBootstrap(ctx environs.BootstrapContext, controllerName string) error {
// TODO(ecs)
return nil
}
// Bootstrap deploys controller with mongoDB together into ecs cluster.
func (env *environ) Bootstrap(
ctx environs.BootstrapContext, callCtx envcontext.ProviderCallContext, args environs.BootstrapParams,
) (*environs.BootstrapResult, error) {
// TODO(ecs)
return nil, nil
}
// Create implements environs.BootstrapEnviron.
func (env *environ) Create(envcontext.ProviderCallContext, environs.CreateParams) error {
return nil
}
func (env *environ) CurrentModel() string {
env.lock.Lock()
defer env.lock.Unlock()
// TODO(ecs): remove from caas.Broker?
return env.envCfgUnlocked.Name()
}
// DeleteService deletes the specified service with all related resources.
func (env *environ) DeleteService(appName string) (err error) {
// TODO(ecs)
return nil
}
// Destroy is part of the Broker interface.
func (env *environ) Destroy(callbacks envcontext.ProviderCallContext) (err error) {
// TODO(ecs)
return nil
}
// DestroyController implements the Environ interface.
func (env *environ) DestroyController(ctx envcontext.ProviderCallContext, controllerUUID string) error {
// TODO(ecs)
return nil
}
// EnsureService creates or updates a service for pods with the given params.
func (env *environ) EnsureService(
appName string,
statusCallback caas.StatusCallbackFunc,
params *caas.ServiceParams,
numUnits int,
config application.ConfigAttributes,
) (err error) {
// TODO(ecs): remove from caas.Broker?
return nil
}
// ExposeService sets up external access to the specified application.
func (env *environ) ExposeService(appName string, resourceTags map[string]string, config application.ConfigAttributes) error {
// TODO(ecs): remove from caas.Broker?
return nil
}
// GetAnnotations returns current namespace's annotations.
func (env *environ) GetAnnotations() annotations.Annotation {
// TODO(ecs): remove from caas.Broker?
return nil
}
// GetService returns the service for the specified application.
func (env *environ) GetService(appName string, mode caas.DeploymentMode, includeClusterIP bool) (*caas.Service, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// UnexposeService removes external access to the specified service.
func (env *environ) UnexposeService(appName string) error {
// TODO(ecs): remove from caas.Broker?
return nil
}
// Units returns all units and any associated filesystems of the specified application.
// Filesystems are mounted via volumes bound to the unit.
func (env *environ) Units(appName string, mode caas.DeploymentMode) ([]caas.Unit, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// WatchContainerStart returns a watcher which is notified when a container matching containerName regexp
// is starting/restarting. Each string represents the provider id for the unit the container belongs to.
// If containerName regexp matches empty string, then the first workload container
// is used.
func (env *environ) WatchContainerStart(appName string, containerName string) (watcher.StringsWatcher, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// WatchService returns a watcher which notifies when there
// are changes to the deployment of the specified application.
func (env *environ) WatchService(appName string, mode caas.DeploymentMode) (watcher.NotifyWatcher, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// WatchUnits returns a watcher which notifies when there
// are changes to units of the specified application.
func (env *environ) WatchUnits(appName string, mode caas.DeploymentMode) (watcher.NotifyWatcher, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// AdoptResources is called when the model is moved from one
// controller to another using model migration.
func (env *environ) AdoptResources(ctx envcontext.ProviderCallContext, controllerUUID string, fromVersion version.Number) error {
// TODO(ecs): remove from caas.Broker?
return nil
}
// Application returns an Application interface.
func (env *environ) Application(name string, deploymentType caas.DeploymentType) caas.Application {
return newApplication(
name, env.clusterName, env.controllerUUID, env.modelUUID, env.CurrentModel(), deploymentType, env.client(), env.clock,
)
}
// DeleteOperator deletes the specified operator.
func (env *environ) DeleteOperator(appName string) (err error) {
// TODO(ecs): remove from caas.Broker?
return nil
}
// EnsureOperator creates or updates an operator pod with the given application
// name, agent path, and operator config.
func (*environ) EnsureOperator(appName, agentPath string, config *caas.OperatorConfig) (err error) {
// TODO(ecs): remove from caas.Broker?
return nil
}
// Operator returns an Operator with current status and life details.
func (*environ) Operator(appName string) (*caas.Operator, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// OperatorExists indicates if the operator for the specified
// application exists, and whether the operator is terminating.
func (*environ) OperatorExists(appName string) (caas.DeploymentState, error) {
// TODO(ecs): remove from caas.Broker?
return caas.DeploymentState{}, nil
}
// WatchOperator returns a watcher which notifies when there
// are changes to the operator of the specified application.
func (*environ) WatchOperator(appName string) (watcher.NotifyWatcher, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// EnsureModelOperator implements caas broker's interface. Function ensures that
// a model operator for this broker's namespace exists within Kubernetes.
func (env *environ) EnsureModelOperator(
modelUUID, agentPath string, config *caas.ModelOperatorConfig,
) error {
// TODO(ecs): remove from caas.Broker?
return nil
}
// ModelOperator return the model operator config used to create the current
// model operator for this broker
func (*environ) ModelOperator() (*caas.ModelOperatorConfig, error) {
// TODO(ecs): remove from caas.Broker?
return nil, nil
}
// ModelOperatorExists indicates if the model operator for the given broker
// exists
func (*environ) ModelOperatorExists() (bool, error) {
// TODO(ecs): remove from caas.Broker?
return false, nil
}
// PrecheckInstance performs a preflight check on the specified
// series and constraints, ensuring that they are possibly valid for
// creating an instance in this model.
//
// PrecheckInstance is best effort, and not guaranteed to eliminate
// all invalid parameters. If PrecheckInstance returns nil, it is not
// guaranteed that the constraints are valid; if a non-nil error is
// returned, then the constraints are definitely invalid.
func (*environ) PrecheckInstance(ctx envcontext.ProviderCallContext, params environs.PrecheckInstanceParams) error {
// TODO(ecs): remove from caas.Broker?
return nil
}
func (*environ) Upgrade(agentTag string, vers version.Number) error {
// TODO(ecs): remove from caas.Broker?
return nil
}
func (*environ) EnsureImageRepoSecret(imageRepo docker.ImageRepoDetails) error {
// TODO(ecs): remove from caas.Broker?
return nil
}