1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
4
// Package cloud defines an API end point for functions dealing with
5
// the controller's cloud definition, and cloud credentials.
9
"github.com/juju/loggo"
10
"gopkg.in/juju/names.v2"
12
"github.com/juju/juju/apiserver/common"
13
"github.com/juju/juju/apiserver/facade"
14
"github.com/juju/juju/apiserver/params"
15
"github.com/juju/juju/cloud"
16
"github.com/juju/juju/state"
19
var logger = loggo.GetLogger("juju.apiserver.cloud")
22
common.RegisterStandardFacade("Cloud", 1, newFacade)
25
// CloudAPI implements the model manager interface and is
26
// the concrete implementation of the api end point.
27
type CloudAPI struct {
29
authorizer facade.Authorizer
31
getCredentialsAuthFunc common.GetAuthFunc
32
getCloudDefaultsAuthFunc common.GetAuthFunc
35
func newFacade(st *state.State, resources facade.Resources, auth facade.Authorizer) (*CloudAPI, error) {
36
return NewCloudAPI(NewStateBackend(st), auth)
39
// NewCloudAPI creates a new API server endpoint for managing the controller's
40
// cloud definition and cloud credentials.
41
func NewCloudAPI(backend Backend, authorizer facade.Authorizer) (*CloudAPI, error) {
42
if !authorizer.AuthClient() {
43
return nil, common.ErrPerm
45
getUserAuthFunc := func() (common.AuthFunc, error) {
46
authUser, _ := authorizer.GetAuthTag().(names.UserTag)
47
isAdmin, err := backend.IsControllerAdministrator(authUser)
51
return func(tag names.Tag) bool {
52
userTag, ok := tag.(names.UserTag)
56
return isAdmin || userTag.Canonical() == authUser.Canonical()
61
authorizer: authorizer,
62
getCredentialsAuthFunc: getUserAuthFunc,
63
getCloudDefaultsAuthFunc: getUserAuthFunc,
67
// Cloud returns the cloud definitions for the specified clouds.
68
func (mm *CloudAPI) Cloud(args params.Entities) (params.CloudResults, error) {
69
results := params.CloudResults{
70
Results: make([]params.CloudResult, len(args.Entities)),
72
one := func(arg params.Entity) (*params.Cloud, error) {
73
tag, err := names.ParseCloudTag(arg.Tag)
77
cloud, err := mm.backend.Cloud(tag.Id())
81
authTypes := make([]string, len(cloud.AuthTypes))
82
for i, authType := range cloud.AuthTypes {
83
authTypes[i] = string(authType)
85
regions := make([]params.CloudRegion, len(cloud.Regions))
86
for i, region := range cloud.Regions {
87
regions[i] = params.CloudRegion{
89
Endpoint: region.Endpoint,
90
StorageEndpoint: region.StorageEndpoint,
96
Endpoint: cloud.Endpoint,
97
StorageEndpoint: cloud.StorageEndpoint,
101
for i, arg := range args.Entities {
102
cloud, err := one(arg)
104
results.Results[i].Error = common.ServerError(err)
106
results.Results[i].Cloud = cloud
112
// CloudDefaults returns the cloud defaults for a set of users.
113
func (mm *CloudAPI) CloudDefaults(args params.Entities) (params.CloudDefaultsResults, error) {
114
results := params.CloudDefaultsResults{
115
Results: make([]params.CloudDefaultsResult, len(args.Entities)),
117
authFunc, err := mm.getCloudDefaultsAuthFunc()
121
controllerModel, err := mm.backend.ControllerModel()
125
for i, arg := range args.Entities {
126
userTag, err := names.ParseUserTag(arg.Tag)
128
results.Results[i].Error = common.ServerError(err)
131
if !authFunc(userTag) {
132
results.Results[i].Error = common.ServerError(common.ErrPerm)
135
isAdmin, err := mm.backend.IsControllerAdministrator(userTag)
137
results.Results[i].Error = common.ServerError(err)
140
cloudDefaults := params.CloudDefaults{
141
CloudTag: names.NewCloudTag(controllerModel.Cloud()).String(),
142
CloudRegion: controllerModel.CloudRegion(),
145
// As a special case, controller admins will default to
146
// using the same credential that was used to bootstrap.
147
cloudDefaults.CloudCredential = controllerModel.CloudCredential()
149
results.Results[i].Result = &cloudDefaults
154
// Credentials returns the cloud credentials for a set of users.
155
func (mm *CloudAPI) Credentials(args params.UserClouds) (params.CloudCredentialsResults, error) {
156
results := params.CloudCredentialsResults{
157
Results: make([]params.CloudCredentialsResult, len(args.UserClouds)),
159
authFunc, err := mm.getCredentialsAuthFunc()
163
for i, arg := range args.UserClouds {
164
userTag, err := names.ParseUserTag(arg.UserTag)
166
results.Results[i].Error = common.ServerError(err)
169
if !authFunc(userTag) {
170
results.Results[i].Error = common.ServerError(common.ErrPerm)
173
cloudTag, err := names.ParseCloudTag(arg.CloudTag)
175
results.Results[i].Error = common.ServerError(err)
178
cloudCredentials, err := mm.backend.CloudCredentials(userTag, cloudTag.Id())
180
results.Results[i].Error = common.ServerError(err)
183
out := make(map[string]params.CloudCredential)
184
for name, credential := range cloudCredentials {
185
out[name] = params.CloudCredential{
186
string(credential.AuthType()),
187
credential.Attributes(),
190
results.Results[i].Credentials = out
195
// UpdateCredentials updates the cloud credentials for a set of users.
196
func (mm *CloudAPI) UpdateCredentials(args params.UsersCloudCredentials) (params.ErrorResults, error) {
197
results := params.ErrorResults{
198
Results: make([]params.ErrorResult, len(args.Users)),
200
authFunc, err := mm.getCredentialsAuthFunc()
204
for i, arg := range args.Users {
205
userTag, err := names.ParseUserTag(arg.UserTag)
207
results.Results[i].Error = common.ServerError(err)
210
if !authFunc(userTag) {
211
results.Results[i].Error = common.ServerError(common.ErrPerm)
214
cloudTag, err := names.ParseCloudTag(arg.CloudTag)
216
results.Results[i].Error = common.ServerError(err)
219
in := make(map[string]cloud.Credential)
220
for name, credential := range arg.Credentials {
221
in[name] = cloud.NewCredential(
222
cloud.AuthType(credential.AuthType), credential.Attributes,
225
if err := mm.backend.UpdateCloudCredentials(userTag, cloudTag.Id(), in); err != nil {
226
results.Results[i].Error = common.ServerError(err)