1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
7
"github.com/juju/errors"
8
"github.com/juju/utils/set"
9
"gopkg.in/juju/charm.v6-unstable"
10
"gopkg.in/juju/charm.v6-unstable/resource"
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/state"
19
common.RegisterStandardFacade("Charms", 2, NewAPI)
22
var getState = func(st *state.State) charmsAccess {
26
// Charms defines the methods on the charms API end point.
27
type Charms interface {
28
List(args params.CharmsList) (params.CharmsListResult, error)
29
CharmInfo(args params.CharmURL) (params.CharmInfo, error)
30
IsMetered(args params.CharmURL) (bool, error)
33
// API implements the charms interface and is the concrete
34
// implementation of the api end point.
37
authorizer facade.Authorizer
40
// NewAPI returns a new charms API facade.
43
resources facade.Resources,
44
authorizer facade.Authorizer,
46
if !authorizer.AuthClient() {
47
return nil, common.ErrPerm
52
authorizer: authorizer,
56
// CharmInfo returns information about the requested charm.
57
// NOTE: thumper 2016-06-29, this is not a bulk call and probably should be.
58
func (a *API) CharmInfo(args params.CharmURL) (params.CharmInfo, error) {
59
curl, err := charm.ParseURL(args.URL)
61
return params.CharmInfo{}, err
63
aCharm, err := a.access.Charm(curl)
65
return params.CharmInfo{}, err
67
info := params.CharmInfo{
68
Revision: aCharm.Revision(),
70
Config: convertCharmConfig(aCharm.Config()),
71
Meta: convertCharmMeta(aCharm.Meta()),
72
Actions: convertCharmActions(aCharm.Actions()),
73
Metrics: convertCharmMetrics(aCharm.Metrics()),
78
// List returns a list of charm URLs currently in the state.
79
// If supplied parameter contains any names, the result will be filtered
80
// to return only the charms with supplied names.
81
func (a *API) List(args params.CharmsList) (params.CharmsListResult, error) {
82
charms, err := a.access.AllCharms()
84
return params.CharmsListResult{}, errors.Annotatef(err, " listing charms ")
87
names := set.NewStrings(args.Names...)
88
checkName := !names.IsEmpty()
89
charmURLs := []string{}
90
for _, aCharm := range charms {
91
charmURL := aCharm.URL()
93
if !names.Contains(charmURL.Name) {
97
charmURLs = append(charmURLs, charmURL.String())
99
return params.CharmsListResult{CharmURLs: charmURLs}, nil
102
// IsMetered returns whether or not the charm is metered.
103
func (a *API) IsMetered(args params.CharmURL) (params.IsMeteredResult, error) {
104
curl, err := charm.ParseURL(args.URL)
106
return params.IsMeteredResult{false}, err
108
aCharm, err := a.access.Charm(curl)
110
return params.IsMeteredResult{false}, err
112
if aCharm.Metrics() != nil && len(aCharm.Metrics().Metrics) > 0 {
113
return params.IsMeteredResult{true}, nil
115
return params.IsMeteredResult{false}, nil
118
func convertCharmConfig(config *charm.Config) map[string]params.CharmOption {
122
result := make(map[string]params.CharmOption)
123
for key, value := range config.Options {
124
result[key] = convertCharmOption(value)
129
func convertCharmOption(opt charm.Option) params.CharmOption {
130
return params.CharmOption{
132
Description: opt.Description,
133
Default: opt.Default,
137
func convertCharmMeta(meta *charm.Meta) *params.CharmMeta {
141
result := ¶ms.CharmMeta{
143
Summary: meta.Summary,
144
Description: meta.Description,
145
Subordinate: meta.Subordinate,
146
Provides: convertCharmRelationMap(meta.Provides),
147
Requires: convertCharmRelationMap(meta.Requires),
148
Peers: convertCharmRelationMap(meta.Peers),
149
ExtraBindings: convertCharmExtraBindingMap(meta.ExtraBindings),
150
Categories: meta.Categories,
153
Storage: convertCharmStorageMap(meta.Storage),
154
PayloadClasses: convertCharmPayloadClassMap(meta.PayloadClasses),
155
Resources: convertCharmResourceMetaMap(meta.Resources),
157
MinJujuVersion: meta.MinJujuVersion.String(),
163
func convertCharmRelationMap(relations map[string]charm.Relation) map[string]params.CharmRelation {
164
if len(relations) == 0 {
167
result := make(map[string]params.CharmRelation)
168
for key, value := range relations {
169
result[key] = convertCharmRelation(value)
174
func convertCharmRelation(relation charm.Relation) params.CharmRelation {
175
return params.CharmRelation{
177
Role: string(relation.Role),
178
Interface: relation.Interface,
179
Optional: relation.Optional,
180
Limit: relation.Limit,
181
Scope: string(relation.Scope),
185
func convertCharmStorageMap(storage map[string]charm.Storage) map[string]params.CharmStorage {
186
if len(storage) == 0 {
189
result := make(map[string]params.CharmStorage)
190
for key, value := range storage {
191
result[key] = convertCharmStorage(value)
196
func convertCharmStorage(storage charm.Storage) params.CharmStorage {
197
return params.CharmStorage{
199
Description: storage.Description,
200
Type: string(storage.Type),
201
Shared: storage.Shared,
202
ReadOnly: storage.ReadOnly,
203
CountMin: storage.CountMin,
204
CountMax: storage.CountMax,
205
MinimumSize: storage.MinimumSize,
206
Location: storage.Location,
207
Properties: storage.Properties,
211
func convertCharmPayloadClassMap(payload map[string]charm.PayloadClass) map[string]params.CharmPayloadClass {
212
if len(payload) == 0 {
215
result := make(map[string]params.CharmPayloadClass)
216
for key, value := range payload {
217
result[key] = convertCharmPayloadClass(value)
222
func convertCharmPayloadClass(payload charm.PayloadClass) params.CharmPayloadClass {
223
return params.CharmPayloadClass{
229
func convertCharmResourceMetaMap(resources map[string]resource.Meta) map[string]params.CharmResourceMeta {
230
if len(resources) == 0 {
233
result := make(map[string]params.CharmResourceMeta)
234
for key, value := range resources {
235
result[key] = convertCharmResourceMeta(value)
240
func convertCharmResourceMeta(meta resource.Meta) params.CharmResourceMeta {
241
return params.CharmResourceMeta{
243
Type: meta.Type.String(),
245
Description: meta.Description,
249
func convertCharmActions(actions *charm.Actions) *params.CharmActions {
253
result := ¶ms.CharmActions{
254
ActionSpecs: convertCharmActionSpecMap(actions.ActionSpecs),
260
func convertCharmActionSpecMap(specs map[string]charm.ActionSpec) map[string]params.CharmActionSpec {
264
result := make(map[string]params.CharmActionSpec)
265
for key, value := range specs {
266
result[key] = convertCharmActionSpec(value)
271
func convertCharmActionSpec(spec charm.ActionSpec) params.CharmActionSpec {
272
return params.CharmActionSpec{
273
Description: spec.Description,
278
func convertCharmMetrics(metrics *charm.Metrics) *params.CharmMetrics {
282
return ¶ms.CharmMetrics{
283
Metrics: convertCharmMetricMap(metrics.Metrics),
287
func convertCharmMetricMap(metrics map[string]charm.Metric) map[string]params.CharmMetric {
288
if len(metrics) == 0 {
291
result := make(map[string]params.CharmMetric)
292
for key, value := range metrics {
293
result[key] = convertCharmMetric(value)
298
func convertCharmMetric(metric charm.Metric) params.CharmMetric {
299
return params.CharmMetric{
300
Type: string(metric.Type),
301
Description: metric.Description,
305
func convertCharmExtraBindingMap(bindings map[string]charm.ExtraBinding) map[string]string {
306
if len(bindings) == 0 {
309
result := make(map[string]string)
310
for key, value := range bindings {
311
result[key] = value.Name