~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/juju/charmstore.v5-unstable/docs/API.md

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Charm store API
 
2
 
 
3
The current live API lives at https://api.jujucharms.com/charmstore/v5
 
4
 
 
5
## Intro
 
6
 
 
7
The charm store stores and indexes charms and bundles. A charm or bundle is
 
8
referred to by a charm store id which can take one of the following two forms:
 
9
 
 
10
* ~*owner*/*series*/*name*(-*revision*)
 
11
* *series*/*name*(-*revision*)
 
12
 
 
13
*Owner* is the name of the user that owns the charm.
 
14
*Series* is one of a small number of known possible series for charms
 
15
(currently just the Ubuntu series names) or the special name bundle to signify
 
16
that the charm id refers to a charm bundle.
 
17
 
 
18
A charm store id referring to a charm (not a bundle) can also use one of the
 
19
following two forms, omitting the series:
 
20
 
 
21
* ~*owner*/*name*(-*revision*)
 
22
* *name*(-*revision*)
 
23
 
 
24
In this case the store will look at all charms with the same *owner* and
 
25
*name*, and choose one according to its preference (for example, it currently
 
26
prefers the latest LTS series).
 
27
 
 
28
### Data format
 
29
 
 
30
All endpoints that do not produce binary data produce a single JSON object as
 
31
their result. These will be described in terms of the Go types that produce and
 
32
consume the format, along with an example. A charm id is represented as a
 
33
`charm.URL type`.
 
34
 
 
35
### Errors
 
36
 
 
37
If any request returns an error, it will produce it in the following form:
 
38
 
 
39
```go
 
40
type Error struct {
 
41
        Message string
 
42
        Code string
 
43
        Info map[string] Error `json:",omitempty"`
 
44
}
 
45
```
 
46
 
 
47
Example:
 
48
 
 
49
```json
 
50
{
 
51
  "Message": "unexpected Content-Type \"image/jpeg\"; expected \"application/json\"",
 
52
  "Code": "bad request"
 
53
}
 
54
```
 
55
 
 
56
Note: this format is compatible with the error results used by juju-core.
 
57
Currently defined codes are the following:
 
58
 
 
59
* not found
 
60
* metadata not found
 
61
* forbidden
 
62
* bad request
 
63
* duplicate upload
 
64
* multiple errors
 
65
* unauthorized
 
66
* method not allowed
 
67
 
 
68
The `Info` field is set when a request returns a "multiple errors" error code;
 
69
currently the only two endpoints that can are "/meta" and "*id*/meta/any".
 
70
Each element in `Info` corresponds to an element in the PUT request, and holds
 
71
the error for that element. See those endpoints for examples.
 
72
 
 
73
### Bulk requests and missing metadata
 
74
 
 
75
There are two forms of "bulk" API request that can return information about
 
76
several items at once. The `/meta/any` endpoint (along with some others) have a
 
77
set of "include" flags that specify metadata to return. The `/meta` endpoint
 
78
has a set of "id" flags that specify a set of ids to return data on.
 
79
 
 
80
In both of these cases, when the relevant data does not exist, the result will
 
81
be omitted from the returned map. For example a GET of
 
82
`/meta/archive-size?id=something` will return an empty map if the id
 
83
"something" is not found; a GET of
 
84
`/precise/wordpress-34/meta/any?include=bundle-metadata` will return an empty
 
85
map if the id "precise/wordpress-34" refers to a bundle rather than a charm.
 
86
 
 
87
For the singular forms of these endpoints, a 404 "metadata not found" error
 
88
will be returned when this happens.
 
89
 
 
90
In the `meta/any` GET bulk request, if some data requires authorization, the
 
91
default behavior is to return an authorization required response. Clients
 
92
interested in public data only can include a `ignore-auth=1` query so that only
 
93
public information is returned. In this case, results requiring authorization
 
94
(if any) will be omitted.
 
95
 
 
96
### Channels
 
97
 
 
98
Any entity in the charm store is considered to be part of one or more "channels"
 
99
(think "distribution channels"). Currently supported channels are "unpublished",
 
100
"development" and "stable". All entities are initially (and always) part
 
101
of the "unpublished" channel; subsequent operations on the publish
 
102
endpoint can make entities available in other channels.
 
103
 
 
104
All requests that take one or more entity ids as parameters
 
105
accept a "channel" query parameter that influences what channel
 
106
is chosen to resolve the ids. The default channel is "stable".
 
107
 
 
108
For example, if wordpress-3 has just been published to the stable
 
109
channel, and wordpress-4 has been published to the development
 
110
 then a GET of wordpress/meta/id-revision?channel=development
 
111
will return {"Revision": 4} and a GET of wordpress/wordpress/meta/id-revision
 
112
will return {"Revision": 3} because the default channel is "stable".
 
113
 
 
114
### Versioning
 
115
 
 
116
The version of the API is indicated by an initial "vN" prefix to the path.
 
117
Later versions will increment this number. This also means we can potentially
 
118
serve backwardly compatible paths to juju-core. All paths in this document
 
119
should be read as if they had a "v5" prefix. For example, the
 
120
`wordpress/meta/charm-metadata` path is actually at
 
121
`v5/wordpress/meta/charm-metadata`.
 
122
 
 
123
### Boolean values
 
124
 
 
125
Where a flag specifies a boolean property, the value must be either "1",
 
126
signifying true, or empty or "0", signifying false.
 
127
 
 
128
## Requests
 
129
 
 
130
### Expand-id
 
131
 
 
132
#### GET *id*/expand-id
 
133
 
 
134
The expand-id path expands a general id into a set of specific ids. It strips
 
135
any revision number and series from id, and returns a slice of all the possible
 
136
ids matched by that, including all the versions and series.
 
137
If *id* is in the development channel, all development and non-development
 
138
revisions will be returned; if it is not, then only non-development
 
139
revisions will be returned.
 
140
 
 
141
```go
 
142
[]Id
 
143
 
 
144
type Id struct {
 
145
        Id string
 
146
}
 
147
```
 
148
 
 
149
Example: `GET wordpress/expand-id`
 
150
 
 
151
```json
 
152
[
 
153
    {"Id": "trusty/wordpress-2"}
 
154
    {"Id": "trusty/wordpress-1"},
 
155
    {"Id": "precise/wordpress-2"},
 
156
    {"Id": "precise/wordpress-1"},
 
157
]
 
158
```
 
159
 
 
160
Example: `GET precise/wordpress-34/expand-id`
 
161
 
 
162
```json
 
163
[
 
164
    {"Id": "trusty/wordpress-2"}
 
165
    {"Id": "trusty/wordpress-1"},
 
166
    {"Id": "precise/wordpress-2"},
 
167
    {"Id": "precise/wordpress-1"},
 
168
]
 
169
```
 
170
 
 
171
Example: `GET development/precise/wordpress-34/expand-id`
 
172
 
 
173
```json
 
174
[
 
175
    {"Id": "development/trusty/wordpress-3"},
 
176
    {"Id": "trusty/wordpress-2"},
 
177
    {"Id": "trusty/wordpress-1"},
 
178
    {"Id": "precise/wordpress-2"},
 
179
    {"Id": "precise/wordpress-1"},
 
180
 ]
 
181
```
 
182
 
 
183
 
 
184
### Archive
 
185
 
 
186
#### GET *id*/archive
 
187
 
 
188
The `/archive` path returns the raw archive zip file for the charm with the
 
189
given charm id. The response header includes the SHA 384 hash of the archive
 
190
(Content-Sha384) and the fully qualified entity id (Entity-Id).
 
191
 
 
192
Example: `GET wordpress/archive`
 
193
 
 
194
Any additional elements attached to the `/charm` path retrieve the file from
 
195
the charm or bundle's zip file. The `Content-Sha384` header field in the
 
196
response will hold the hash checksum of the archive.
 
197
 
 
198
#### GET *id*/archive/*path*
 
199
 
 
200
Retrieve a file corresponding to *path* in the charm or bundle's zip archive.
 
201
 
 
202
Example: `GET trusty/wordpress/archive/config.yaml`
 
203
 
 
204
#### POST *id*/archive
 
205
 
 
206
This uploads the given charm or bundle in zip format.
 
207
 
 
208
<pre>
 
209
POST <i>id</i>/archive?hash=<i>sha384hash</i>
 
210
</pre>
 
211
 
 
212
The id specified must specify the series and must not contain a revision
 
213
number. The hash flag must specify the SHA384 hash of the uploaded archive in
 
214
hexadecimal format. If the same content has already been uploaded, the response
 
215
will return immediately without reading the entire body.
 
216
 
 
217
The charm or bundle is verified before being made available.
 
218
 
 
219
The response holds the full charm/bundle id including the revision number.
 
220
 
 
221
```go
 
222
type UploadedId struct {
 
223
        Id string
 
224
}
 
225
```
 
226
 
 
227
Example response body:
 
228
 
 
229
```json
 
230
{
 
231
    "Id": "precise/wordpress-24"
 
232
}
 
233
```
 
234
 
 
235
#### DELETE *id*/archive
 
236
 
 
237
This deletes the given charm or bundle with the given id. If the ID is not
 
238
fully specified, the charm series or revisions are not resolved and the charm
 
239
is not deleted. In order to delete the charm, the ID must include series as
 
240
well as revisions. In order to delete all versions of the charm, use
 
241
`/expand-id` and iterate on all elements in the result.
 
242
 
 
243
### Visual diagram
 
244
 
 
245
#### GET *id*/diagram.svg
 
246
 
 
247
This returns a scalable vector-graphics image representing the entity with the
 
248
given id. This will return a not-found error for charms.
 
249
 
 
250
#### GET *id*/icon.svg
 
251
 
 
252
This returns the SVG image of the charm's icon. This reports a not-found error
 
253
for bundles. Unlike the `archive/icon.svg` where 404 is returned in case an
 
254
icon does not exist, this endpoint returns the default icon.
 
255
 
 
256
#### GET *id*/readme
 
257
 
 
258
This returns the README.
 
259
 
 
260
### Promulgation
 
261
 
 
262
#### PUT *id*/promulgate
 
263
 
 
264
A PUT to ~*user*/*anyseries*/*name*-*anyrevision* sets whether entities
 
265
with the id *x*/*name* are considered to be aliases
 
266
for ~*user*/*x*/*name* for all series *x*. The series
 
267
and revision in the id are ignored (except that an
 
268
entity must exist that matches the id).
 
269
 
 
270
If Promulgate is true, it means that any new charms published
 
271
to ~*user*/*x*/*name* will also be given the alias
 
272
*x*/*name*. The latest revision for all ids ~*user*/*anyseries*/*name*
 
273
will also be aliased likewise.
 
274
 
 
275
If Promulgate is false, any new charms published
 
276
to ~*user*/*anyseries*/*name* will not be given a promulgated
 
277
alias, but no change is made to any existing aliases.
 
278
 
 
279
The promulgated status can be retrieved from the
 
280
promulgated meta endpoint.
 
281
 
 
282
```go
 
283
type PromulgateRequest struct {
 
284
        Promulgated bool
 
285
}
 
286
```
 
287
 
 
288
Example: `PUT ~charmers/precise/wordpress-23/promulgate`
 
289
 
 
290
Request body:
 
291
```json
 
292
{
 
293
    "Promulgate" : true,
 
294
}
 
295
```
 
296
 
 
297
### Charm and bundle publishing
 
298
 
 
299
#### PUT *id*/publish
 
300
 
 
301
A PUT to the publish endpoint publishes the entity with the given id
 
302
on the channels provided in the request body. It reports an error if
 
303
there are no channels specified or if one of the channels is invalid
 
304
(the "unpublished" channel is special and is also considered invalid in
 
305
a publish request).
 
306
 
 
307
See the section on Channels in the introduction for how the published
 
308
channels affects id resolving.
 
309
 
 
310
```go
 
311
type PublishRequest struct {
 
312
    Channels []string
 
313
}
 
314
```
 
315
 
 
316
On success, the response body will be empty.
 
317
 
 
318
Example: `PUT ~charmers/trusty/django-42/publish`
 
319
 
 
320
Request body:
 
321
```json
 
322
{
 
323
    "Channels" : ["stable"],
 
324
}
 
325
```
 
326
 
 
327
After the above request, ~charmers/trusty/django will
 
328
resolve to ~charmers/trusty/django-42 unless a different
 
329
channel is specified in the request.
 
330
 
 
331
### Stats
 
332
 
 
333
#### GET stats/counter/...
 
334
 
 
335
This endpoint can be used to retrieve stats related to entities.
 
336
 
 
337
<pre>
 
338
GET stats/counter/<i>key</i>[:<i>key</i>]...?[by=<i>unit</i>]&start=<i>date</i>][&stop=<i>date</i>][&list=1]
 
339
</pre>
 
340
 
 
341
The stats path allows the retrieval of counts of operations in a general way. A
 
342
statistic is composed of an ordered tuple of keys:
 
343
 
 
344
<pre>
 
345
<i>kind</i>:<i>series</i>:<i>name</i>:<i>user</i>
 
346
</pre>
 
347
Operations on the store increment counts associated with a specific tuple,
 
348
determined by the operation and the charm being operated on.
 
349
 
 
350
When querying statistics, it is possible to aggregate statistics by using a
 
351
`\*` as the last tuple element, standing for all tuples with the given prefix.
 
352
For example, `missing:\*` will retrieve the counts for all operations of kind
 
353
"missing", regardless of the series, name or user.
 
354
 
 
355
If the list flag is specified, counts for all next level keys will be listed.
 
356
 For example, a query for `stats/counter/download:*?list=1&by=week` will show
 
357
 all the download counts for each series for each week.
 
358
 
 
359
If a date range is specified, the returned counts will be restricted to the
 
360
given date range. Dates are specified in the form "yyyy-mm-dd". If the `by`
 
361
flag is specified, one count is shown for each unit in the specified period,
 
362
where unit can be `week` or `day`.
 
363
 
 
364
Possible kinds are:
 
365
 
 
366
* archive-download
 
367
* archive-delete
 
368
* archive-upload
 
369
* archive-failed-upload
 
370
 
 
371
```go
 
372
[]Statistic
 
373
 
 
374
type Statistic struct {
 
375
        Key string      `json:",omitempty"`
 
376
        Date string     `json:",omitempty"`
 
377
        Count int64
 
378
}
 
379
```
 
380
 
 
381
Example: `GET "stats/counter/missing:trusty:*"`
 
382
 
 
383
```json
 
384
[
 
385
    {"Count": 1917}
 
386
]
 
387
```
 
388
 
 
389
Example:
 
390
`GET stats/counter/download/archive-download:*?by=week&list=1&start=2014-03-01`
 
391
 
 
392
```json
 
393
[
 
394
    {
 
395
        "Key": "charm-bundle:precise:*",
 
396
        "Date": "2014-06-08",
 
397
        "Count": 2715
 
398
    }, {
 
399
        "Key": "charm-bundle:trusty:*",
 
400
        "Date": "2014-06-08",
 
401
        "Count": 2672
 
402
    }, {
 
403
        "Key": "charm-bundle:oneiric:*",
 
404
        "Date": "2014-06-08",
 
405
        "Count": 14
 
406
    }, {
 
407
        "Key": "charm-bundle:quantal:*",
 
408
        "Date": "2014-06-08",
 
409
        "Count": 1
 
410
    }, {
 
411
        "Key": "charm-bundle:trusty:*",
 
412
        "Date": "2014-06-15",
 
413
        "Count": 3835
 
414
    }, {
 
415
        "Key": "charm-bundle:precise:*",
 
416
        "Date": "2014-06-15",
 
417
        "Count": 3389
 
418
    }
 
419
]
 
420
```
 
421
 
 
422
**Update**:
 
423
We need to provide aggregated stats for downloads:
 
424
* promulgated and ~user counterpart charms should have the same download stats.
 
425
 
 
426
#### PUT stats/update
 
427
 
 
428
This endpoint can be used to increase the stats related to an entity.
 
429
This will increase the download stats by one for the entity provided and at the time stamp provided.
 
430
It can for future purpose include the client issuing the requests.
 
431
This is used when charmstore is in front of a cache server that will not call the real /archive endpoint and
 
432
as such will not increase the download counts.
 
433
 
 
434
<pre>
 
435
PUT stats/counter
 
436
</pre>
 
437
 
 
438
Request body:
 
439
```go
 
440
type StatsUpdateRequest struct {
 
441
        Timestamp      time.Time
 
442
        Type           string
 
443
        CharmReference *charm.URL
 
444
}
 
445
```
 
446
Example: `PUT stats/update`
 
447
 
 
448
 
 
449
Request body:
 
450
```json
 
451
{
 
452
    "Timestamp":"2015-08-06T06:46:13Z",
 
453
    "Type":"deploy",
 
454
    "CharmReference":"cs:~charmers/utopic/wordpress-42"
 
455
}
 
456
```
 
457
 
 
458
### Meta
 
459
 
 
460
#### GET meta
 
461
 
 
462
The meta path returns an array of all the path names under meta, excluding the
 
463
`meta/any` path, as suitable for passing as "include=" flags to paths that
 
464
allow those. Note that the result does not include sub-paths of extra-info
 
465
because these vary according to each charm or bundle.
 
466
 
 
467
Example: `GET /meta`
 
468
 
 
469
```json
 
470
[
 
471
    "archive-size",
 
472
    "archive-upload-time",
 
473
    "bundle-machine-count",
 
474
    "bundle-metadata",
 
475
    "bundle-unit-count",
 
476
    "bundles-containing",
 
477
    "charm-actions",
 
478
    "charm-config",
 
479
    "charm-metadata",
 
480
    "charm-related",
 
481
    "extra-info",
 
482
    "hash",
 
483
    "hash256",
 
484
    "id",
 
485
    "id-name",
 
486
    "id-revision",
 
487
    "id-series",
 
488
    "id-user",
 
489
    "manifest",
 
490
    "promulgated",
 
491
    "published",
 
492
    "revision-info",
 
493
    "stats",
 
494
    "supported-series",
 
495
    "tags"
 
496
]
 
497
```
 
498
 
 
499
#### GET meta/*endpoint*
 
500
 
 
501
This endpoint allows a user to query any number of IDs for metadata.
 
502
<pre>
 
503
GET meta/<i>endpoint</i>?id=<i>id0</i>[&id=<i>id1</i>...][<i>otherflags</i>]
 
504
</pre>
 
505
 
 
506
This call is equivalent to calling "*id*/meta" for each id separately. The
 
507
result holds an element for each id in the request with the resulting metadata
 
508
exactly as returned by "GET *id*/meta/*endpoint*[?*otherflags*]". The map keys
 
509
are the ids exactly as specified in the request, although they are resolved to
 
510
fill in series and revision as usual when fetching the metadata. Any ids that
 
511
are not found, or with non-relevant metadata, will be omitted.
 
512
 
 
513
```go
 
514
map[string] interface{}
 
515
```
 
516
 
 
517
Example: `GET meta/archive-size?id=wordpress&id=mysql`
 
518
 
 
519
```json
 
520
{
 
521
    "wordpress": {
 
522
        "Size": 1234
 
523
    },
 
524
    "mysql" : {
 
525
        "Size": 4321
 
526
    }
 
527
}
 
528
```
 
529
 
 
530
Example: `GET /meta/any?include=archive-size&include=extra-info/featured&id=wordpress&id=mysql`
 
531
 
 
532
```json
 
533
{
 
534
    "wordpress": {
 
535
        "Id": "precise/wordpress-3",
 
536
        "Meta": {
 
537
            "archive-size": {
 
538
                "Size": 1234
 
539
            },
 
540
            "extra-info/featured": true
 
541
        }
 
542
    },
 
543
    "mysql" : {
 
544
        "Id": "precise/mysql-23",
 
545
        "Meta": {
 
546
            "archive-size": {
 
547
                "Size": 4321
 
548
            },
 
549
            "extra-info/featured": true
 
550
        }
 
551
    }
 
552
}
 
553
```
 
554
 
 
555
#### PUT meta/*endpoint*
 
556
 
 
557
A PUT to this endpoint allows the metadata endpoint of several ids to be
 
558
updated. The request body is as specified in the result of the above GET
 
559
request. The ids in the body specify the ids that will be updated. If there is
 
560
a failure, the error code will be "multiple errors", and the Info field will
 
561
holds one entry for each id in the request body that failed, holding the error
 
562
for that id. If there are no errors, PUT endpoints usually return an empty body
 
563
in the response.
 
564
 
 
565
Example: `PUT meta/extra-info/featured`
 
566
 
 
567
Request body:
 
568
```json
 
569
{
 
570
    "precise/wordpress-23" : true,
 
571
    "precise/mysql-53" :     true,
 
572
    "precise/wordpress-22" : false,
 
573
}
 
574
```
 
575
 
 
576
Example: `PUT meta/any`
 
577
 
 
578
Request body:
 
579
```json
 
580
{
 
581
    "precise/wordpress-23": {
 
582
        "Meta": {
 
583
            "extra-info/featured": true,
 
584
            "extra-info/revision-info": "12dfede4ee23",
 
585
            "bad-metaname": 3235
 
586
        }
 
587
    },
 
588
    "trusty/mysql-23": {
 
589
        "Meta": {
 
590
            "extra-info/featured": false,
 
591
        }
 
592
    }
 
593
}
 
594
```
 
595
 
 
596
Response body (with HTTP status 500):
 
597
```json
 
598
{
 
599
    "Message": "multiple errors (1) found",
 
600
    "Code": "multiple errors",
 
601
    "Info": {
 
602
        "precise/wordpress-23": {
 
603
            "Message": "multiple errors",
 
604
            "Code": "multiple errors",
 
605
            "Info": {
 
606
                "bad-metaname": {
 
607
                    "Message": "metadata not found",
 
608
                    "Code": "not found"
 
609
                }
 
610
            }
 
611
        }
 
612
    }
 
613
}
 
614
```
 
615
 
 
616
If the request succeeds, a 200 OK status code is returned with an empty
 
617
response body.
 
618
 
 
619
#### GET *id*/meta
 
620
 
 
621
This path returns the same information as the meta path. The results are the
 
622
same regardless of the actual id.
 
623
 
 
624
Example: `GET foo/meta`
 
625
 
 
626
```json
 
627
[
 
628
    "archive-size",
 
629
    "archive-upload-time",
 
630
    "bundle-machine-count",
 
631
    "bundle-metadata",
 
632
    "bundle-unit-count",
 
633
    "bundles-containing",
 
634
    "charm-actions",
 
635
    "charm-config",
 
636
    "charm-metadata",
 
637
    "charm-related",
 
638
    "extra-info",
 
639
    "id",
 
640
    "id-name",
 
641
    "id-revision",
 
642
    "id-series",
 
643
    "id-user",
 
644
    "manifest",
 
645
    "promulgated",
 
646
    "revision-info",
 
647
    "stats",
 
648
    "tags"
 
649
]
 
650
```
 
651
 
 
652
#### GET *id*/meta/any
 
653
 
 
654
<pre>
 
655
GET <i>id</i>/meta/any?[include=<i>meta</i>[&include=<i>meta</i>...]]
 
656
</pre>
 
657
 
 
658
The `meta/any` path returns requested metadata information on the given id. If
 
659
the id is non-specific, the latest revision and preferred series for the id
 
660
will be assumed.
 
661
 
 
662
Other metadata can be requested by specifying one or more `include` flags. The
 
663
value of each meta must be the name of one of the path elements defined under
 
664
the `/meta` path (for example: `charm-config`, `charm-meta`, `manifest`) and
 
665
causes the desired metadata to be included in the Meta field, keyed by meta. If
 
666
there is no metadata for the given meta path, the element will be omitted (for
 
667
example, if bundle-specific data is requested for a charm id).
 
668
 
 
669
The `any` path may not itself be the subject of an include directive. It is
 
670
allowed to specify "charm-" or "bundle-"" specific metadata paths -- if the id
 
671
refers to a charm then bundle-specific metadata will be omitted and vice versa.
 
672
 
 
673
Various other paths use the same `include` mechanism to allow retrieval of
 
674
arbitrary metadata.
 
675
 
 
676
```go
 
677
type Meta struct {
 
678
        Id string                      `json:",omitempty"`
 
679
        Meta map[string] interface{}   `json:",omitempty"`
 
680
}
 
681
```
 
682
 
 
683
Example: `GET wordpress/meta/any`
 
684
 
 
685
```json
 
686
{
 
687
    "Id": "trusty/wordpress-32"
 
688
}
 
689
```
 
690
 
 
691
Example: `GET ubuntu/meta/any?include=archive-size&include=extra-info/featured`
 
692
 
 
693
```json
 
694
{
 
695
        "Id": "trusty/ubuntu-3",
 
696
        "Meta": {
 
697
        "archive-size": {
 
698
           "Size": 7580
 
699
        },
 
700
        "extra-info/featured": true
 
701
        }
 
702
}
 
703
```
 
704
 
 
705
#### PUT *id*/meta/any
 
706
 
 
707
This endpoint allows the updating of several metadata elements at once. These
 
708
must support PUT requests. The body of the PUT request is in the same form as
 
709
returned by the above GET request, except with the Id field omitted. The
 
710
elements inside the Meta field specify which meta endpoints will be updated. If
 
711
one or more of the update fails, the resulting error will contain an Info field
 
712
that has an entry for each update that fails, keyed by the endpoint name.
 
713
 
 
714
Example: `PUT ubuntu/meta/any`
 
715
 
 
716
Request body:
 
717
```json
 
718
{
 
719
    "Meta": {
 
720
        "extra-info": {
 
721
            "revision-info": "a46f45649f0d0e0b"
 
722
        },
 
723
        "extra-info/featured": true
 
724
    }
 
725
}
 
726
```
 
727
 
 
728
Example: `PUT ubuntu/meta/any`
 
729
 
 
730
Request body:
 
731
```json
 
732
{
 
733
    "Meta": {
 
734
        "extra-info/featured": false,
 
735
        "archive-size": 12354,
 
736
    }
 
737
}
 
738
```
 
739
 
 
740
Response body:
 
741
```json
 
742
{
 
743
    "Message": "multiple errors",
 
744
    "Code": "multiple errors",
 
745
    "Info": {
 
746
        "archive-size": {
 
747
            "Message": "method not allowed",
 
748
            "Code": "bad request",
 
749
        }
 
750
    }
 
751
}
 
752
```
 
753
 
 
754
#### GET *id*/meta/charm-metadata
 
755
 
 
756
The `/meta/charm.metadata` path returns the contents of the charm metadata file
 
757
for a charm. The id must refer to a charm, not a bundle.
 
758
 
 
759
```go
 
760
type CharmMetadata struct {
 
761
        Summary     string
 
762
        Description string
 
763
        Subordinate bool                        `json:",omitempty"`
 
764
        // Provides and Requires map from the relation name to
 
765
        // information about the relation.
 
766
        Provides    map[string]Relation         `json:",omitempty"`
 
767
        Requires    map[string]Relation         `json:",omitempty"`
 
768
        Peers       map[string]Relation         `json:",omitempty"`
 
769
        Tags  []string                          `json:",omitempty"`
 
770
}
 
771
 
 
772
type Relation struct {
 
773
        Interface string
 
774
        Optional  bool                          `json:",omitempty"`
 
775
        Limit     int                           `json:",omitempty"`
 
776
        Scope     RelationScope
 
777
}
 
778
 
 
779
type RelationRole string
 
780
type RelationScope string
 
781
```
 
782
 
 
783
The possible values of a `RelationScope` are
 
784
 
 
785
* global
 
786
* container
 
787
 
 
788
Example: `GET wordpress/meta/charm-metadata`
 
789
 
 
790
```json
 
791
{
 
792
    "Summary": "WordPress is a full featured web blogging tool, this charm deploys it.",
 
793
    "Description": "This will install and setup WordPress optimized to run in the cloud. This install, in particular, will \n place Ngnix and php-fpm configured to scale horizontally with Nginx's reverse proxy\n",
 
794
    "Provides": {
 
795
        "website": {
 
796
            "Interface": "http",
 
797
            "Scope": "global"
 
798
        }
 
799
    },
 
800
    "Requires": {
 
801
        "cache": {
 
802
            "Interface": "cache",
 
803
            "Scope": "global"
 
804
        },
 
805
        "db": {
 
806
            "Interface": "db",
 
807
            "Scope": "global"
 
808
        }
 
809
    },
 
810
    "Peers": {
 
811
        "loadbalancer": {
 
812
            "Interface": "reversenginx",
 
813
            "Scope": "global"
 
814
        }
 
815
    },
 
816
    "Tags": [
 
817
        "applications"
 
818
    ]
 
819
}
 
820
```
 
821
 
 
822
#### GET *id*/meta/bundle-metadata
 
823
 
 
824
The `meta/bundle-metadata` path returns the contents of the bundle metadata
 
825
file for a bundle. The id must refer to a bundle, not a charm.
 
826
 
 
827
```go
 
828
type BundleData struct {
 
829
        Applications map[string] ApplicationSpec
 
830
        Machines map[string] MachineSpec `json:",omitempty"`
 
831
        Series string                    `json:",omitempty"`
 
832
        Relations [][]string             `json:",omitempty"`
 
833
}
 
834
 
 
835
type MachineSpec struct {
 
836
        Constraints string               `json:",omitempty"`
 
837
        Annotations map[string]string    `json:",omitempty"`
 
838
}
 
839
 
 
840
type ApplicationSpec struct {
 
841
        Charm string
 
842
        NumUnits int
 
843
        To []string                      `json:",omitempty"`
 
844
 
 
845
        // Options holds the configuration values
 
846
        // to apply to the new application. They should
 
847
        // be compatible with the charm configuration.
 
848
        Options map[string]interface{}   `json:",omitempty"`
 
849
        Annotations map[string]string    `json:",omitempty"`
 
850
        Constraints string               `json:",omitempty"`
 
851
}
 
852
```
 
853
 
 
854
Example: `GET mediawiki/meta/bundle-metadata`
 
855
 
 
856
```json
 
857
{
 
858
    "Applications": {
 
859
        "mediawiki": {
 
860
            "Charm": "cs:precise/mediawiki-10",
 
861
            "NumUnits": 1,
 
862
            "Options": {
 
863
                "debug": false,
 
864
                "name": "Please set name of wiki",
 
865
                "skin": "vector"
 
866
            },
 
867
            "Annotations": {
 
868
                "gui-x": "619",
 
869
                "gui-y": "-128"
 
870
            }
 
871
        },
 
872
        "memcached": {
 
873
            "Charm": "cs:precise/memcached-7",
 
874
            "NumUnits": 1,
 
875
            "Options": {
 
876
                "connection_limit": "global",
 
877
                "factor": 1.25
 
878
            },
 
879
            "Annotations": {
 
880
                "gui-x": "926",
 
881
                "gui-y": "-125"
 
882
            }
 
883
        }
 
884
    },
 
885
    "Relations": [
 
886
        [
 
887
            "mediawiki:cache",
 
888
            "memcached:cache"
 
889
        ]
 
890
    ]
 
891
}
 
892
```
 
893
 
 
894
#### GET *id*/meta/bundle-unit-count
 
895
 
 
896
The `meta/bundle-unit-count` path returns a count of all the units that will be
 
897
created by a bundle. The id must refer to a bundle, not a charm.
 
898
 
 
899
```go
 
900
type BundleCount struct {
 
901
        Count int
 
902
}
 
903
```
 
904
 
 
905
Example: `GET bundle/mediawiki/meta/bundle-unit-count`
 
906
 
 
907
```json
 
908
{
 
909
    "Count": 1
 
910
}
 
911
```
 
912
 
 
913
#### GET *id*/meta/bundle-machine-count
 
914
 
 
915
The `meta/bundle-machine-count` path returns a count of all the machines used
 
916
by a bundle. The id must refer to a bundle, not a charm.
 
917
 
 
918
```go
 
919
type BundleCount struct {
 
920
        Count int
 
921
}
 
922
```
 
923
 
 
924
Example: `GET bundle/mediawiki/meta/bundle-machine-count`
 
925
 
 
926
```json
 
927
{
 
928
    "Count": 2
 
929
}
 
930
```
 
931
 
 
932
#### GET *id*/meta/manifest
 
933
 
 
934
The `meta/manifest` path returns the list of all files in the bundle or charm's
 
935
archive.
 
936
 
 
937
```go
 
938
[]ManifestFile
 
939
type ManifestFile struct {
 
940
        Name string
 
941
        Size int64
 
942
}
 
943
```
 
944
 
 
945
Example: `GET trusty/juju-gui-3/meta/manifest`
 
946
 
 
947
```json
 
948
[
 
949
    {
 
950
        "Name": "config.yaml",
 
951
        "Size": 8254
 
952
    },
 
953
    {
 
954
        "Name": "HACKING.md",
 
955
        "Size": 11376
 
956
    },
 
957
    {
 
958
        "Name": "Makefile",
 
959
        "Size": 3304
 
960
    },
 
961
    {
 
962
        "Name": "metadata.yaml",
 
963
        "Size": 1110
 
964
    },
 
965
    {
 
966
        "Name": "README.md",
 
967
        "Size": 9243
 
968
    },
 
969
    {
 
970
        "Name": "hooks/config-changed",
 
971
        "Size": 1636
 
972
    },
 
973
    {
 
974
        "Name": "hooks/install",
 
975
        "Size": 3055
 
976
    },
 
977
    {
 
978
        "Name": "hooks/start",
 
979
        "Size": 1101
 
980
    },
 
981
    {
 
982
        "Name": "hooks/stop",
 
983
        "Size": 1053
 
984
    }
 
985
]
 
986
```
 
987
 
 
988
#### GET *id*/meta/charm-actions
 
989
 
 
990
 
 
991
The `meta/charm-actions` path returns the actions available in a charm as
 
992
stored in its `actions.yaml` file. Id must refer to a charm, not a bundle.
 
993
 
 
994
```go
 
995
type Actions struct {
 
996
        Actions map[string]ActionSpec `json:",omitempty"`
 
997
}
 
998
 
 
999
type ActionSpec struct {
 
1000
        Description string
 
1001
        Params JSONSchema
 
1002
}
 
1003
```
 
1004
 
 
1005
The Params field holds a JSON schema specification of an action's parameters.
 
1006
See [http://json-schema.org/latest/json-schema-core.html](http://json-schema.org/latest/json-schema-core.html).
 
1007
 
 
1008
Example: `GET wordpress/meta/charm-actions`
 
1009
 
 
1010
```json
 
1011
{
 
1012
    "Actions": {
 
1013
        "backup": {
 
1014
            "Description": "back up the charm",
 
1015
            "Params": {
 
1016
                "properties": {
 
1017
                    "destination-host": {
 
1018
                        "type": "string"
 
1019
                    },
 
1020
                    "destination-name": {
 
1021
                        "type": "string"
 
1022
                    }
 
1023
                },
 
1024
                "required": [
 
1025
                    "destination-host"
 
1026
                ],
 
1027
                "type": "object"
 
1028
            }
 
1029
        }
 
1030
    }
 
1031
}
 
1032
```
 
1033
 
 
1034
#### GET *id*/meta/charm-config
 
1035
 
 
1036
The `meta/charm-config` path returns the charm's configuration specification as
 
1037
stored in its `config.yaml` file. Id must refer to a charm, not a bundle.
 
1038
 
 
1039
```go
 
1040
type Config struct {
 
1041
        Options map[string] Option
 
1042
}
 
1043
 
 
1044
// Option represents a single charm config option.
 
1045
type Option struct {
 
1046
        Type        string
 
1047
        Description string
 
1048
        Default     interface{}
 
1049
}
 
1050
```
 
1051
 
 
1052
Example: `GET trusty/juju-gui-3/meta/charm-config`
 
1053
 
 
1054
```json
 
1055
{
 
1056
    "Options": {
 
1057
        "builtin-server": {
 
1058
            "Type": "boolean",
 
1059
            "Description": "Enable the built-in server.",
 
1060
            "Default": true
 
1061
        },
 
1062
        "login-help": {
 
1063
            "Type": "string",
 
1064
            "Description": "The help text shown to the user.",
 
1065
            "Default": null
 
1066
        },
 
1067
        "read-only": {
 
1068
            "Type": "boolean",
 
1069
            "Description": "Enable read-only mode.",
 
1070
            "Default": false
 
1071
        }
 
1072
    }
 
1073
}
 
1074
```
 
1075
 
 
1076
#### GET *id*/meta/published
 
1077
 
 
1078
The `meta/published` path returns a list of the channels that
 
1079
the entity has been published to.
 
1080
 
 
1081
```go
 
1082
type PublishedResponse struct {
 
1083
        // Info holds an entry for each channel that the
 
1084
        // entity has been published to.
 
1085
        Info []PublishedInfo
 
1086
}
 
1087
 
 
1088
// PublishedInfo holds information on a channel that an entity
 
1089
// has been published to.
 
1090
type PublishedInfo struct {
 
1091
        // Channel holds the value of the channel that
 
1092
        // the entity has been published to.
 
1093
        // This will never be "unpublished" as entities
 
1094
        // cannot be published to that channel.
 
1095
        Channel Channel
 
1096
 
 
1097
        // Current holds whether the entity is the most
 
1098
        // recently published member of the channel.
 
1099
        Current bool
 
1100
}
 
1101
```
 
1102
 
 
1103
#### GET *id*/meta/terms
 
1104
 
 
1105
The `meta/terms` path returns a list of terms and conditions (as recorded in
 
1106
the terms field of the charm metadata) the user must agree to in order to 
 
1107
obtain the archive of the given charm id.
 
1108
 
 
1109
Example: `GET some-charm/meta/terms`
 
1110
 
 
1111
```json
 
1112
[
 
1113
    "enterprise-terms/1",
 
1114
    "special-terms/17"
 
1115
]
 
1116
```
 
1117
 
 
1118
#### GET *id*/meta/archive-size
 
1119
 
 
1120
The `meta/archive-size` path returns the archive size, in bytes, of the archive
 
1121
of the given charm or bundle id.
 
1122
 
 
1123
```go
 
1124
type ArchiveSize struct {
 
1125
        Size int64
 
1126
}
 
1127
```
 
1128
 
 
1129
Example: `GET wordpress/meta/archive-size`
 
1130
 
 
1131
```json
 
1132
{
 
1133
    "Size": 4747
 
1134
}
 
1135
```
 
1136
 
 
1137
#### GET *id*/meta/hash
 
1138
 
 
1139
This path returns the SHA384 hash sum of the archive of the given charm or
 
1140
bundle id.
 
1141
 
 
1142
```go
 
1143
type HashResponse struct {
 
1144
    Sum string
 
1145
}
 
1146
```
 
1147
 
 
1148
Example: `GET wordpress/meta/hash`
 
1149
 
 
1150
Response body:
 
1151
```json
 
1152
{
 
1153
    "Sum": "0a410321586d244d3981e2b23a27a7e86ebdcab8bd0ca8f818d3f4c34b2ea2791e0dbdc949f70b283a3f5efdf908abf1"
 
1154
}
 
1155
```
 
1156
 
 
1157
#### GET *id*/meta/hash256
 
1158
 
 
1159
This path returns the SHA256 hash sum of the archive of the given charm or
 
1160
bundle id.
 
1161
 
 
1162
```go
 
1163
type HashResponse struct {
 
1164
    Sum string
 
1165
}
 
1166
```
 
1167
 
 
1168
Example: `GET wordpress/meta/hash256`
 
1169
 
 
1170
Response body:
 
1171
```json
 
1172
{
 
1173
    "Sum": "9ab5036cc18ba61a9d25fad389e46b3d407fc02c3eba917fe5f18fdf51ee6924"
 
1174
}
 
1175
```
 
1176
 
 
1177
#### GET *id*/meta/supported-series
 
1178
 
 
1179
This path returns the set of series supported by the given
 
1180
charm. This endpoint is appropriate for charms only.
 
1181
 
 
1182
```go
 
1183
type SupportedSeriesResponse struct {
 
1184
    SupportedSeries []string
 
1185
}
 
1186
```
 
1187
 
 
1188
Example: `GET precise/wordpress/meta/supported-series`
 
1189
 
 
1190
Response body:
 
1191
```json
 
1192
{
 
1193
    "SupportedSeries": ["precise"]
 
1194
}
 
1195
```
 
1196
 
 
1197
#### GET *id*/meta/bundles-containing
 
1198
 
 
1199
The `meta/bundles-containing` path returns information on the last revision of
 
1200
any bundles that contain the charm with the given id.
 
1201
 
 
1202
<pre>
 
1203
GET <i>id</i>/meta/bundles-containing[?include=<i>meta</i>[&include=<i>meta</i>...]]
 
1204
</pre>
 
1205
 
 
1206
The Meta field is populated with information on the returned bundles according
 
1207
to the include flags - see the `meta/any` path for more info on how to use the
 
1208
`include` flag. The only values that are valid for `any-series`, `any-revision`
 
1209
or `all-results` flags are 0, 1 and empty. If `all-results` is enabled, all the
 
1210
bundle revisions are returned, not just the last one. The API should validate
 
1211
that and return bad request if any other value is provided.
 
1212
 
 
1213
```go
 
1214
[]Bundle
 
1215
type Bundle struct {
 
1216
        Id string
 
1217
        Meta map[string]interface{} `json:",omitempty"`
 
1218
}
 
1219
```
 
1220
 
 
1221
Example: `GET mysql/meta/bundles-containing?include=featured` might return:
 
1222
 
 
1223
```json
 
1224
[
 
1225
    {
 
1226
        "Id": "bundle/mysql-scalable",
 
1227
        "Meta": {
 
1228
            "featured": {
 
1229
                "Featured": false
 
1230
            }
 
1231
        }
 
1232
    },
 
1233
    {
 
1234
        "Id": "bundle/wordpress-simple",
 
1235
        "Meta": {
 
1236
            "featured": {
 
1237
                "Featured": true
 
1238
            }
 
1239
        }
 
1240
    }
 
1241
]
 
1242
```
 
1243
 
 
1244
#### GET *id*/meta/extra-info
 
1245
 
 
1246
The meta/extra-info path reports any additional metadata recorded for the
 
1247
charm. This contains only information stored by clients - the API server itself
 
1248
does not populate any fields. The resulting object holds an entry for each
 
1249
piece of metadata recorded with a PUT to `meta/extra-info`.
 
1250
 
 
1251
```go
 
1252
type ExtraInfo struct {
 
1253
        Values map[string] interface{}
 
1254
}
 
1255
```
 
1256
 
 
1257
Example: `GET wordpress/meta/extra-info`
 
1258
 
 
1259
```json
 
1260
{
 
1261
    "featured": true,
 
1262
    "vcs-digest": "4b6b3c7d795eb66ca5f82bc52c01eb57ab595ab2"
 
1263
}
 
1264
```
 
1265
 
 
1266
#### GET *id*/meta/extra-info/*key*
 
1267
 
 
1268
This path returns the contents of the given `extra-info` key. The result is
 
1269
exactly the JSON value stored as a result of the PUT request to `extra-info` or
 
1270
`extra-info/key`.
 
1271
 
 
1272
Example: `GET wordpress/meta/extra-info/featured`
 
1273
 
 
1274
```json
 
1275
true
 
1276
```
 
1277
 
 
1278
#### PUT *id*/meta/extra-info
 
1279
 
 
1280
This request updates the value of any metadata values. Any values that are not
 
1281
mentioned in the request are left untouched. Any fields with null values are
 
1282
deleted.
 
1283
 
 
1284
Example: `PUT precise/wordpress-32/meta/extra-info`
 
1285
 
 
1286
Request body:
 
1287
```json
 
1288
{
 
1289
    "vcs-digest": "7d6a853c7bb102d90027b6add67b15834d815e08",
 
1290
}
 
1291
```
 
1292
 
 
1293
#### PUT *id*/meta/extra-info/*key*
 
1294
 
 
1295
This request creates or updates the value for a specific key.
 
1296
If the value is null, the key is deleted.
 
1297
 
 
1298
Example: `PUT precise/wordpress-32/meta/extra-info/vcs-digest`
 
1299
 
 
1300
Request body:
 
1301
 
 
1302
```json
 
1303
"7d6a853c7bb102d90027b6add67b15834d815e08",
 
1304
```
 
1305
 
 
1306
The above example is equivalent to the `meta/extra-info` example above.
 
1307
 
 
1308
#### GET *id*/meta/charm-related
 
1309
 
 
1310
The `meta/charm-related` path returns all charms that are related to the given
 
1311
charm id, which must not refer to a bundle. It is possible to include
 
1312
additional metadata for charms by using the `include` query:
 
1313
 
 
1314
<pre>
 
1315
GET <i>id</i>/meta/charm-related[?include=<i>meta</i>[&include=<i>meta</i>...]]
 
1316
</pre>
 
1317
 
 
1318
```go
 
1319
type Related struct {
 
1320
        // Requires holds an entry for each interface provided by
 
1321
        // the charm, containing all charms that require that interface.
 
1322
        Requires map[string] []Item        `json:",omitempty"`
 
1323
 
 
1324
 
 
1325
        // Provides holds an entry for each interface required by the
 
1326
        // the charm, containing all charms that provide that interface.
 
1327
        Provides map[string] []Item        `json:",omitempty"`
 
1328
}
 
1329
 
 
1330
 
 
1331
type Item struct {
 
1332
        Id string
 
1333
        Meta map[string] interface{}       `json:",omitempty"`
 
1334
}
 
1335
```
 
1336
 
 
1337
The Meta field is populated according to the include flags  - see the `meta`
 
1338
path for more info on how to use this.
 
1339
 
 
1340
Example: `GET wordpress/meta/charm-related`
 
1341
 
 
1342
```json
 
1343
{
 
1344
    "Requires": {
 
1345
        "memcache": [
 
1346
            {"Id": "precise/memcached-13"}
 
1347
        ],
 
1348
        "db": [
 
1349
            {"Id": "precise/mysql-46"},
 
1350
            {"Id": "~clint-fewbar/precise/galera-42"}
 
1351
        ]
 
1352
    },
 
1353
    "Provides": {
 
1354
        "http": [
 
1355
            {"Id": "precise/apache2-24"},
 
1356
            {"Id": "precise/haproxy-31"},
 
1357
            {"Id": "precise/squid-reverseproxy-8"}
 
1358
        ]
 
1359
    }
 
1360
}
 
1361
```
 
1362
 
 
1363
Example: `GET trusty/juju-gui-3/meta/charm-related?include=charm-config`
 
1364
 
 
1365
```json
 
1366
{
 
1367
    "Provides": {
 
1368
        "http": [
 
1369
            {
 
1370
                "Id": "precise/apache2-24",
 
1371
                "Meta": {
 
1372
                    "charm-config": {
 
1373
                        "Options": {
 
1374
                            "logrotate_count": {
 
1375
                                "Type": "int",
 
1376
                                "Description": "The number of days",
 
1377
                                "Default": 365
 
1378
                            }
 
1379
                        }
 
1380
                    }
 
1381
                }
 
1382
            }
 
1383
        ],
 
1384
        "nrpe-external-master": [
 
1385
            {
 
1386
                "Id": "precise/nova-compute-31",
 
1387
                "Meta": {
 
1388
                    "charm-config": {
 
1389
                        "Options": {
 
1390
                            "bridge-interface": {
 
1391
                                "Type": "string",
 
1392
                                "Description": "Bridge interface",
 
1393
                                "Default": "br100"
 
1394
                            },
 
1395
                            "bridge-ip": {
 
1396
                                "Type": "string",
 
1397
                                "Description": "IP to be assigned to bridge",
 
1398
                                "Default": "11.0.0.1"
 
1399
                            }
 
1400
                        }
 
1401
                    }
 
1402
                }
 
1403
            }
 
1404
        ]
 
1405
    }
 
1406
}
 
1407
```
 
1408
 
 
1409
#### GET *id*/meta/archive-upload-time
 
1410
 
 
1411
The `meta/archive-upload-time` path returns the time the archives for the given
 
1412
*id* was uploaded. The time is formatted according to RFC3339.
 
1413
 
 
1414
```go
 
1415
type ArchiveUploadTimeResponse struct {
 
1416
    UploadTime time.Time
 
1417
}
 
1418
```
 
1419
 
 
1420
Example: `GET trusty/wordpress-42/meta/archive-upload-time`
 
1421
 
 
1422
```json
 
1423
{
 
1424
    "UploadTime": "2014-07-04T13:53:57.403506102Z"
 
1425
}
 
1426
```
 
1427
 
 
1428
#### GET *id*/meta/promulgated
 
1429
 
 
1430
The `promulgated` path reports whether the entity with the given ID is promulgated.
 
1431
Promulgated charms do not require the user portion of the ID to be specified.
 
1432
 
 
1433
```go
 
1434
type PromulgatedResponse struct {
 
1435
        Promulgated bool
 
1436
}
 
1437
```
 
1438
 
 
1439
Example: `GET trusty/wordpress-42/meta/promulgated`
 
1440
 
 
1441
```json
 
1442
{
 
1443
        "Promulgated": true
 
1444
}
 
1445
```
 
1446
 
 
1447
#### GET *id*/meta/can-ingest
 
1448
 
 
1449
The `can-ingest` path reports whether the entity with the given ID is
 
1450
eligible for ingestion. When an entity is manually uploaded (via the /archive
 
1451
endpoint with the POST method), it becomes ineligible for ingestion.
 
1452
 
 
1453
```go
 
1454
type CanIngestResponse struct {
 
1455
        CanIngest bool
 
1456
}
 
1457
```
 
1458
 
 
1459
Example: `GET trusty/wordpress-42/meta/can-ingest`
 
1460
 
 
1461
```json
 
1462
{
 
1463
        "CanIngest": false
 
1464
}
 
1465
```
 
1466
 
 
1467
#### GET *id*/meta/stats
 
1468
 
 
1469
<pre>
 
1470
GET <i>id</i>/meta/stats?[refresh=0|1]
 
1471
</pre>
 
1472
 
 
1473
Many clients will need to use stats to determine the best result. Details for a
 
1474
charm/bundle might require the stats as important information to users.
 
1475
Currently we track deployment stats only. We intend to open this up to
 
1476
additional data. The response includes downloads count for both the specific
 
1477
requested entity revision and for all the revisions, and it is structured as
 
1478
below:
 
1479
 
 
1480
```go
 
1481
// StatsResponse holds the result of an id/meta/stats GET request.
 
1482
type StatsResponse struct {
 
1483
        // ArchiveDownloadCount is superceded by ArchiveDownload but maintained for
 
1484
        // backward compatibility.
 
1485
        ArchiveDownloadCount int64
 
1486
        // ArchiveDownload holds the downloads count for a specific revision of the
 
1487
        // entity.
 
1488
        ArchiveDownload StatsCount
 
1489
        // ArchiveDownloadAllRevisions holds the downloads count for all revisions
 
1490
        // of the entity.
 
1491
        ArchiveDownloadAllRevisions StatsCount
 
1492
}
 
1493
 
 
1494
// StatsCount holds stats counts and is used as part of StatsResponse.
 
1495
type StatsCount struct {
 
1496
        Total int64 // Total count over all time.
 
1497
        Day   int64 // Count over the last day.
 
1498
        Week  int64 // Count over the last week.
 
1499
        Month int64 // Count over the last month.
 
1500
}
 
1501
```
 
1502
 
 
1503
If the refresh boolean parameter is non-zero, the latest stats will be returned without caching.
 
1504
 
 
1505
#### GET *id*/meta/tags
 
1506
 
 
1507
The `tags` path returns any tags that are associated with the entity.
 
1508
 
 
1509
Example: `GET trusty/wordpress-42/meta/tags`
 
1510
 
 
1511
```json
 
1512
{
 
1513
    "Tags": [
 
1514
        "blog",
 
1515
        "cms"
 
1516
    ]
 
1517
}
 
1518
```
 
1519
 
 
1520
#### GET *id*/meta/revision-info
 
1521
 
 
1522
The `revision-info` path returns information about other available revisions of
 
1523
the charm id that the charm store knows about. It will include both older and
 
1524
newer revisions. The fully qualified ids of those charms will be returned in an
 
1525
ordered list from newest to oldest revision. Note that the current revision
 
1526
will be included in the list as it is also an available revision.
 
1527
 
 
1528
```go
 
1529
type RevisionInfoResponse struct {
 
1530
        Revisions []*charm.URL
 
1531
}
 
1532
```
 
1533
 
 
1534
Example: `GET trusty/wordpress-42/meta/revision-info`
 
1535
 
 
1536
```json
 
1537
{
 
1538
    "Revisions": [
 
1539
        "cs:trusty/wordpress-43",
 
1540
        "cs:trusty/wordpress-42",
 
1541
        "cs:trusty/wordpress-41",
 
1542
        "cs:trusty/wordpress-39"
 
1543
    ]
 
1544
}
 
1545
```
 
1546
 
 
1547
#### GET *id*/meta/id
 
1548
 
 
1549
The `id` path returns information on the charm or bundle id, split apart into
 
1550
its various components, including the id itself. The information is exactly
 
1551
that contained within the entity id.
 
1552
 
 
1553
```go
 
1554
type IdResponse struct {
 
1555
        Id *charm.URL
 
1556
        User string
 
1557
        Series string `json:",omitempty"`
 
1558
        Name string
 
1559
        Revision int
 
1560
}
 
1561
```
 
1562
 
 
1563
Example: `GET ~bob/trusty/wordpress/meta/id`
 
1564
 
 
1565
```json
 
1566
{
 
1567
    "Id": "~bob/trusty/wordpress-42",
 
1568
    "User": "bob",
 
1569
    "Series": "trusty",
 
1570
    "Name": "wordpress",
 
1571
    "Revision": 42
 
1572
}
 
1573
```
 
1574
 
 
1575
Example: `GET precise/wordpress/meta/id`
 
1576
 
 
1577
```json
 
1578
{
 
1579
    "Id": "precise/wordpress-42",
 
1580
    "Series": "precise",
 
1581
    "Name": "wordpress",
 
1582
    "Revision": 42
 
1583
}
 
1584
```
 
1585
 
 
1586
Example: `GET bundle/openstack/meta/id`
 
1587
 
 
1588
```json
 
1589
{
 
1590
    "Id": "bundle/openstack-3",
 
1591
    "Series": "bundle",
 
1592
    "Name": "openstack",
 
1593
    "Revision": 3
 
1594
}
 
1595
```
 
1596
 
 
1597
#### GET *id*/meta/id-revision
 
1598
 
 
1599
The `revision` path returns information on the revision of the id. The
 
1600
information is exactly that contained within the id.
 
1601
 
 
1602
```go
 
1603
type Revision struct {
 
1604
        Revision int
 
1605
}
 
1606
```
 
1607
 
 
1608
Example: `GET trusty/wordpress-42/meta/id-revision`
 
1609
 
 
1610
```json
 
1611
{
 
1612
    "Revision": 42
 
1613
}
 
1614
```
 
1615
 
 
1616
#### GET *id*/meta/id-name
 
1617
 
 
1618
The `name` path returns information on the name of the id. The information is
 
1619
exactly that contained within the id.
 
1620
 
 
1621
```go
 
1622
type Name struct {
 
1623
        Name string
 
1624
}
 
1625
```
 
1626
 
 
1627
Example: `GET trusty/wordpress-42/meta/id-name`
 
1628
 
 
1629
```json
 
1630
{
 
1631
    "Name": "wordpress"
 
1632
}
 
1633
```
 
1634
 
 
1635
#### GET *id*/meta/id-user
 
1636
 
 
1637
The `id-user` path returns information on the user name in the id. This
 
1638
information is exactly that contained within the id.
 
1639
 
 
1640
```go
 
1641
type User struct {
 
1642
        User string
 
1643
}
 
1644
```
 
1645
 
 
1646
Example: `GET ~bob/trusty/wordpress-42/meta/id-user`
 
1647
 
 
1648
```json
 
1649
{
 
1650
    "User": "bob"
 
1651
}
 
1652
```
 
1653
 
 
1654
Example: `GET trusty/wordpress-42/meta/id-user`
 
1655
 
 
1656
```json
 
1657
{
 
1658
    "User": ""
 
1659
}
 
1660
```
 
1661
 
 
1662
#### GET *id*/meta/id-series
 
1663
 
 
1664
The `id-series` path returns information on the series in the id. This
 
1665
information is exactly that contained within the id. For bundles, this will
 
1666
return "bundle".
 
1667
 
 
1668
```go
 
1669
type Series struct {
 
1670
        Series string
 
1671
}
 
1672
```
 
1673
 
 
1674
Example: `GET ~bob/trusty/wordpress-42/meta/id-series`
 
1675
 
 
1676
```json
 
1677
{
 
1678
    "Series": "trusty"
 
1679
}
 
1680
```
 
1681
 
 
1682
#### GET *id*/meta/owner
 
1683
 
 
1684
The `owner` path returns information on the owner of the charm or bundle.
 
1685
This is the owner of the charm or bundle referenced by *id* irrespective
 
1686
of whether a user is included in the id.
 
1687
 
 
1688
```go
 
1689
type User struct {
 
1690
        User string
 
1691
}
 
1692
```
 
1693
 
 
1694
Example: `GET ~bob/trusty/wordpress-42/meta/owner`
 
1695
 
 
1696
```json
 
1697
{
 
1698
    "User": "bob"
 
1699
}
 
1700
```
 
1701
 
 
1702
Example: `GET trusty/wordpress-42/meta/owner`
 
1703
 
 
1704
```json
 
1705
{
 
1706
    "User": "charmers"
 
1707
}
 
1708
```
 
1709
 
 
1710
#### GET *id*/meta/common-info
 
1711
 
 
1712
The meta/common-info path reports any common metadata recorded for the base
 
1713
entity. This contains only information stored by clients - the API server
 
1714
itself does not populate any fields. The resulting object holds an entry for
 
1715
each piece of metadata recorded with a PUT to `meta/common-info`.
 
1716
 
 
1717
```go
 
1718
type CommonInfo struct {
 
1719
        Values map[string] interface{}
 
1720
}
 
1721
```
 
1722
 
 
1723
Example: `GET wordpress/meta/common-info`
 
1724
         `GET precise/wordpress-32/meta/common-info`
 
1725
 
 
1726
```json
 
1727
{
 
1728
    "homepage": "http://wordpress.org",
 
1729
    "bugs-url": "http://wordpress.org/bugs",
 
1730
}
 
1731
```
 
1732
 
 
1733
#### GET *id*/meta/common-info/*key*
 
1734
 
 
1735
This path returns the contents of the given `common-info` key. The result is
 
1736
exactly the JSON value stored as a result of the PUT request to `common-info` or
 
1737
`common-info/key`.
 
1738
 
 
1739
Example: `GET wordpress/meta/common-info/homepage`
 
1740
         `GET precise/wordpress-32/meta/common-info/homepage`
 
1741
 
 
1742
```json
 
1743
"http://wordpress.org"
 
1744
```
 
1745
 
 
1746
#### PUT *id*/meta/common-info
 
1747
 
 
1748
This request updates the value of any metadata values. Any values that are not
 
1749
mentioned in the request are left untouched. Any fields with null values are
 
1750
deleted.
 
1751
 
 
1752
Example: `PUT precise/wordpress-32/meta/common-info`
 
1753
 
 
1754
Request body:
 
1755
```json
 
1756
{
 
1757
    "bugs-url": "http://wordpress.org/newbugs",
 
1758
}
 
1759
```
 
1760
 
 
1761
#### PUT *id*/meta/common-info/*key*
 
1762
 
 
1763
This request creates or updates the value for a specific key.
 
1764
If the value is null, the key is deleted.
 
1765
 
 
1766
Example: `PUT precise/wordpress-32/meta/common-info/bugs-url`
 
1767
 
 
1768
Request body:
 
1769
 
 
1770
```json
 
1771
"http://wordpress.org/newbugs",
 
1772
```
 
1773
 
 
1774
The above example is equivalent to the `meta/common-info` example above.
 
1775
 
 
1776
#### GET *id*/meta/resources
 
1777
 
 
1778
The `meta/resources` path returns information on all the resources associated with the given charm *id* as an array of resource objects.
 
1779
 
 
1780
```go
 
1781
 
 
1782
type Resource struct {
 
1783
        // Name identifies the resource.
 
1784
        Name string
 
1785
 
 
1786
        // Type is the name of the resource type. Currently only
 
1787
        // "file" is supported, which is the default if Type is not specified.
 
1788
        Type string
 
1789
 
 
1790
        // Path holds where the resource will be stored on units
 
1791
        // deployed with the charm.
 
1792
        Path string
 
1793
 
 
1794
        // Description contains user-facing info about the resource.
 
1795
        Description string `json:",omitempty"`
 
1796
 
 
1797
        // Revision is the revision, if applicable.
 
1798
        Revision int
 
1799
 
 
1800
        // Fingerprint is the SHA-384 checksum for the resource blob.
 
1801
        Fingerprint []byte
 
1802
 
 
1803
        // Size is the size of the resource, in bytes.
 
1804
        Size int64
 
1805
}
 
1806
 
 
1807
[]Resource
 
1808
```
 
1809
 
 
1810
#### GET *id*/meta/resources/*name*[/*revision*]
 
1811
 
 
1812
This endpoint retrieves information on the resource with the given *name*
 
1813
associated with the charm *id* as a resource object (see above).
 
1814
 
 
1815
If *revision* is omitted, information on the latest revision of the resource is returned.
 
1816
 
 
1817
### Resources
 
1818
 
 
1819
#### POST *id*/resource/*name*?hash=*sha384*[&filename=*path*]
 
1820
 
 
1821
 
 
1822
Posting to the `resource` path uploads a resource (an arbitrary "blob"
 
1823
of data) associated with the charm with the given *id*, which must not
 
1824
be a bundle. The *sha384* parameter
 
1825
must hold the hex-encoded SHA384 hash of the blob.
 
1826
 
 
1827
If provided, the *path* parameter should hold the filename
 
1828
that the resource has been read from, and its file extension will
 
1829
be verified against the extension of the filename in the
 
1830
declared charm metadata resources of the resolved charm.
 
1831
 
 
1832
As a special case, if the filename in the charm metadata has no
 
1833
extension, any file name will be allowed.
 
1834
 
 
1835
```go
 
1836
type ResourcesRevision struct {
 
1837
        Revision int
 
1838
}
 
1839
```
 
1840
 
 
1841
#### GET *id*/resource/*name*[/*revision*]
 
1842
 
 
1843
Getting from the `/resource` path retrieves a charm resource from the charm
 
1844
with the given id. If version is not specified, it retrieves the latest published
 
1845
version of the resource (for the "unpublished" channel, this will be
 
1846
the most recently uploaded version of the resource).
 
1847
 
 
1848
The SHA-384 checksum of the data is returned
 
1849
in the Content-Sha384 HTTP response header.
 
1850
 
 
1851
### Search
 
1852
 
 
1853
#### GET search
 
1854
 
 
1855
The `search` path searches within the latest version of charms and bundles
 
1856
within the store.
 
1857
 
 
1858
<pre>
 
1859
GET search[?text=<i>text</i>][&autocomplete=1][&filter=<i>value</i>...][&limit=<i>limit</i>][&skip=<i>skip</i>][&include=<i>meta</i>[&include=<i>meta</i>...]][&sort=<i>field</i>]
 
1860
</pre>
 
1861
 
 
1862
`text` specifies any text to search for. If `autocomplete` is specified, the
 
1863
search will return only charms and bundles with a name that has text as a
 
1864
prefix. `limit` limits the number of returned items to the specified limit
 
1865
count. `skip` skips over the first skip items in the result. Any number of
 
1866
filters may be specified, limiting the search to items with attributes that
 
1867
match the specified filter value. Items matching any of the selected values for
 
1868
a filter are selected, so `name=1&name=2` would match items whose name was
 
1869
either 1 or 2. However, if multiple filters are specified, the charm must match
 
1870
all of them, so `name=1&series=2` will only match charms whose name is 1 and
 
1871
whose series is 2. Available filters are:
 
1872
 
 
1873
* tags - the set of tags associated with the charm.
 
1874
* name - the charm's name.
 
1875
* owner - the charm's owner (the ~user element of the charm id)
 
1876
* promulgated - the charm has been promulgated.
 
1877
* provides - interfaces provided by the charm.
 
1878
* requires - interfaces required by the charm.
 
1879
* series - the charm's series.
 
1880
* summary - the charm's summary text.
 
1881
* description - the charm's description text.
 
1882
* type - "charm" or "bundle" to search only one doctype or the other.
 
1883
 
 
1884
 
 
1885
Notes
 
1886
 
 
1887
1. filtering on a specified, but empty, owner is the same as filtering on promulgated=1.
 
1888
2. a specified, but empty text field will return all charms and bundles.
 
1889
3. the promulgated filter is only applied if specified. If the value is "1" then only
 
1890
   promulgated entities are returned if it is any other value only non-promulgated
 
1891
   entities are returned.
 
1892
 
 
1893
The response contains a list of information on the charms or bundles that were
 
1894
matched by the request. If no parameters are specified, all charms and bundles
 
1895
will match.  By default, only the charm store id is included.
 
1896
 
 
1897
The results are sorted according to the given sort field, which may be one of
 
1898
`owner`, `name` or `series`, corresponding to the filters of the same names. If
 
1899
the field is prefixed with a hyphen (-), the sorting order will be reversed. If
 
1900
the sort field is not specified, the results are returned in
 
1901
most-relevant-first order if the text filter was specified, or an arbitrary
 
1902
order otherwise. It is possible to specify more than one sort field to get
 
1903
multi-level sorting, e.g. sort=name,-series will get charms in order of the
 
1904
charm name and then in reverse order of series.
 
1905
 
 
1906
The Meta field is populated according to the include flag  - see the `meta`
 
1907
path for more info on how to use this.
 
1908
 
 
1909
```go
 
1910
[]SearchResult
 
1911
 
 
1912
type SearchResult struct {
 
1913
        Id string
 
1914
        // Meta holds at most one entry for each meta value
 
1915
        // specified in the include flags, holding the
 
1916
        // data that would be returned by reading /meta/meta?id=id.
 
1917
        // Metadata not relevant to a particular result will not
 
1918
        // be included.
 
1919
        Meta map[string] interface{} `json:",omitempty"`
 
1920
}
 
1921
```
 
1922
 
 
1923
Example: `GET search?text=word&autocomplete=1&limit=2&include=archive-size`
 
1924
 
 
1925
```json
 
1926
[
 
1927
    {
 
1928
        "Id": "precise/wordpress-1",
 
1929
        "Meta": {
 
1930
            "archive-size": {
 
1931
                "Size": 1024
 
1932
            }
 
1933
        }
 
1934
    },
 
1935
    {
 
1936
        "Id": "precise/wordpress-2",
 
1937
        "Meta": {
 
1938
            "archive-size": {
 
1939
                "Size": 4242
 
1940
            }
 
1941
        }
 
1942
    }
 
1943
]
 
1944
```
 
1945
 
 
1946
#### GET search/interesting
 
1947
 
 
1948
This returns a list of bundles and charms which are interesting from the Juju
 
1949
GUI perspective. Those are shown on the left sidebar of the GUI when no other
 
1950
search requests are performed.
 
1951
 
 
1952
`GET search/interesting[?limit=limit][&include=meta]`
 
1953
 
 
1954
The Meta field is populated according to the include flag  - see the `meta`
 
1955
path for more info on how to use this.
 
1956
The `limit` flag is the same as for the "search" path.
 
1957
 
 
1958
### List
 
1959
 
 
1960
#### GET list
 
1961
 
 
1962
The `list` path lists charms and bundles within the store.
 
1963
 
 
1964
<pre>
 
1965
GET list[?filter=<i>value</i>...][&include=<i>meta</i>[&include=<i>meta</i>...]][&sort=<i>field</i>]
 
1966
</pre>
 
1967
 
 
1968
Any number of filters may be specified, limiting the list to items with attributes that
 
1969
match the specified filter value. Items matching any of the selected values for
 
1970
a filter are selected, so `name=1&name=2` would match items whose name was
 
1971
either 1 or 2. However, if multiple filters are specified, the charm must match
 
1972
all of them, so `name=1&series=2` will only match charms whose name is 1 and
 
1973
whose series is 2. Available filters are:
 
1974
 
 
1975
* name - the charm's name.
 
1976
* owner - the charm's owner (the ~user element of the charm id)
 
1977
* promulgated - the charm has been promulgated.
 
1978
* series - the charm's series.
 
1979
* type - "charm" or "bundle" to search only one doctype or the other.
 
1980
 
 
1981
 
 
1982
Notes
 
1983
 
 
1984
1. the promulgated filter is only applied if specified. If the value is "1" then only
 
1985
   promulgated entities are returned if it is any other value only non-promulgated
 
1986
   entities are returned.
 
1987
 
 
1988
The response contains a list of information on the charms or bundles that were
 
1989
matched by the request. If no parameters are specified, all charms and bundles
 
1990
will match.  By default, only the charm store id is included.
 
1991
 
 
1992
The results are sorted according to the given sort field, which may be one of
 
1993
`owner`, `name` or `series`, corresponding to the filters of the same names. If
 
1994
the field is prefixed with a hyphen (-), the sorting order will be reversed. If
 
1995
the sort field is not specified the order will be a server side logical order. 
 
1996
It is possible to specify more than one sort field to get
 
1997
multi-level sorting, e.g. sort=name,-series will get charms in order of the
 
1998
charm name and then in reverse order of series.
 
1999
 
 
2000
The Meta field is populated according to the include flag  - see the `meta`
 
2001
path for more info on how to use this.
 
2002
 
 
2003
```go
 
2004
[]EntityResult
 
2005
 
 
2006
type EntityResult struct {
 
2007
        Id string
 
2008
        // Meta holds at most one entry for each meta value
 
2009
        // specified in the include flags, holding the
 
2010
        // data that would be returned by reading /meta/meta?id=id.
 
2011
        // Metadata not relevant to a particular result will not
 
2012
        // be included.
 
2013
        Meta map[string] interface{} `json:",omitempty"`
 
2014
}
 
2015
```
 
2016
 
 
2017
Example: `GET list?name=wordpress&include=archive-size`
 
2018
 
 
2019
```json
 
2020
[
 
2021
    {
 
2022
        "Id": "precise/wordpress-1",
 
2023
        "Meta": {
 
2024
            "archive-size": {
 
2025
                "Size": 1024
 
2026
            }
 
2027
        }
 
2028
    },
 
2029
    {
 
2030
        "Id": "precise/wordpress-2",
 
2031
        "Meta": {
 
2032
            "archive-size": {
 
2033
                "Size": 4242
 
2034
            }
 
2035
        }
 
2036
    }
 
2037
]
 
2038
```
 
2039
 
 
2040
### Debug info
 
2041
 
 
2042
#### GET /debug
 
2043
 
 
2044
**Not yet implemented**
 
2045
 
 
2046
This returns metadata describing the current version of the software running
 
2047
the server, and any other information deemed appropriate. The specific form of
 
2048
 the returned data is deliberately left unspecified for now.
 
2049
 
 
2050
#### GET /debug/status
 
2051
 
 
2052
Used as a health check of the service. The API will also be used for nagios
 
2053
tests. The items that are checked:
 
2054
 
 
2055
* connection to MongoDB
 
2056
* connection to ElasticSearch (if needed) (based on charm config) (elasticsearch cluster status, all nodes up/etc see charmworld)
 
2057
* number of charms and bundles in the blobstore
 
2058
* number of promulgated items
 
2059
* time and location of service start
 
2060
* time of last ingestion process
 
2061
* did ingestion finish
 
2062
* did ingestion finished without errors (this should not count charm/bundle ingest errors)
 
2063
 
 
2064
```go
 
2065
type DebugStatuses map[string] struct {
 
2066
    Name string
 
2067
    Value string
 
2068
    Passed bool
 
2069
}
 
2070
```
 
2071
 
 
2072
Example: `GET /debug/status`
 
2073
 
 
2074
```json
 
2075
{
 
2076
    "mongo_connected" : {
 
2077
        "Name": "MongoDB is connected",
 
2078
        "Value": "Connected",
 
2079
        "Passed": true
 
2080
    },
 
2081
    "mongo_collections" : {
 
2082
        "Name": "MongoDB collections",
 
2083
        "Value": "All required collections exist",
 
2084
        "Passed": true
 
2085
    },
 
2086
    "ES_connected": {
 
2087
        "Name": "ElasticSearch is connected",
 
2088
        "Value": "Connected",
 
2089
        "Passed": true
 
2090
    },
 
2091
    "entities": {
 
2092
        "Name": "Entities in charm store",
 
2093
        "Value": "5701 charms; 2000 bundles; 42 promulgated",
 
2094
        "Passed": true,
 
2095
    },
 
2096
    "server_started": {
 
2097
        "Name": "Server started",
 
2098
        "Value": "123.45.67.89 2014-09-16 11:12:29Z",
 
2099
        "Passed": true
 
2100
    },
 
2101
}
 
2102
```
 
2103
 
 
2104
### Permissions
 
2105
 
 
2106
All entities in the charm store have their own access control lists. Read and
 
2107
write permissions are supported for specific users and groups. By default, all
 
2108
charms and bundles are readable by everyone, meaning that anonymous users can
 
2109
retrieve archives and metadata information without restrictions. The permission
 
2110
endpoints can be used to retrieve or change entities' permissions.
 
2111
 
 
2112
#### GET *id*/meta/perm
 
2113
 
 
2114
This path reports the read and write ACLs for the charm or bundle.
 
2115
 
 
2116
```go
 
2117
type PermResponse struct {
 
2118
    Read  []string
 
2119
    Write []string
 
2120
}
 
2121
```
 
2122
 
 
2123
If the `Read` ACL is empty, the entity and its metadata cannot be retrieved by
 
2124
anyone.
 
2125
If the `Write` ACL is empty, the entity cannot be modified by anyone.
 
2126
The special user `everyone` indicates that the corresponding operation
 
2127
(read or write) can be performed by everyone, including anonymous users.
 
2128
 
 
2129
Example: `GET ~joe/wordpress/meta/perm`
 
2130
 
 
2131
```json
 
2132
{
 
2133
    "Read": ["everyone"],
 
2134
    "Write": ["joe"]
 
2135
}
 
2136
```
 
2137
 
 
2138
#### PUT *id*/meta/perm
 
2139
 
 
2140
This request updates the permissions associated with the charm or bundle.
 
2141
 
 
2142
```go
 
2143
type PermResponse struct {
 
2144
    Read  []string
 
2145
    Write []string
 
2146
}
 
2147
```
 
2148
 
 
2149
If the Read or Write ACL is empty or missing from the request body, that
 
2150
field will be overwritten as empty. See the *id*/meta/perm/*key* request
 
2151
to PUT only Read or Write.
 
2152
 
 
2153
Example: `PUT precise/wordpress-32/meta/perm`
 
2154
 
 
2155
Request body:
 
2156
```json
 
2157
{
 
2158
    "Read": ["everyone"],
 
2159
    "Write": ["joe"]
 
2160
}
 
2161
```
 
2162
 
 
2163
#### GET *id*/meta/perm/*key*
 
2164
 
 
2165
This path returns the contents of the given permission *key* (that can be
 
2166
`read` or `write`). The result is exactly the JSON value stored as a result of
 
2167
the PUT request to `meta/perm/key`.
 
2168
 
 
2169
Example: `GET wordpress/meta/perm/read`
 
2170
 
 
2171
```json
 
2172
["everyone"]
 
2173
```
 
2174
 
 
2175
#### PUT *id*/meta/perm/*key*
 
2176
 
 
2177
This request updates the *key* permission associated with the charm or bundle,
 
2178
where *key* can be `read` or `write`.
 
2179
 
 
2180
Example: `PUT precise/wordpress-32/meta/perm/read`
 
2181
 
 
2182
Request body:
 
2183
 
 
2184
```json
 
2185
["joe", "frank"]
 
2186
```
 
2187
 
 
2188
### Authorization
 
2189
 
 
2190
#### GET /macaroon
 
2191
 
 
2192
This endpoint returns a macaroon in JSON format that, when its third party 
 
2193
caveats are discharged, will allow access to the charm store. No prior 
 
2194
authorization is required.
 
2195
 
 
2196
#### GET /delegatable-macaroon
 
2197
 
 
2198
This endpoint returns a macaroon in JSON format that can be passed to
 
2199
third parties to allow them to access the charm store on the user's
 
2200
behalf. If the "id" parameter is specified (url encoded), the returned
 
2201
macaroon will be restricted for use only with the entity with the 
 
2202
given id.
 
2203
 
 
2204
A delegatable macaroon will only be returned to an authorized user (not 
 
2205
including admin). It will carry the same privileges as the macaroon used 
 
2206
to authorize the request, but is suitable for use by third parties.
 
2207
 
 
2208
#### GET /whoami
 
2209
 
 
2210
This endpoint returns the user name of the client and the list of groups the 
 
2211
user is a member of. This endpoint requires authorization.
 
2212
 
 
2213
Example: `GET whoami`
 
2214
 
 
2215
```json
 
2216
{
 
2217
    "User": "alice",
 
2218
    "Groups": ["charmers", "admin", "team-awesome"]
 
2219
}
 
2220
```
 
2221
 
 
2222
The response is defined as:
 
2223
```go
 
2224
type WhoAmIResponse struct {
 
2225
    User string
 
2226
    Groups []string
 
2227
}
 
2228
```
 
2229
 
 
2230
### Logs
 
2231
 
 
2232
#### GET /log
 
2233
 
 
2234
This endpoint returns the log messages stored on the charm store. It is
 
2235
possible to save them by sending POST requests to the same endpoint (see
 
2236
below). For instance, the ingestion of charms/bundles produces logs that are
 
2237
collected and send to the charm store by the ingestion client.
 
2238
 
 
2239
`GET /log[?limit=count][&skip=count][&id=entity-id][&level=log-level][&type=log-type]`
 
2240
 
 
2241
 
 
2242
Each log message is defined as:
 
2243
 
 
2244
```go
 
2245
type LogResponse struct {
 
2246
        // Data holds the log message as a JSON-encoded value.
 
2247
        Data json.RawMessage
 
2248
 
 
2249
        // Level holds the log level as a string.
 
2250
        Level LogLevel
 
2251
 
 
2252
        // Type holds the log type as a string.
 
2253
        Type LogType
 
2254
 
 
2255
        // URLs holds a slice of entity URLs associated with the log message.
 
2256
        URLs []`*`charm.URL `json:",omitempty"`
 
2257
 
 
2258
        // Time holds the time of the log.
 
2259
        Time time.Time
 
2260
}
 
2261
```
 
2262
 
 
2263
The log entries are ordered by last inserted (most recent logs first), and by
 
2264
default the last 1000 logs are returned. Use the `limit` and skip `query`
 
2265
parameters to change the default behavior. Logs can further be filtered by log
 
2266
level (“info”, “warning” or “error”) and by related entity id. The type query
 
2267
parameter groups entries by type. For instance, to request all the ingestion
 
2268
errors related to the *utopic/django* charm, use the following URL:
 
2269
 
 
2270
`/log?type=ingestion&level=error&id=utopic/django`
 
2271
 
 
2272
#### POST /log
 
2273
 
 
2274
This endpoint uploads logs to the charm store. The request content type must be
 
2275
`application/json`. The body must contain the JSON representation of a list of
 
2276
logs, each one being in this format:
 
2277
 
 
2278
```go
 
2279
type Log struct {
 
2280
        // Data holds the log message as a JSON-encoded value.
 
2281
        Data *json.RawMessage
 
2282
 
 
2283
        // Level holds the log level as a string.
 
2284
        Level LogLevel
 
2285
 
 
2286
        // Type holds the log type as a string.
 
2287
        Type LogType
 
2288
 
 
2289
        // URLs holds a slice of entity URLs associated with the log message.
 
2290
        URLs []*charm.URL `json:",omitempty"`
 
2291
}
 
2292
```
 
2293
 
 
2294
Nothing is returned if the request succeeds. Otherwise, an error is returned.
 
2295
 
 
2296
### Changes
 
2297
 
 
2298
Each charm store has a global feed for all new published charms and bundles.
 
2299
 
 
2300
#### GET changes/published
 
2301
 
 
2302
This endpoint returns the ids of published charms or bundles published, most
 
2303
recently published first.
 
2304
 
 
2305
`GET changes/published[?limit=count][&start=fromdate][&stop=todate]`
 
2306
 
 
2307
The `fromdate` and `todate` values constrain the range of publish dates, in
 
2308
"yyyy-mm-dd" format. If `fromdate` is specified only charms published on or
 
2309
after that date are returned; if `todate` is specified, only charms published
 
2310
on or before that date are returned. If the `limit` count is specified, it must
 
2311
be positive, and only the first count results are returned. The published time
 
2312
is in RFC3339 format.
 
2313
 
 
2314
```go
 
2315
[]Published
 
2316
type Published struct {
 
2317
        Id string
 
2318
        PublishTime time.Time
 
2319
}
 
2320
```
 
2321
 
 
2322
Example: `GET changes/published`
 
2323
 
 
2324
```json
 
2325
[
 
2326
    {
 
2327
        "Id": "cs:trusty/wordpress-42",
 
2328
        "PublishTime": "2014-07-31T15:04:05Z"
 
2329
    },
 
2330
    {
 
2331
        "Id": "cs:trusty/mysql-11",
 
2332
        "PublishTime": "2014-07-30T14:20:00Z"
 
2333
    },
 
2334
    {
 
2335
        "Id": "cs:bundle/mediawiki",
 
2336
        "PublishTime": "2014-07-29T13:45:10Z"
 
2337
    }
 
2338
]
 
2339
```
 
2340
 
 
2341
Example: `GET changes/published?limit=10&start=31-07-2014`
 
2342
 
 
2343
```json
 
2344
[
 
2345
    {
 
2346
        "Id": "cs:trusty/wordpress-42",
 
2347
        "PublishTime": "2014-07-31T15:04:05Z"
 
2348
    }
 
2349
]
 
2350
```