github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/charms/client.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // charms provides a client for accessing the charms API. 5 package charms 6 7 import ( 8 "github.com/juju/errors" 9 "github.com/juju/version" 10 "gopkg.in/juju/charm.v6" 11 "gopkg.in/juju/charm.v6/resource" 12 13 "github.com/juju/juju/api/base" 14 "github.com/juju/juju/apiserver/params" 15 ) 16 17 // Client allows access to the charms API end point. 18 type Client struct { 19 base.ClientFacade 20 facade base.FacadeCaller 21 } 22 23 // NewClient creates a new client for accessing the charms API. 24 func NewClient(st base.APICallCloser) *Client { 25 frontend, backend := base.NewClientFacade(st, "Charms") 26 return &Client{ClientFacade: frontend, facade: backend} 27 } 28 29 // IsMetered returns whether or not the charm is metered. 30 func (c *Client) IsMetered(charmURL string) (bool, error) { 31 args := params.CharmURL{URL: charmURL} 32 var metered params.IsMeteredResult 33 if err := c.facade.FacadeCall("IsMetered", args, &metered); err != nil { 34 return false, errors.Trace(err) 35 } 36 return metered.Metered, nil 37 } 38 39 // CharmInfo holds information about a charm. 40 type CharmInfo struct { 41 Revision int 42 URL string 43 Config *charm.Config 44 Meta *charm.Meta 45 Actions *charm.Actions 46 Metrics *charm.Metrics 47 LXDProfile *charm.LXDProfile 48 } 49 50 // CharmInfo returns information about the requested charm. 51 func (c *Client) CharmInfo(charmURL string) (*CharmInfo, error) { 52 args := params.CharmURL{URL: charmURL} 53 var info params.CharmInfo 54 if err := c.facade.FacadeCall("CharmInfo", args, &info); err != nil { 55 return nil, errors.Trace(err) 56 } 57 meta, err := convertCharmMeta(info.Meta) 58 if err != nil { 59 return nil, errors.Trace(err) 60 } 61 result := &CharmInfo{ 62 Revision: info.Revision, 63 URL: info.URL, 64 Config: convertCharmConfig(info.Config), 65 Meta: meta, 66 Actions: convertCharmActions(info.Actions), 67 Metrics: convertCharmMetrics(info.Metrics), 68 LXDProfile: convertCharmLXDProfile(info.LXDProfile), 69 } 70 return result, nil 71 } 72 73 func convertCharmConfig(config map[string]params.CharmOption) *charm.Config { 74 if len(config) == 0 { 75 return nil 76 } 77 result := &charm.Config{ 78 Options: make(map[string]charm.Option), 79 } 80 for key, value := range config { 81 result.Options[key] = convertCharmOption(value) 82 } 83 return result 84 } 85 86 func convertCharmOption(opt params.CharmOption) charm.Option { 87 return charm.Option{ 88 Type: opt.Type, 89 Description: opt.Description, 90 Default: opt.Default, 91 } 92 } 93 94 func convertCharmMeta(meta *params.CharmMeta) (*charm.Meta, error) { 95 if meta == nil { 96 return nil, nil 97 } 98 minVersion, err := version.Parse(meta.MinJujuVersion) 99 if err != nil { 100 return nil, errors.Trace(err) 101 } 102 resources, err := convertCharmResourceMetaMap(meta.Resources) 103 if err != nil { 104 return nil, errors.Trace(err) 105 } 106 result := &charm.Meta{ 107 Name: meta.Name, 108 Summary: meta.Summary, 109 Description: meta.Description, 110 Subordinate: meta.Subordinate, 111 Provides: convertCharmRelationMap(meta.Provides), 112 Requires: convertCharmRelationMap(meta.Requires), 113 Peers: convertCharmRelationMap(meta.Peers), 114 ExtraBindings: convertCharmExtraBindingMap(meta.ExtraBindings), 115 Categories: meta.Categories, 116 Tags: meta.Tags, 117 Series: meta.Series, 118 Storage: convertCharmStorageMap(meta.Storage), 119 PayloadClasses: convertCharmPayloadClassMap(meta.PayloadClasses), 120 Resources: resources, 121 Terms: meta.Terms, 122 MinJujuVersion: minVersion, 123 } 124 return result, nil 125 } 126 127 func convertCharmRelationMap(relations map[string]params.CharmRelation) map[string]charm.Relation { 128 if len(relations) == 0 { 129 return nil 130 } 131 result := make(map[string]charm.Relation) 132 for key, value := range relations { 133 result[key] = convertCharmRelation(value) 134 } 135 return result 136 } 137 138 func convertCharmRelation(relation params.CharmRelation) charm.Relation { 139 return charm.Relation{ 140 Name: relation.Name, 141 Role: charm.RelationRole(relation.Role), 142 Interface: relation.Interface, 143 Optional: relation.Optional, 144 Limit: relation.Limit, 145 Scope: charm.RelationScope(relation.Scope), 146 } 147 } 148 149 func convertCharmStorageMap(storage map[string]params.CharmStorage) map[string]charm.Storage { 150 if len(storage) == 0 { 151 return nil 152 } 153 result := make(map[string]charm.Storage) 154 for key, value := range storage { 155 result[key] = convertCharmStorage(value) 156 } 157 return result 158 } 159 160 func convertCharmStorage(storage params.CharmStorage) charm.Storage { 161 return charm.Storage{ 162 Name: storage.Name, 163 Description: storage.Description, 164 Type: charm.StorageType(storage.Type), 165 Shared: storage.Shared, 166 ReadOnly: storage.ReadOnly, 167 CountMin: storage.CountMin, 168 CountMax: storage.CountMax, 169 MinimumSize: storage.MinimumSize, 170 Location: storage.Location, 171 Properties: storage.Properties, 172 } 173 } 174 175 func convertCharmPayloadClassMap(payload map[string]params.CharmPayloadClass) map[string]charm.PayloadClass { 176 if len(payload) == 0 { 177 return nil 178 } 179 result := make(map[string]charm.PayloadClass) 180 for key, value := range payload { 181 result[key] = convertCharmPayloadClass(value) 182 } 183 return result 184 } 185 186 func convertCharmPayloadClass(payload params.CharmPayloadClass) charm.PayloadClass { 187 return charm.PayloadClass{ 188 Name: payload.Name, 189 Type: payload.Type, 190 } 191 } 192 193 func convertCharmResourceMetaMap(resources map[string]params.CharmResourceMeta) (map[string]resource.Meta, error) { 194 if len(resources) == 0 { 195 return nil, nil 196 } 197 result := make(map[string]resource.Meta) 198 for key, value := range resources { 199 converted, err := convertCharmResourceMeta(value) 200 if err != nil { 201 return nil, errors.Trace(err) 202 } 203 result[key] = converted 204 } 205 return result, nil 206 } 207 208 func convertCharmResourceMeta(meta params.CharmResourceMeta) (resource.Meta, error) { 209 resourceType, err := resource.ParseType(meta.Type) 210 if err != nil { 211 return resource.Meta{}, errors.Trace(err) 212 } 213 return resource.Meta{ 214 Name: meta.Name, 215 Type: resourceType, 216 Path: meta.Path, 217 Description: meta.Description, 218 }, nil 219 } 220 221 func convertCharmActions(actions *params.CharmActions) *charm.Actions { 222 if actions == nil { 223 return nil 224 } 225 return &charm.Actions{ 226 ActionSpecs: convertCharmActionSpecMap(actions.ActionSpecs), 227 } 228 } 229 230 func convertCharmActionSpecMap(specs map[string]params.CharmActionSpec) map[string]charm.ActionSpec { 231 if len(specs) == 0 { 232 return nil 233 } 234 result := make(map[string]charm.ActionSpec) 235 for key, value := range specs { 236 result[key] = convertCharmActionSpec(value) 237 } 238 return result 239 } 240 241 func convertCharmActionSpec(spec params.CharmActionSpec) charm.ActionSpec { 242 return charm.ActionSpec{ 243 Description: spec.Description, 244 Params: spec.Params, 245 } 246 } 247 248 func convertCharmMetrics(metrics *params.CharmMetrics) *charm.Metrics { 249 if metrics == nil { 250 return nil 251 } 252 return &charm.Metrics{ 253 Metrics: convertCharmMetricMap(metrics.Metrics), 254 Plan: convertCharmPlan(metrics.Plan), 255 } 256 } 257 258 func convertCharmPlan(plan params.CharmPlan) *charm.Plan { 259 return &charm.Plan{Required: plan.Required} 260 } 261 262 func convertCharmMetricMap(metrics map[string]params.CharmMetric) map[string]charm.Metric { 263 if len(metrics) == 0 { 264 return nil 265 } 266 result := make(map[string]charm.Metric) 267 for key, value := range metrics { 268 result[key] = convertCharmMetric(value) 269 } 270 return result 271 } 272 273 func convertCharmMetric(metric params.CharmMetric) charm.Metric { 274 return charm.Metric{ 275 Type: charm.MetricType(metric.Type), 276 Description: metric.Description, 277 } 278 } 279 280 func convertCharmExtraBindingMap(bindings map[string]string) map[string]charm.ExtraBinding { 281 if len(bindings) == 0 { 282 return nil 283 } 284 result := make(map[string]charm.ExtraBinding) 285 for key, value := range bindings { 286 result[key] = charm.ExtraBinding{value} 287 } 288 return result 289 } 290 291 func convertCharmLXDProfile(lxdProfile *params.CharmLXDProfile) *charm.LXDProfile { 292 if lxdProfile == nil { 293 return nil 294 } 295 return &charm.LXDProfile{ 296 Description: lxdProfile.Description, 297 Config: convertCharmLXDProfileConfigMap(lxdProfile.Config), 298 Devices: convertCharmLXDProfileDevicesMap(lxdProfile.Devices), 299 } 300 } 301 302 func convertCharmLXDProfileConfigMap(config map[string]string) map[string]string { 303 result := make(map[string]string, len(config)) 304 for k, v := range config { 305 result[k] = v 306 } 307 return result 308 } 309 310 func convertCharmLXDProfileDevicesMap(devices map[string]map[string]string) map[string]map[string]string { 311 result := make(map[string]map[string]string, len(devices)) 312 for k, v := range devices { 313 nested := make(map[string]string, len(v)) 314 for nk, nv := range v { 315 nested[nk] = nv 316 } 317 result[k] = nested 318 } 319 return result 320 }