Merge lp:~jujudocs/juju-core/docs-reorg into lp:juju-core/docs

Proposed by Nick Veitch
Status: Merged
Merged at revision: 140
Proposed branch: lp:~jujudocs/juju-core/docs-reorg
Merge into: lp:juju-core/docs
Diff against target: 5678 lines (+3495/-1230)
55 files modified
htmldocs/authors-charm-anatomy.html (+0/-525)
htmldocs/authors-charm-best-practice.html (+4/-0)
htmldocs/authors-charm-components.html (+235/-0)
htmldocs/authors-charm-config.html (+244/-0)
htmldocs/authors-charm-hooks.html (+387/-0)
htmldocs/authors-charm-icon.html (+4/-0)
htmldocs/authors-charm-interfaces.html (+340/-0)
htmldocs/authors-charm-metadata.html (+376/-0)
htmldocs/authors-charm-policy.html (+5/-1)
htmldocs/authors-charm-quality.html (+4/-0)
htmldocs/authors-charm-store.html (+4/-0)
htmldocs/authors-charm-upgrades.html (+212/-0)
htmldocs/authors-charm-writing.html (+5/-1)
htmldocs/authors-charms-in-action.html (+0/-296)
htmldocs/authors-hook-debug.html (+169/-0)
htmldocs/authors-hook-environment.html (+561/-0)
htmldocs/authors-hook-errors.html (+194/-0)
htmldocs/authors-hook-kinds.html (+402/-0)
htmldocs/authors-hooks.html (+0/-185)
htmldocs/authors-implicit-relations.html (+4/-0)
htmldocs/authors-interfaces.html (+4/-0)
htmldocs/authors-intro.html (+5/-1)
htmldocs/authors-relations-in-depth.html (+187/-0)
htmldocs/authors-service-config.html (+0/-208)
htmldocs/authors-subordinate-services.html (+4/-0)
htmldocs/authors-testing.html (+4/-0)
htmldocs/charms-config.html (+4/-0)
htmldocs/charms-constraints.html (+4/-0)
htmldocs/charms-deploying.html (+4/-0)
htmldocs/charms-destroy.html (+4/-0)
htmldocs/charms-exposing.html (+4/-0)
htmldocs/charms-relations.html (+4/-0)
htmldocs/charms-scaling.html (+4/-0)
htmldocs/charms-service-groups.html (+4/-0)
htmldocs/charms-upgrading.html (+4/-0)
htmldocs/charms.html (+4/-0)
htmldocs/commands.html (+4/-0)
htmldocs/config-aws.html (+4/-0)
htmldocs/config-azure.html (+4/-0)
htmldocs/config-hpcloud.html (+4/-0)
htmldocs/config-local.html (+4/-0)
htmldocs/config-maas.html (+4/-0)
htmldocs/config-openstack.html (+4/-0)
htmldocs/contributing.html (+4/-0)
htmldocs/getting-started-keygen-win.html (+4/-0)
htmldocs/getting-started.html (+4/-0)
htmldocs/glossary.html (+4/-0)
htmldocs/howto-gui-management.html (+4/-0)
htmldocs/howto-node.html (+4/-0)
htmldocs/howto-rails.html (+4/-0)
htmldocs/howto.html (+4/-0)
htmldocs/navigation.html (+15/-8)
htmldocs/navigation.json (+20/-5)
htmldocs/reference-constraints.html (+2/-0)
htmldocs/tools-charm-tools.html (+4/-0)
To merge this branch: bzr merge lp:~jujudocs/juju-core/docs-reorg
Reviewer Review Type Date Requested Status
Nick Veitch (community) Approve
Review via email: mp+190236@code.launchpad.net

Description of the change

docs re-org and charm author additions

To post a comment you must log in.
Revision history for this message
Nick Veitch (evilnick) wrote :

Um, this is why it has taken a long time...
  "Diff against target: 5678 lines (+3495/-1230)"

Revision history for this message
Nick Veitch (evilnick) wrote :

Not that I expect a medal or anything

Revision history for this message
Nick Veitch (evilnick) wrote :

Hurrah! Good work there... Approve

review: Approve
Revision history for this message
Antonio Rosales (arosales) wrote :

Looks good Nick, thanks for the work on this branch.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'htmldocs/authors-charm-anatomy.html'
2--- htmldocs/authors-charm-anatomy.html 2013-09-27 14:53:30 +0000
3+++ htmldocs/authors-charm-anatomy.html 1970-01-01 00:00:00 +0000
4@@ -1,525 +0,0 @@
5-<!DOCTYPE html>
6-<html>
7-<!--Head-->
8- <head>
9- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
10- <title>Juju Documentation</title>
11- <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
12- <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
13- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
14- <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
15- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
16- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
17- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
18- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
19- <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
20- <link href="./css/main.css" rel="stylesheet" type="text/css">
21-
22- <!--[if lt IE 9]>
23- <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
24- <![endif]-->
25- </head>
26-<!--End-Head-->
27-
28-
29-
30- <body class="resources">
31-<!--Header-->
32-
33- <header class="banner global" role="banner">
34- <nav role="navigation" class="nav-primary nav-right">
35- <div class="logo">
36- <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
37- <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
38- <span>Juju</span>
39- </a>
40- </div>
41- <ul>
42- <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
43- <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
44- <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
45- <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
46- <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
47- <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
48- <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
49- </ul>
50- <div id="box-search">
51- <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
52- <label class="off-left" for="s">Search:</label>
53- <input class="form-text" type="text" value="" name="s" id="s" />
54- <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
55- </form>
56- </div>
57- </nav>
58- </header>
59-<!--End-Header-->
60-<!--Preamble-->
61-<div class="wrapper">
62- <div id="main-content" class="inner-wrapper" role="main">
63- <div class="row no-border">
64- <div class="header-navigation-secondary"></div>
65- <h2 class="pagetitle">Juju documentation</h2>
66- </div>
67- <section id="content" class="container-12">
68- <div class="grid-12 doc-container">
69- <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
70- <div class="grid-9 doc-content">
71-<!--End-Preamble-->
72-<article>
73-<section id="charm-anatomy">
74-<h1>Anatomy of a charm</h1>
75-<p>Charms define how services integrate and how their service units
76-react to events in the distributed environment, as orchestrated by
77-juju.</p>
78-<p>This specification describes how charms are defined, including their
79-metadata and hooks. It also describes the resources available to hooks
80-in working with the juju environment.</p>
81-
82-<h2>The metadata file</h2>
83-<p>The <cite>metadata.yaml</cite> file, at the root of the charm directory,
84-describes the charm. The following fields are supported:</p>
85-<blockquote>
86-<ul>
87-<li><strong>name:</strong> - The charm name itself. Charm names are formed by
88-lowercase letters, digits, and dashes, and must necessarily
89-begin with a letter and have no digits alone in a dashed
90-section.</li>
91-<li><strong>summary:</strong> - A one-line description of the charm.</li>
92-<li><strong>maintainer:</strong> - An RFC2822 compliant email address that should
93-be the main point of contact for development of this charm.</li>
94-<li><strong>description:</strong> - Long explanation of the charm and its
95-features.</li>
96-<li><strong>categories</strong> - all charms should contain a category so it looks correctly in the web UI, any one of the following is acceptable: "databases", "file-servers", "applications", "cache-proxy", "app-servers" and "misc".</li>
97-<li><strong>provides:</strong> - The deployed service unit must have the given
98-relations established with another service unit whose charm
99-requires them for the service to work properly. See below for how
100-to define a relation.</li>
101-<li><strong>requires:</strong> - The deployed service unit must have the given
102-relations established with another service unit whose charm
103-provides them for the service to work properly. See below for how
104-to define a relation.</li>
105-<li><strong>peers:</strong> - Relations that are established with P2P semantics
106-instead of a provides/requires (or client/server) style. When the
107-charm is deployed as a service unit, all the units from the
108-given service will automatically be made part of the relation.
109-See below for how to define a relation.</li>
110-</ul>
111-</blockquote>
112-
113-<p>Relations available in <cite>provides</cite>, <cite>requires</cite>, and <cite>peers</cite> are defined
114-as follows:</p>
115-<blockquote>
116-<ul>
117-<li><p class="first"><strong>provides|requires|peers:</strong></p>
118-<ul>
119-<li><p class="first"><strong>&lt;relation name&gt;:</strong> - This name is a user-provided value which
120-identifies the relation uniquely within the given charm.
121-Examples include &quot;database&quot;, &quot;cache&quot;, &quot;proxy&quot;, and &quot;appserver&quot;.</p>
122-<p>Each relation may have the following fields defined:</p>
123-<ul>
124-<li><strong>interface:</strong> - This field defines the type of the
125-relation. The relation will only be established with service
126-units that define a compatible relation with the same
127-interface. Examples include &quot;http&quot;, &quot;mysql&quot;, and
128-&quot;backup-schedule&quot;.</li>
129-<li><strong>limit:</strong> - The maximum number of relations of this kind
130-which may be established to other service units. Defaults to
131-1 for <cite>requires</cite> relations, and to &quot;none&quot; (no limit) for
132-<cite>provides</cite> and <cite>peers</cite> relations. While you may define it,
133-this field is not yet enforced by juju.</li>
134-<li><strong>optional:</strong> - Whether this relation is required for the
135-service unit to function or not. Defaults to <cite>false</cite>, which
136-means the relation is required. While you may define it, this
137-field is not yet enforced by juju.</li>
138-<li><strong>scope:</strong> - Controls which units of related-to services can
139-be communicated with through this relationship. Juju supports
140-the following scopes:<ul>
141-<li><strong>global:</strong> <cite>default</cite> When a traditional relation is added
142-between two services, all the service units for the first service will
143-receive relation events about all service units for the second
144-service.</li>
145-<li><strong>container</strong>: Communication is restricted to units deployed
146-in the same container. It is not possible to establish a
147-container scoped relation between principal services. See
148-<a href="authors-subordinate-services.html"><em>Subordinate services</em></a>.</li>
149-</ul>
150-</li>
151-</ul>
152-<p>As a shortcut, if these properties are not defined, and instead
153-a single string value is provided next to the relation name, the
154-string is taken as the interface value, as seen in this
155-example:</p>
156-<pre><code>requires:
157- db: mysql</code></pre>
158-
159-</li>
160-</ul>
161-</li>
162-</ul>
163-</blockquote>
164-<p>Some sample charm definitions are provided at the end of this
165-specification.</p>
166-</section>
167-
168-<section id="hooks">
169-<h2>Hooks</h2>
170-<p>Juju uses hooks to notify a service unit about changes happening
171-in its lifecycle or the larger distributed environment. A hook running
172-for a service unit can query this environment, make any desired local
173-changes on its underlying machine, and change the relation
174-settings.</p>
175-<p>Each hook for a charm is implemented by placing an executable with
176-the desired hook name under the <span class="pre">hooks/</span> directory of the charm
177-directory. juju will execute the hook based on its file name when
178-the corresponding event occurs.</p>
179-<p>All hooks are optional. Not including a corresponding executable in
180-the charm is treated by juju as if the hook executed and then
181-exited with an exit code of 0.</p>
182-<p>All hooks are executed in the charm directory on the service unit.</p>
183-<p>The following hooks are with respect to the lifecycle of a service unit:</p>
184-<blockquote>
185-<ul>
186-<li><strong>install</strong> - Runs just once during the life time of a service
187-unit. Currently this hook is the right place to ensure any package
188-dependencies are met. However, in the future juju will use the
189-charm metadata to perform this role instead.</li>
190-<li><strong>config-changed</strong> - runs once after installation, and in response
191-to configuration changes (e.g. <span class="pre">juju</span> <span class="pre">set</span>). Service configuration
192-actions such as config file generation or runtime tuning should
193-happen here.</li>
194-<li><strong>start</strong> - Runs when the service unit is started. This happens
195-before any relation hooks are called. The purpose of this hook is
196-to get the service unit ready for relations to be established.</li>
197-<li><strong>stop</strong> - Runs when the service unit is stopped. If relations
198-exist, they will be broken and the respective hooks called before
199-this hook is called.</li>
200-</ul>
201-</blockquote>
202-<p>The following hooks are called on each service unit as the membership
203-of an established relation changes:</p>
204-<blockquote>
205-<ul>
206-<li><p class="first"><strong>&lt;relation name&gt;-relation-joined</strong> - Runs upon each time a remote
207-service unit joins the relation.</p>
208-</li>
209-<li><p class="first"><strong>&lt;relation name&gt;-relation-changed</strong> - Runs upon each time the
210-following events occur:</p>
211-<ol class="arabic simple">
212-<li>A remote service unit joins the relation, right after the
213-<strong>&lt;relation name&gt;-relation-joined</strong> hook was called.</li>
214-<li>A remote service unit changes its relation settings.</li>
215-</ol>
216-<p>This hook enables the charm to modify the service unit state
217-(configuration, running processes, or anything else) to adapt to
218-the relation settings of remote units.</p>
219-<p>An example usage is that HAProxy needs to be aware of web servers
220-as they become available, including details like its IP
221-address. Web server service units can publish their availability
222-by making the appropriate relation settings in the hook that makes
223-the most sense. Assume the HAProxy uses the relation name of
224-<span class="pre">server</span>. Then upon that happening, the HAProxy in its
225-<span class="pre">server-relation-changed</span> <span class="pre">hook</span> can then change its own
226-configuration as to what is available to be proxied.</p>
227-</li>
228-<li><p class="first"><strong>&lt;relation name&gt;-relation-departed</strong> - Runs upon each time a
229-remote service unit leaves a relation. This could happen because
230-the service unit has been removed, its service has been destroyed,
231-or the relation between this service and the remote service has
232-been removed.</p>
233-<p>An example usage is that HAProxy needs to be aware of web servers
234-when they are no longer available. It can remove each web server
235-its configuration as the corresponding service unit departs the
236-relation.</p>
237-</li>
238-</ul>
239-</blockquote>
240-<p>This relation hook is with respect to the relation itself:</p>
241-<blockquote>
242-<ul>
243-<li><p class="first"><strong>&lt;relation name&gt;-relation-broken</strong> - Runs when a relation which
244-had at least one other relation hook run for it (successfully or
245-not) is now unavailable. The service unit can then clean up any
246-established state.</p>
247-<p>An example might be cleaning up the configuration changes which
248-were performed when HAProxy was asked to load-balance for another
249-service unit.</p>
250-</li>
251-</ul>
252-</blockquote>
253-<p>Note that the coupling between charms is defined by which settings
254-are required and made available to them through the relation hooks and
255-how these settings are used. Those conventions then define what the
256-relation interface really is, and the <strong>interface</strong> name in the
257-<cite>metadata.yaml</cite> file is simply a way to refer to them and avoid the
258-attempting of incompatible conversations. Keep that in mind when
259-designing your charms and relations, since it is a good idea to
260-allow the implementation of the charm to change and be replaced with
261-alternative versions without changing the relation conventions in a
262-backwards incompatible way.</p>
263-
264-<h2>Hook environment</h2>
265-<p>Hooks can expect to be invoked with a standard environment and
266-context. The following environment variables are set:</p>
267-<blockquote>
268-<ul>
269-<li><strong>$JUJU_UNIT_NAME</strong> - The name of the local unit executing,
270-in the form <span class="pre">&lt;service</span> <span class="pre">name&gt;/&lt;unit</span> <span class="pre">sequence&gt;</span>. E.g. <span class="pre">myblog/3</span>.</li>
271-</ul>
272-</blockquote>
273-<p>Hooks called for relation changes will have the follow additional
274-environment variables set:</p>
275-<blockquote>
276-<ul>
277-<li><strong>$JUJU_RELATION</strong> - The relation name this hook is running
278-for. It's redundant with the hook name, but is necessary for
279-the command line tools to know the current context.</li>
280-<li><strong>$JUJU_REMOTE_UNIT</strong> - The unit name of the remote unit
281-which has triggered the hook execution.</li>
282-</ul>
283-</blockquote>
284-
285-<h2>Hook commands for working with relations</h2>
286-<p>In implementing their functionality, hooks can leverage a set of
287-command tools provided by juju for working with relations. These
288-utilities enable the hook to collaborate on their relation settings,
289-and to inquire about the peers the service unit has relations with.</p>
290-<p>The following command line tools are made available:</p>
291-<blockquote>
292-<ul>
293-<li><p class="first"><strong>relation-ids</strong> - List ids for established relations.</p>
294-<p>Example:</p>
295-<pre><span class="n">relation</span><span class="o">-</span><span class="n">ids</span>
296-</pre>
297-
298-</li>
299-<li><p class="first"><strong>relation-list</strong> - List all service units participating in the
300-established relation. This list excludes the local service unit
301-which is executing the command. For <cite>provides</cite> and <cite>requires</cite>
302-relations, this command will always return a single service unit.</p>
303-<p>Example:</p>
304-<pre>MEMBERS=$(relation-list)</pre>
305-
306-</li>
307-<li><p class="first"><strong>relation-get</strong> - Queries a setting from an established relation
308-with one or more service units. This command will read some
309-context information from environment variables (e.g.
310-$JUJU_RELATION_NAME).</p>
311-<p>Examples:</p>
312-<p>Get the IP address from the remote unit which triggered the hook
313-execution:</p>
314-<pre>relation-get ip</pre>
315-
316-<p>Get all the settings from the remote unit which triggered the hook
317-execution:</p>
318-<span class="n">relation</span><span class="o">-</span><span class="n">get</span>
319-
320-
321-<p>Get the port information from the <cite>wordpress/3</cite> unit:</p>
322-<pre>relation-get port wordpress/3</pre>
323-
324-<p>Get all the settings from the <cite>wordpress/3</cite> unit, in JSON format:</p>
325-<pre><span class="n">relation</span><span class="o">-</span><span class="n">get</span> <span class="o">-</span> <span class="n">wordpress</span><span class="o">/</span><span class="mi">3</span>
326-</pre>
327-
328-</li>
329-<li><p class="first"><strong>relation-set</strong> - Changes a setting in an established relation.</p>
330-<p>Examples:</p>
331-<p>Set this unit's port number for other peers to use:</p>
332-<pre>relation-set port=8080</pre>
333-
334-<p>Change two settings at once:</p>
335-<pre>relation-set dbname=wordpress dbpass="super secur3"</pre>
336-
337-<p>Change several settings at once, with a JSON file:</p>
338-<pre>cat settings.json | relation-set</pre>
339-
340-<p>Delete a setting:</p>
341-<pre>relation-set name=</pre>
342-
343-</li>
344-</ul>
345-</blockquote>
346-<p>Changes to relation settings are only committed if the hook exited
347-with an exit code of 0. Such changes will then trigger further hook
348-execution in the remote unit(s), through the <strong>&lt;relation
349-name&gt;-relation-changed</strong> hook. This mechanism enables a general
350-communication mechanism for service units to coordinate.</p>
351-
352-
353-<h2>Hook commands for opening and closing ports></h2>
354-<p>Service exposing determines which ports to expose by using the
355-<span class="pre">open-port</span> and <span class="pre">close-port</span> commands in hooks. They may be
356-executed within any charm hook. The commands take the same
357-arguments:</p>
358-<pre>open-port port[/protocol]
359-
360-close-port port[/protocol]</pre>
361-
362-<p>These commands are executed immediately; they do not depend on the
363-exit status of the hook.</p>
364-<p>As an example, consider the WordPress charm, which has been deployed
365-as <span class="pre">my-wordpress</span>. After completing the setup and restart of Apache,
366-the <span class="pre">wordpress</span> charm can then publish the available port in its
367-<span class="pre">start</span> hook for a given service unit:</p>
368-<pre>open-port 80</pre>
369-
370-<p>External access to the service unit is only allowed when both
371-<span class="pre">open-port</span> is executed within any hook and the administrator has
372-exposed its service. The order in which these happen is not
373-important, however.</p>
374-
375-<p class="note"><strong>Note: </strong>Being able to use any hook may be important for your charm.
376-Ideally, the service does not have ports that are vulnerable if
377-exposed prior to the service being fully ready. But if that's the
378-case, you can solve this problem by only opening the port in the
379-appropriate hook and when the desired conditions are met.</p>
380-
381-<p>Alternatively, you may need to expose more than one port, or expose
382-ports that don't use the TCP protocol. To expose ports for
383-HTTP and HTTPS, your charm could instead make these settings:</p>
384-<pre>open-port 80
385-open-port 443</pre>
386-
387-<p>Or if you are writing a charm for a DNS server that you would like
388-to expose, then specify the protocol to be UDP:</p>
389-<pre>open-port 53/udp</pre>
390-
391-<p>When the service unit is removed or stopped for any reason, the
392-firewall will again be changed to block traffic which was previously
393-allowed to reach the exposed service. Your charm can also do this to
394-close the port:</p>
395-<pre>close-port 80</pre>
396-
397-<p>To be precise, the firewall is only open for the exposed ports during
398-the time both these conditions hold:</p>
399-<blockquote>
400-<ul>
401-<li>A service has been exposed.</li>
402-<li>A corresponding <span class="pre">open-port</span> command has been run (without a
403-subsequent <span class="pre">close-port</span>).</li>
404-</ul>
405-</blockquote>
406-
407-<h2>Sample metadata.yaml files</h2>
408-<p>Below are presented some sample metadata files.</p>
409-<p>MySQL:</p>
410-<pre>name: mysql
411-summary: "A pretty popular database"
412-maintainer: "Juju Charmers &lt;juju@lists.ubuntu.com&gt;"
413-
414-provides:
415- db: mysql</pre>
416-
417-<p>Wordpress:</p>
418-<pre>name: wordpress
419-summary: "A pretty popular blog engine"
420-maintainer: "Juju Charmers &lt;juju@lists.ubuntu.com&gt;"
421-provides:
422- url:
423- interface: http
424-
425-requires:
426- db:
427- interface: mysql</pre>
428-
429-<p>Riak:</p>
430-<pre>name: riak
431-summary: "Scalable K/V Store in Erlang with Clocks :-)"
432-maintainer: "Juju Charmers &lt;juju@lists.ubuntu.com&gt;"
433-provides:
434- endpoint:
435- interface: http
436-
437-peers:
438- ring:
439- interface: riak</pre>
440-
441-</section>
442-</article>
443-<!--Postamble-->
444- </div>
445- </div>
446- </section>
447- </div>
448-</div>
449-<!--End-Postamble-->
450-<!--Footer-->
451- <footer class="global clearfix" role="contentinfo">
452- <nav role="navigation">
453- <div class="footer-a">
454- <div class="clearfix">
455- <ul>
456- <li>
457- <h2><a href="/">Juju</a></h2>
458- <ul>
459- <li><a href="/charms">Charms</a></li>
460- <li><a href="/features">Features</a></li>
461- <li><a href="/deployment">Deployment</a></li>
462- </ul>
463- </li>
464- <li>
465- <h2><a href="/resources">Resources</a></h2>
466- <ul>
467- <li><a href="/resources/juju-overview/">Overview</a></li>
468- <li><a href="/docs/">Documentation</a></li>
469- <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
470- <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
471- <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
472- <li><a href="/resources/videos/">Videos</a></li>
473- <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
474- </ul>
475- </li>
476- <li>
477- <h2><a href="/community">Community</a></h2>
478- <ul>
479- <li><a href="/community/blog/">Juju Blog</a></li>
480- <li><a href="/events/">Events</a></li>
481- <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
482- <li><a href="/community/charmers/">Charmers</a></li>
483- <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
484- <li><a href="/docs/contributing.html">Help with documentation</a></li>
485- <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
486- </ul>
487- </li>
488- <li>
489- <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
490- <ul>
491- <li><a href="https://jujucharms.com/">Charm store</a></li>
492- <li><a href="/download/">Download Juju</a></li>
493- </ul>
494- </li>
495- </ul>
496- </div>
497- </div>
498- </nav>
499- <div class="legal clearfix">
500- <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
501- </div>
502- </footer>
503-
504-<!--End-Footer-->
505-<!--Scripts-->
506- <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
507- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
508- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
509- <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
510- <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
511- <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
512- <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
513- <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
514- <!-- google analytics -->
515- <script>
516- var _gaq = _gaq || [];
517- _gaq.push(['_setAccount', 'UA-1018242-41']);
518- _gaq.push(['_trackPageview']);
519-
520- (function() {
521- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
522- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
523- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
524- })();
525- </script>
526-<!--End-Scripts-->
527-
528-
529-</body></html>
530\ No newline at end of file
531
532=== modified file 'htmldocs/authors-charm-best-practice.html'
533--- htmldocs/authors-charm-best-practice.html 2013-09-27 14:53:30 +0000
534+++ htmldocs/authors-charm-best-practice.html 2013-10-09 20:07:46 +0000
535@@ -23,6 +23,8 @@
536
537
538
539+
540+
541 <body class="resources">
542
543 <!--Header-->
544@@ -220,4 +222,6 @@
545 <!--End-Scripts-->
546
547
548+
549+
550 </body></html>
551
552=== added file 'htmldocs/authors-charm-components.html'
553--- htmldocs/authors-charm-components.html 1970-01-01 00:00:00 +0000
554+++ htmldocs/authors-charm-components.html 2013-10-09 20:07:46 +0000
555@@ -0,0 +1,235 @@
556+<!DOCTYPE html>
557+<html>
558+<!--Head-->
559+ <head>
560+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
561+ <title>Juju Documentation</title>
562+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
563+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
564+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
565+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
566+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
567+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
568+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
569+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
570+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
571+ <link href="./css/main.css" rel="stylesheet" type="text/css">
572+
573+ <!--[if lt IE 9]>
574+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
575+ <![endif]-->
576+ </head>
577+<!--End-Head-->
578+
579+
580+ <body class="resources">
581+<!--Header-->
582+
583+ <header class="banner global" role="banner">
584+ <nav role="navigation" class="nav-primary nav-right">
585+ <div class="logo">
586+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
587+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
588+ <span>Juju</span>
589+ </a>
590+ </div>
591+ <ul>
592+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
593+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
594+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
595+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
596+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
597+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
598+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
599+ </ul>
600+ <div id="box-search">
601+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
602+ <label class="off-left" for="s">Search:</label>
603+ <input class="form-text" type="text" value="" name="s" id="s" />
604+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
605+ </form>
606+ </div>
607+ </nav>
608+ </header>
609+<!--End-Header-->
610+<!--Preamble-->
611+<div class="wrapper">
612+ <div id="main-content" class="inner-wrapper" role="main">
613+ <div class="row no-border">
614+ <div class="header-navigation-secondary"></div>
615+ <h2 class="pagetitle">Juju documentation</h2>
616+ </div>
617+ <section id="content" class="container-12">
618+ <div class="grid-12 doc-container">
619+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
620+ <div class="grid-9 doc-content">
621+<!--End-Preamble-->
622+<article>
623+<section id="charm-contents">
624+<h1>What makes a Charm?</h1>
625+<p>Each charm is a structured bundle of files. Conceptually, charms are composed of metadata, configuration data, and hooks with some extra support files.</p>
626+</section>
627+
628+<section id="required-files">
629+<h2>Required files</h2>
630+<p>A charm requires only a single file in order to be considered valid by juju:
631+<ul>
632+<li><code>metadata.yaml</code> <a href="./authors-charm-metadata.html">describes the
633+ charm</a> and the relations it can participate in.</li>
634+</ul>
635+<p>Of course, a charm which consists solely of metadata may be valid, but it can't actually do anything. For that, some additional files will be required.</p>
636+</section>
637+
638+<section id="special-files">
639+<h2>Special files</h2>
640+<p>The following files will be treated specially, if present:</p>
641+<ul>
642+ <li><code>/hooks</code> must be a directory holding
643+ executables with specific names, that will be invoked by juju at the relevant times.
644+ A charm needs to implement at least one hook in order to do anything at all. How to implement hooks is covered more thoroughly in the <a href="">Hooks section</a></li>
645+ <li><code>config.yaml</code> defines service configuration options.<a href="./authors-charm-config.html">
646+ The config.yaml file is descibed more fully here</a>.</li>
647+ <li><code>icon.svg</code> is used to identify your charm in the GUI and in the charm store.<a href="authors-charm-icon.html">See the walkthrough for creating an icon.</a></li>
648+ <li><code>README</code> is made available in the charm store. It should be
649+ comprehensible to a reasonably ignorant user.</li>
650+ <li><code>revision</code> is now deprecated.</li>
651+ <li> files matching <code>.juju*</code> should <strong>not</strong> be used.</li>
652+</ul>
653+</section>
654+
655+<section id="other-files">
656+<h2>Other files</h2>
657+
658+<p>Any other files you know you'll need can be placed in the charm for convenience.
659+It is recommended to leave the hooks directory for the executable hooks alone - library
660+code may be included elsewhere in the charm.</p>
661+
662+<p>When hooks are actually running, they can read and write to the charm directory
663+freely, but should carefully observe the caveats in the next section...</p>
664+</section>
665+
666+<section id="runtime-files">
667+<h2>Charm files at runtime</h2>
668+
669+<p>The files you store with your charm should <em>not</em> be used directly by the
670+software installed by your charm. If the files are really needed by the software
671+at runtime, copy them on the system alongside the software and reference those
672+instead.</p>
673+
674+<p>This is because the software does <em>not</em> have control over the charm directory;
675+<em>juju</em> has control over the charm directory, which it temporarily cedes to the
676+charm only when running a hook. Juju will occasionally do things to the contents
677+of that directory that assume it is neither read nor written outside a hook, and
678+the results of such interactions can only be undefined.</p>
679+
680+<p>The only files you should be writing into the charm directory should be written
681+by hooks and accessed only by hooks. If everything in your charm directory
682+went away, that should be considered a <em>management</em> failure only; the software
683+installed should continue to run, using its last known good configuration, and
684+should do this by virtue of never having had the opportunity to observe the
685+change.</p>
686+
687+<p>Finally, any file written at runtime constrains all future implementations of
688+the charm. When <a href="./authors-charm-upgrades.html">upgrading a charm</a>, any
689+change that would cause runtime state to be overwritten will cause juju to abort
690+the operation and hand over to the user for resolution. This is inconvenient for
691+the users and undermines confidence in the charm.</p>
692+
693+<p class="note"> <strong>Note: </strong> You need to be especially aware of the following
694+when writing python code:
695+Python packages run without bytecode suppression will write <code>.pyc</code> files into
696+the package, and subsequent attempts to move or remove the package will fail:
697+the .pyc files are treated as important hook-relevant runtime state information, to be
698+recorded and tracked, and the loss of their directory will put the unit into
699+an upgrade error state as referenced above.</p>
700+</section>
701+
702+ </article>
703+<!--Postamble-->
704+ </div>
705+ </div>
706+ </section>
707+ </div>
708+</div>
709+<!--End-Postamble-->
710+<!--Footer-->
711+ <footer class="global clearfix" role="contentinfo">
712+ <nav role="navigation">
713+ <div class="footer-a">
714+ <div class="clearfix">
715+ <ul>
716+ <li>
717+ <h2><a href="/">Juju</a></h2>
718+ <ul>
719+ <li><a href="/charms">Charms</a></li>
720+ <li><a href="/features">Features</a></li>
721+ <li><a href="/deployment">Deployment</a></li>
722+ </ul>
723+ </li>
724+ <li>
725+ <h2><a href="/resources">Resources</a></h2>
726+ <ul>
727+ <li><a href="/resources/juju-overview/">Overview</a></li>
728+ <li><a href="/docs/">Documentation</a></li>
729+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
730+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
731+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
732+ <li><a href="/resources/videos/">Videos</a></li>
733+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
734+ </ul>
735+ </li>
736+ <li>
737+ <h2><a href="/community">Community</a></h2>
738+ <ul>
739+ <li><a href="/community/blog/">Juju Blog</a></li>
740+ <li><a href="/events/">Events</a></li>
741+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
742+ <li><a href="/community/charmers/">Charmers</a></li>
743+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
744+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
745+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
746+ </ul>
747+ </li>
748+ <li>
749+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
750+ <ul>
751+ <li><a href="https://jujucharms.com/">Charm store</a></li>
752+ <li><a href="/download/">Download Juju</a></li>
753+ </ul>
754+ </li>
755+ </ul>
756+ </div>
757+ </div>
758+ </nav>
759+ <div class="legal clearfix">
760+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
761+ </div>
762+ </footer>
763+
764+<!--End-Footer-->
765+<!--Scripts-->
766+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
767+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
768+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
769+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
770+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
771+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
772+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
773+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
774+ <!-- google analytics -->
775+ <script>
776+ var _gaq = _gaq || [];
777+ _gaq.push(['_setAccount', 'UA-1018242-41']);
778+ _gaq.push(['_trackPageview']);
779+
780+ (function() {
781+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
782+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
783+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
784+ })();
785+ </script>
786+<!--End-Scripts-->
787+
788+
789+</body></html>
790+
791
792=== added file 'htmldocs/authors-charm-config.html'
793--- htmldocs/authors-charm-config.html 1970-01-01 00:00:00 +0000
794+++ htmldocs/authors-charm-config.html 2013-10-09 20:07:46 +0000
795@@ -0,0 +1,244 @@
796+<!DOCTYPE html>
797+<html>
798+<!--Head-->
799+ <head>
800+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
801+ <title>Juju Documentation</title>
802+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
803+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
804+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
805+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
806+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
807+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
808+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
809+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
810+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
811+ <link href="./css/main.css" rel="stylesheet" type="text/css">
812+
813+ <!--[if lt IE 9]>
814+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
815+ <![endif]-->
816+ </head>
817+<!--End-Head-->
818+
819+
820+ <body class="resources">
821+<!--Header-->
822+
823+ <header class="banner global" role="banner">
824+ <nav role="navigation" class="nav-primary nav-right">
825+ <div class="logo">
826+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
827+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
828+ <span>Juju</span>
829+ </a>
830+ </div>
831+ <ul>
832+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
833+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
834+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
835+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
836+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
837+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
838+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
839+ </ul>
840+ <div id="box-search">
841+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
842+ <label class="off-left" for="s">Search:</label>
843+ <input class="form-text" type="text" value="" name="s" id="s" />
844+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
845+ </form>
846+ </div>
847+ </nav>
848+ </header>
849+<!--End-Header-->
850+<!--Preamble-->
851+<div class="wrapper">
852+ <div id="main-content" class="inner-wrapper" role="main">
853+ <div class="row no-border">
854+ <div class="header-navigation-secondary"></div>
855+ <h2 class="pagetitle">Juju documentation</h2>
856+ </div>
857+ <section id="content" class="container-12">
858+ <div class="grid-12 doc-container">
859+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
860+ <div class="grid-9 doc-content">
861+<!--End-Preamble-->
862+<article>
863+
864+<section id="charm-configuration">
865+<h1>Charm configuration</h1>
866+
867+<p>The optional <code>config.yaml</code> file defines how a service running the
868+charm can be configured by its user.</p>
869+
870+<p>If it exists, it must contain a dictionary of <code>options</code>, in which
871+each possible setting is named by the key and defined by the value. An option
872+definition may contain any number of the following fields:</p>
873+<ul>
874+ <li><code>type</code> can be <code>string</code>, <code>int</code>, <code>float</code>,
875+ or <code>boolean</code>. If not present, it defaults to <code>string</code>.</li>
876+ <li><code>description</code> should contain an explanation of what the user might
877+ achieve by altering the setting.</li>
878+ <li><code>default</code> should, if present, contain a value of the appropriate
879+ type. If not present it is treated as null (which is always a valid value in this
880+ context); an option with no default will not normally be reported by the
881+ config-get <a href="./authors-hook-environment.html">hook tool</a> unless it
882+ has been explicitly set.</li>
883+</ul>
884+</section>
885+
886+<section id="picking-options">
887+<h2>What to expose to users</h2>
888+
889+<p>The charm configuration is deliberately somewhat restrictive, in the hope of
890+encouraging charmers to expose only features that are clear and comprehensible.
891+The user doesn't want to configure the software - they want to configure the
892+<em>service</em>, which exists at a higher level of abstraction. A charm with
893+a single opinionated <code>tuning</code> option is, from this perspective,
894+infinitely superior to one that exposes 6 arcane options that correspond
895+directly to flags or config settings for the software.</p>
896+
897+<p>In short, the config is part of the user interface for the charm - it needs to be concise and
898+as easy to understand and use as possible. If you're considering using base64
899+encoding to slip structured data through the deliberately restrictive configuration
900+language, you're probably "Doing It Wrong".</p>
901+</section>
902+
903+<section id="default-options">
904+<h2>Default configuration</h2>
905+
906+<p>Your charm should operate correctly with no explicit configuration settings.
907+The first time someone uses your charm, they're likely to run <code>juju deploy yourcharm</code>
908+and see what happens; if it doesn't work out of the box ont the first go,
909+many potential users won't give it a second try.</p>
910+</section>
911+
912+
913+<h2>Warning</h2>
914+
915+<p class="Warning"><strong>Warning: </strong> There's a <a href="https://bugs.launchpad.net/juju-core/+bug/1194945">bug</a>
916+in the service configuration CLI at the moment; if a string-typed option has an
917+explicit default that is <em>not</em> the empty string, it will become
918+impossible to set the value to the empty string at runtime. If your option
919+needs to accept an empty string value, it should make the empty string the
920+explicit default value.</p>
921+</section>
922+
923+<section id="examples">
924+<h2>Sample config.yaml files</h2>
925+
926+<p> The MediaWiki has some simple but useful configuration options:</p>
927+<pre class="prettyprint">
928+ options:
929+ name:
930+ default: Please set name of wiki
931+ description: The name, or Title of the Wiki
932+ type: string
933+ skin:
934+ default: vector
935+ description: skin for the Wiki
936+ type: string
937+ logo:
938+ description: URL to fetch logo from
939+ type: string
940+ admins:
941+ description: Admin users to create, user:pass
942+ type: string
943+ debug:
944+ default: false
945+ type: boolean
946+ description: turn on debugging features of mediawiki
947+</pre>
948+
949+</section>
950+
951+ </article>
952+</article>
953+<!--Postamble-->
954+ </div>
955+ </div>
956+ </section>
957+ </div>
958+</div>
959+<!--End-Postamble-->
960+<!--Footer-->
961+ <footer class="global clearfix" role="contentinfo">
962+ <nav role="navigation">
963+ <div class="footer-a">
964+ <div class="clearfix">
965+ <ul>
966+ <li>
967+ <h2><a href="/">Juju</a></h2>
968+ <ul>
969+ <li><a href="/charms">Charms</a></li>
970+ <li><a href="/features">Features</a></li>
971+ <li><a href="/deployment">Deployment</a></li>
972+ </ul>
973+ </li>
974+ <li>
975+ <h2><a href="/resources">Resources</a></h2>
976+ <ul>
977+ <li><a href="/resources/juju-overview/">Overview</a></li>
978+ <li><a href="/docs/">Documentation</a></li>
979+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
980+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
981+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
982+ <li><a href="/resources/videos/">Videos</a></li>
983+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
984+ </ul>
985+ </li>
986+ <li>
987+ <h2><a href="/community">Community</a></h2>
988+ <ul>
989+ <li><a href="/community/blog/">Juju Blog</a></li>
990+ <li><a href="/events/">Events</a></li>
991+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
992+ <li><a href="/community/charmers/">Charmers</a></li>
993+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
994+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
995+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
996+ </ul>
997+ </li>
998+ <li>
999+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
1000+ <ul>
1001+ <li><a href="https://jujucharms.com/">Charm store</a></li>
1002+ <li><a href="/download/">Download Juju</a></li>
1003+ </ul>
1004+ </li>
1005+ </ul>
1006+ </div>
1007+ </div>
1008+ </nav>
1009+ <div class="legal clearfix">
1010+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
1011+ </div>
1012+ </footer>
1013+
1014+<!--End-Footer-->
1015+<!--Scripts-->
1016+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
1017+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
1018+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
1019+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
1020+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
1021+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
1022+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
1023+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
1024+ <!-- google analytics -->
1025+ <script>
1026+ var _gaq = _gaq || [];
1027+ _gaq.push(['_setAccount', 'UA-1018242-41']);
1028+ _gaq.push(['_trackPageview']);
1029+
1030+ (function() {
1031+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
1032+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
1033+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
1034+ })();
1035+ </script>
1036+<!--End-Scripts-->
1037+
1038+
1039+</body></html>
1040
1041=== added file 'htmldocs/authors-charm-hooks.html'
1042--- htmldocs/authors-charm-hooks.html 1970-01-01 00:00:00 +0000
1043+++ htmldocs/authors-charm-hooks.html 2013-10-09 20:07:46 +0000
1044@@ -0,0 +1,387 @@
1045+<!DOCTYPE html>
1046+<html>
1047+<!--Head-->
1048+ <head>
1049+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1050+ <title>Juju Documentation</title>
1051+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
1052+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
1053+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
1054+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
1055+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
1056+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
1057+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
1058+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
1059+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
1060+ <link href="./css/main.css" rel="stylesheet" type="text/css">
1061+
1062+ <!--[if lt IE 9]>
1063+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
1064+ <![endif]-->
1065+ </head>
1066+<!--End-Head-->
1067+
1068+
1069+ <body class="resources">
1070+<!--Header-->
1071+
1072+ <header class="banner global" role="banner">
1073+ <nav role="navigation" class="nav-primary nav-right">
1074+ <div class="logo">
1075+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
1076+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
1077+ <span>Juju</span>
1078+ </a>
1079+ </div>
1080+ <ul>
1081+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
1082+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
1083+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
1084+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
1085+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
1086+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
1087+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
1088+ </ul>
1089+ <div id="box-search">
1090+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
1091+ <label class="off-left" for="s">Search:</label>
1092+ <input class="form-text" type="text" value="" name="s" id="s" />
1093+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
1094+ </form>
1095+ </div>
1096+ </nav>
1097+ </header>
1098+<!--End-Header-->
1099+<!--Preamble-->
1100+<div class="wrapper">
1101+ <div id="main-content" class="inner-wrapper" role="main">
1102+ <div class="row no-border">
1103+ <div class="header-navigation-secondary"></div>
1104+ <h2 class="pagetitle">Juju documentation</h2>
1105+ </div>
1106+ <section id="content" class="container-12">
1107+ <div class="grid-12 doc-container">
1108+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
1109+ <div class="grid-9 doc-content">
1110+<!--End-Preamble-->
1111+<article>
1112+<section id="charm-hooks">
1113+<h1>Charm hooks</h1>
1114+
1115+<p>A service unit's direct action is entirely defined by its charm's hooks. Hooks
1116+are executable files in a charm's <code>hooks</code> directory; hooks with particular
1117+names (see below) will be invoked by the juju unit agent at particular times, and thereby cause
1118+changes to the world.</p>
1119+
1120+<p>Whenever a hook-worthy event takes place, the unit agent first checks whether
1121+that hook is being <a href="./authors-hook-debug.html">debugged</a>, and if so
1122+hands over control to the user. Otherwise, it tries to find a hook with precisely
1123+the right name. If the hook doesn't exist, the agent continues without complaint;
1124+if it does, it is invoked without arguments in a specific
1125+<a href="./authors-hook-environment.html">environment</a>, and its output is written
1126+to the unit agent's log. If it returns a non-zero exit code, the agent enters an
1127+<a href="./authors-hook-errors.html">error state</a> and awaits user intervention.</p>
1128+
1129+<p>The agent will also enter an error state if the unit agent process is aborted
1130+during hook execution.</p>
1131+
1132+<p>There are two types of hooks, described in more detail in the following sections.</p>
1133+
1134+<p class = "note"><strong>Note: </strong>None of the unit or relation hooks are required; if you don't implement a hook,
1135+it just doesn't get run. When a hook event occurs, Juju will look for the corresponding hook file to execute, but if it finds none, will continue running without generating an error.</p>
1136+</section>
1137+
1138+<section id="unit-hooks">
1139+<h2>Unit hooks</h2>
1140+
1141+<p>There are 5 &quot;unit hooks&quot; with predefined names that can be implemented
1142+by any charm:</p>
1143+<ul>
1144+ <li>install</li>
1145+ <li>config-changed</li>
1146+ <li>start</li>
1147+ <li>upgrade-charm</li>
1148+ <li>stop</li>
1149+</ul>
1150+
1151+<p>For every relation defined by a charm, an additional 4 &quot;relation hooks&quot;
1152+can be implemented, named after the charm relation:</p>
1153+<ul>
1154+ <li>&lt;name&gt;-relation-joined</li>
1155+ <li>&lt;name&gt;-relation-changed</li>
1156+ <li>&lt;name&gt;-relation-departed</li>
1157+ <li>&lt;name&gt;-relation-broken</li>
1158+</ul>
1159+
1160+<h3 id="hook-install">install</h3>
1161+
1162+<p><code>install</code> runs just once, before any other hook. It should be used to
1163+perform one-time setup operations only.</p>
1164+
1165+<h3 id="hook-config-changed">config-changed</h3>
1166+
1167+<p><code>config-changed</code> runs in several different situations.</p>
1168+<ul>
1169+ <li>immediately after "install"</li>
1170+ <li>immediately after "upgrade-charm"</li>
1171+ <li>at least once when the unit agent is restarted (but, if the unit is in
1172+ an <a href="./authors-hook-errors.html">error state</a>, it won't be run
1173+ until after the error state is cleared).</li>
1174+</ul>
1175+<p>It cannot assume that the software has already been started; it should not
1176+start stopped software, but should (if appropriate) restart running software
1177+to take configuration changes into account.</p>
1178+
1179+<h3 id="hook-start">start</h3>
1180+<p><code>start</code> runs immediately after the first <code>config-changed</code>
1181+hook. It should be used to ensure the charm's software is running. Note that the
1182+charm's software should be configured so as to persist through reboots without further
1183+intervention on juju's part.
1184+
1185+<h3 id="hook-upgrade-charm">upgrade-charm</h3>
1186+
1187+<p><code>upgrade-charm</code> runs immediately after any
1188+<a href="./authors-charm-upgrades.html">upgrade</a> operation that does <em>not</em>
1189+itself interrupt an existing <a href="./authors-hook-errors.html">error state.</a>. It
1190+should be used to reconcile local state written by some other version of the charm into
1191+whatever form it needs to take to be manipulated by the current version.</p>
1192+
1193+<p>While the forced upgrade functionality is intended as a developer tool, and is
1194+not generally suitable for end users, it's somewhat optimistic to depend on the
1195+functionality never being abused. In light of this, if you need to run an
1196+<code>upgrade-charm</code> hook before your other hooks will work correctly,
1197+it may be wise to preface all your other hooks with a quick call to your
1198+(idempotent)<code>upgrade-charm</code>.</p>
1199+
1200+<h3 id="hook-stop">stop</h3>
1201+
1202+<p><code>stop</code> runs immediately before the end of the unit's destruction
1203+sequence. It should be used to ensure that the charm's software is not running, and
1204+will not start again on reboot.</p>
1205+</section>
1206+
1207+<section id="relation-hooks">
1208+<h2>Relation hooks</h2>
1209+
1210+<p>Units will only participate in relations after they're been started, and before
1211+they've been stopped. Within that time window, the unit may participate in several
1212+different relations at a time, <em>including</em> multiple relations with the
1213+same name.</p>
1214+
1215+<p>To illustrate, consider a database service that will be used by multiple client
1216+services. Units of a single client service will surely want to connect to, and
1217+use, the same database; but if units of another client service were to use that
1218+same database, the consequences could be catastrophic for all concerned.</p>
1219+
1220+<p>If juju respected the <code>limit</code> field in relation
1221+<a href="./authors-charm-metadata.html">metadata</a>, it would be possible
1222+to work around this, but it's not a high-priority
1223+<a href="https://bugs.launchpad.net/bugs/1089297">bug</a>: most provider services
1224+<em>should</em> be able to handle multiple requirers anyway; and most requirers will
1225+only be connected to one provider anyway.</p>
1226+
1227+<p>When a unit running a given charm participates in a given relation, it runs at
1228+least three hooks for every remote unit it becomes aware of in that relation.</p>
1229+</section>
1230+
1231+<section id="hook-relation-joined">
1232+<h3>&lt;name&gt;-relation-joined</h3>
1233+
1234+<p><code>&lt;name&gt;-relation-joined</code> is run once only, when that remote
1235+unit is first observed by the unit. It should be used to <code>relation-set</code> any
1236+local unit settings that can be determined using no more than the name of the joining
1237+unit and the remote <code>private-address</code> setting, which is always available
1238+when the relation is created and is by convention not deleted.</p>
1239+
1240+<p>You should not depend upon any other relation settings in the -joined hook
1241+because they're not guaranteed to be present; if you need more information
1242+you should wait for a -changed hook that presents the right information.</p>
1243+</section>
1244+
1245+<section id="hook-relation-changed">
1246+<h3>&lt;name&gt;-relation-changed</h3>
1247+
1248+<p><code>&lt;name&gt;-relation-changed</code> is always run once, after -joined, and
1249+will subsequently be run whenever that remote unit changes its settings for the
1250+relation. It should be the <em>only</em> hook that <em>relies</em> upon remote relation
1251+settings from <code>relation-get</code>, and it should <em>not</em> error if the
1252+settings are incomplete: you can guarantee that when the remote unit changes its
1253+settings, the hook will be run again.</p>
1254+
1255+<p>The settings that you can get, and that you should set, are determined by
1256+the relation's <a href="./authors-charm-interfaces.html">interface</a>.</p>
1257+</section>
1258+
1259+<section id="hook-relation-departed">
1260+<h3>&lt;name&gt;-relation-departed</h3>
1261+
1262+<p><code>&lt;name&gt;-relation-departed</code> is run once only, when the remote unit
1263+is known to be leaving the relation; it will only run once at least one -changed has
1264+been run, and after -departed has run, no further -changeds will be run. This should
1265+be used to remove all references to the remote unit, because there's no guarantee that
1266+it's still part of the system; it's perfectly probable (although not guaranteed) that
1267+the system running that unit has already shut down.</p>
1268+
1269+<p>When a unit's own participation in a relation is known to be ending, the unit
1270+agent continues to uphold the ordering guarantees above; but within those
1271+constraints, it will run the fewest possible hooks to notify the charm of the
1272+departure of each individual remote unit.</p>
1273+
1274+<p>Once all necessary -departed hooks have been run for such a relation, the unit
1275+agent will run the final relation hook:</p>
1276+</section>
1277+
1278+<section id="hook-relation-broken">
1279+<h3>&lt;name&gt;-relation-broken</h3>
1280+
1281+<p><code>&lt;name&gt;-relation-broken</code> indicates that the current relation is
1282+no longer valid, and that the charm's software must be configured as though the
1283+relation had never existed. It will only be called after every necessary -departed
1284+hook has been run; if it's being executed, you can be sure that no remote units are
1285+currently known locally.</p>
1286+
1287+<p>It is important to note that the -broken hook might run even if no other units
1288+have ever joined the relation. This is not a bug: even if no remote units have ever
1289+joined, the fact of the unit's participation can be detected in other hooks via the
1290+<code>relation-ids</code> tool, and the -broken hook needs to execute to give the
1291+charm an opportunity to clean up any optimistically-generated configuration.</p>
1292+
1293+<p>And, again, it's important to internalise the fact that there may be multiple
1294+runtime relations in play with the same name, and that they're independent:
1295+one -broken hook does not mean that <em>every</em> such relation is broken.</p>
1296+</section>
1297+
1298+<section id="writing-hooks">
1299+<h2>Writing hooks</h2>
1300+
1301+<p>If you follow the <a href="./authors-charm-writing.html">tutorial</a>, you'll
1302+get a good sense of the basics. To fill out your knowledge, you'll want to study
1303+the hook <a href="./authors-hook-environment.html">environment and tools</a>, and
1304+to experiment with <a href="./authors-hook-debug.html">debug-hooks</a>.</p>
1305+
1306+<p>Independent of the nuts and bolts, though, good hooks display a number of
1307+useful high-level properties:</p>
1308+<ul>
1309+ <li>They are <em>idempotent</em>: that is to say that there should be no
1310+ observable difference between running a hook once, and running it N times
1311+ in a row. If this property does not hold, you are likely to be making your
1312+ own life unnecesarily difficult: apart from anything else, the average user's
1313+ most likely first response to a failed hook will be to try to run it again
1314+ (if they don't just skip it).</li>
1315+
1316+ <li>They are <em>easy to read</em> and understand. It's tempting to write a
1317+ single file that does everything, and which just calls different functions
1318+ internally depending on the value of <code>argv[0]</code>, and to symlink that
1319+ one file for every hook; but such structures quickly become unwieldy.<br />
1320+ The time taken to write a library, separate from the hooks, is very likely
1321+ to be well spent: it lets you write single hooks that are clear and focused,
1322+ and insulates the maintainer from irrelevant details.</li>
1323+
1324+ <li>Where possible, they reuse
1325+ <a href="https://launchpad.net/charm-tools">common code</a> already written to
1326+ ease or solve common use cases.</li>
1327+
1328+ <li>They do not return <a href="./authors-hook-errors.html">errors</a> unless
1329+ there is a good reason to believe that they cannot be resolved without user
1330+ intervention. Doing so is an admission of defeat: a user who sees your charm
1331+ returning an error state is unlikely to have the specific expertise necessary
1332+ to resolve it. If you have to return an error, please be sure to at least write
1333+ any context you can to the log before you do so.</li>
1334+
1335+ <li>They write only <em>very</em> sparingly to the
1336+ <a href="./authors-charm-contents.html">charm directory</a>.</li>
1337+</ul>
1338+
1339+<p>We recommend you also familiarize yourself with the
1340+<a href="./authors-charm-best-practice.html">best practices</a> and, if you
1341+plan to distribute your charm, the
1342+<a href="./authors-charm-policy.html">charm store policy</a>.</p>
1343+</section>
1344+ </article>
1345+<!--Postamble-->
1346+ </div>
1347+ </div>
1348+ </section>
1349+ </div>
1350+</div>
1351+<!--End-Postamble-->
1352+<!--Footer-->
1353+ <footer class="global clearfix" role="contentinfo">
1354+ <nav role="navigation">
1355+ <div class="footer-a">
1356+ <div class="clearfix">
1357+ <ul>
1358+ <li>
1359+ <h2><a href="/">Juju</a></h2>
1360+ <ul>
1361+ <li><a href="/charms">Charms</a></li>
1362+ <li><a href="/features">Features</a></li>
1363+ <li><a href="/deployment">Deployment</a></li>
1364+ </ul>
1365+ </li>
1366+ <li>
1367+ <h2><a href="/resources">Resources</a></h2>
1368+ <ul>
1369+ <li><a href="/resources/juju-overview/">Overview</a></li>
1370+ <li><a href="/docs/">Documentation</a></li>
1371+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
1372+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
1373+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
1374+ <li><a href="/resources/videos/">Videos</a></li>
1375+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
1376+ </ul>
1377+ </li>
1378+ <li>
1379+ <h2><a href="/community">Community</a></h2>
1380+ <ul>
1381+ <li><a href="/community/blog/">Juju Blog</a></li>
1382+ <li><a href="/events/">Events</a></li>
1383+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
1384+ <li><a href="/community/charmers/">Charmers</a></li>
1385+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
1386+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
1387+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
1388+ </ul>
1389+ </li>
1390+ <li>
1391+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
1392+ <ul>
1393+ <li><a href="https://jujucharms.com/">Charm store</a></li>
1394+ <li><a href="/download/">Download Juju</a></li>
1395+ </ul>
1396+ </li>
1397+ </ul>
1398+ </div>
1399+ </div>
1400+ </nav>
1401+ <div class="legal clearfix">
1402+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
1403+ </div>
1404+ </footer>
1405+
1406+<!--End-Footer-->
1407+<!--Scripts-->
1408+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
1409+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
1410+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
1411+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
1412+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
1413+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
1414+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
1415+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
1416+ <!-- google analytics -->
1417+ <script>
1418+ var _gaq = _gaq || [];
1419+ _gaq.push(['_setAccount', 'UA-1018242-41']);
1420+ _gaq.push(['_trackPageview']);
1421+
1422+ (function() {
1423+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
1424+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
1425+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
1426+ })();
1427+ </script>
1428+<!--End-Scripts-->
1429+
1430+
1431+</body></html>
1432
1433=== modified file 'htmldocs/authors-charm-icon.html'
1434--- htmldocs/authors-charm-icon.html 2013-09-27 14:53:30 +0000
1435+++ htmldocs/authors-charm-icon.html 2013-10-09 20:07:46 +0000
1436@@ -23,6 +23,8 @@
1437
1438
1439
1440+
1441+
1442 <body class="resources">
1443
1444 <!--Header-->
1445@@ -242,4 +244,6 @@
1446 <!--End-Scripts-->
1447
1448
1449+
1450+
1451 </body></html>
1452
1453=== added file 'htmldocs/authors-charm-interfaces.html'
1454--- htmldocs/authors-charm-interfaces.html 1970-01-01 00:00:00 +0000
1455+++ htmldocs/authors-charm-interfaces.html 2013-10-09 20:07:46 +0000
1456@@ -0,0 +1,340 @@
1457+<!DOCTYPE html>
1458+<html>
1459+<!--Head-->
1460+ <head>
1461+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1462+ <title>Juju Documentation</title>
1463+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
1464+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
1465+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
1466+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
1467+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
1468+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
1469+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
1470+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
1471+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
1472+ <link href="./css/main.css" rel="stylesheet" type="text/css">
1473+
1474+ <!--[if lt IE 9]>
1475+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
1476+ <![endif]-->
1477+ </head>
1478+<!--End-Head-->
1479+
1480+ <body class="resources">
1481+<!--Header-->
1482+
1483+ <header class="banner global" role="banner">
1484+ <nav role="navigation" class="nav-primary nav-right">
1485+ <div class="logo">
1486+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
1487+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
1488+ <span>Juju</span>
1489+ </a>
1490+ </div>
1491+ <ul>
1492+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
1493+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
1494+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
1495+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
1496+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
1497+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
1498+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
1499+ </ul>
1500+ <div id="box-search">
1501+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
1502+ <label class="off-left" for="s">Search:</label>
1503+ <input class="form-text" type="text" value="" name="s" id="s" />
1504+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
1505+ </form>
1506+ </div>
1507+ </nav>
1508+ </header>
1509+<!--End-Header-->
1510+<!--Preamble-->
1511+<div class="wrapper">
1512+ <div id="main-content" class="inner-wrapper" role="main">
1513+ <div class="row no-border">
1514+ <div class="header-navigation-secondary"></div>
1515+ <h2 class="pagetitle">Juju documentation</h2>
1516+ </div>
1517+ <section id="content" class="container-12">
1518+ <div class="grid-12 doc-container">
1519+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
1520+ <div class="grid-9 doc-content">
1521+<!--End-Preamble-->
1522+<article>
1523+<section id="relation-interfaces">
1524+<h1>Charm relation interfaces</h1>
1525+
1526+<p>As described <a href="./authors-charm-metadata.html">elsewhere</a>, picking an
1527+interface is a strong statement; whether you're providing or requiring a given
1528+interface, you need to be compatible with all providers and requirers of that
1529+interface.</p>
1530+
1531+<p>In short, this means that you need to set the same settings as do all the
1532+other charms with the same role for the interface; and you should only expect
1533+to be able to read those settings set by the other charms with the counterpart
1534+role.</p>
1535+</section>
1536+
1537+<section id="determining-interfaces">
1538+<h2>Determining charm relation interfaces</h2>
1539+
1540+<p>This is in some respects an uncomfortable situation to be in. If two charms
1541+declare compatibility, but fail when run together due to disagreement about
1542+the actual definition of that interface; it's not immediately clear which is
1543+at fault, because the &quot;standard&quot; is defined only by consensus among the
1544+existing charms that provide or require that interface.</p>
1545+
1546+<p>On the upside, this means that reading any charm that already implements the
1547+interface is <em>theoretically</em> good enough to figure it out; in practice, it's
1548+sometimes hard to understand the code in isolation. The incontrovertible way
1549+to determine the protocol defined by an interface is to deploy a pair of charms
1550+that already use that interface, and <a href="./authors-hook-debug.html">intercept</a>
1551+the communications between them.</p>
1552+
1553+<pre class="prettyprint">
1554+juju deploy mongodb
1555+juju deploy node-app
1556+</pre>
1557+
1558+<p>In a separate window, once node-app/0 reports <code>started</code> status:</p>
1559+
1560+<pre class="prettyprint">
1561+juju debug-hooks node-app/0 *
1562+</pre>
1563+
1564+<p>This opens a tmux session; when the unit wants to run a hook, it'll create a
1565+new window in which you can interactively inspect the environment. In a relation
1566+hook, you'll want to run the following commands:</p>
1567+
1568+<pre class="prettyprint">
1569+# discover what's been set by the unit on the other end of the relation:
1570+$ relation-get $JUJU_REMOTE_UNIT
1571+
1572+address: example.com:37070
1573+username: bob
1574+password: seekrit
1575+
1576+# get the local unit's relation settings, for comparison afterwards:
1577+$ relation-get $JUJU_UNIT_NAME
1578+# (no results)
1579+
1580+# run the actual hook:
1581+$ ./hooks/$JUJU_HOOK_NAME
1582+
1583+# get the local settings again, to see if any changes were made by the hook:
1584+$ relation-get $JUJU_UNIT_NAME
1585+# (no results)
1586+</pre>
1587+
1588+<p>...and then close that tmux window and wait to see if another one opens for the
1589+next hook. Assuming you started debugging before creating the relation, you'll
1590+see exactly one -joined hook, and at least one -changed hook, and you're only
1591+done when new -changed hooks stop popping up.</p>
1592+
1593+<p>The relation-get <a href="./authors-hook-environment.html">tool</a> accepts a
1594+<code>--format</code> parameter that accepts <code>json</code> and <code>yaml</code>
1595+values, in case you want to consume them programmatically.</p>
1596+
1597+<p>In practice, what you'll most likely find is that one side sets a couple of keys,
1598+the other side gets them, and that's that... in no more than two changed hooks.
1599+Be aware, though, that it is possible in principle for an interface to imply
1600+a more demanding interface, involving multiple rounds of setting and getting.</p>
1601+</section>
1602+
1603+<section id="documenting-interfaces">
1604+<h2>Documenting charm relation interfaces</h2>
1605+
1606+<p>In light of the above, there is a clear need for some means of documenting the
1607+above. The optional <code>gets</code> and <code>sets</code> fields in a charm's
1608+relation <a href="./authors-charm-metadata.html">metadata</a> should be used for
1609+this purpose.</p>
1610+
1611+<p>Please be especially careful to note that this format is <em>not</em> checked
1612+by juju today. But it does encode the information that's most helpful to your fellow
1613+charmers, and by doing so in a consistent and machine-readable format we maximise
1614+our chances of one day making use of this information automatically.</p>
1615+
1616+<p>The simple form, which will be the most common form, looks like this:</p>
1617+
1618+<pre class="prettyprint">
1619+name: python-django
1620+...
1621+provides:
1622+ website:
1623+ interface: http
1624+ sets: [host, post]
1625+</pre>
1626+
1627+<p>...and this:</p>
1628+
1629+<pre class="prettyprint">
1630+name: haproxy
1631+...
1632+requires:
1633+ reverseproxy:
1634+ interface: http
1635+ gets: [host, port]
1636+</pre>
1637+
1638+<p>...indicating that a relation can surely be made between python-django and haproxy,
1639+because the <code>website</code> relation unconditionally sets the keys that the
1640+<code>reverseproxy</code> relation requires in order to function.</p>
1641+
1642+<p>The more complex form, which is only required for complex protocols, is defined
1643+as follows:</p>
1644+<ul>
1645+ <li><code>gets</code> holds a list of settings keys that must all be set by
1646+ each unit on the remote end of a relation in order for the local unit to
1647+ function.</li>
1648+ <li><code>sets</code> holds a list of settings that will be set by each unit
1649+ of the local charm. These settings can either be a plain string, indicating that
1650+ no remote settings need exist for this key to be written; or a single-element
1651+ map, with the setting to be written mapped to the remote settings that must
1652+ exist for this to be done.</li>
1653+</ul>
1654+<p>For example, consider charms <code>a</code> and <code>b</code>, which do the
1655+following handshake dance before they can complete their configuration:</p>
1656+<ul>
1657+ <li><code>b/0</code> starts running -joined, which takes a while.</li>
1658+ <li><code>a/0</code> runs -joined and -changed before <code>b/0</code> has
1659+ finished -joined. In the -changed hook, it fails to find the remote settings
1660+ it expected, and exits without error.</li>
1661+ <li><code>b/0</code> finishes -joined, setting <code>X</code> and <code>Y</code>,
1662+ thus triggering -changed on <code>a/0</code>.</li>
1663+ <li><code>a/0</code> sets <code>P</code> and <code>Q</code> in response, causing
1664+ a -changed on <code>b/0</code>.</li>
1665+ <li><code>b/0</code> completes local configuration using <code>P</code> and
1666+ <code>Q</code>, and sets <code>Z</code>, triggering a final -changed on
1667+ <code>a/0</code>.</li>
1668+ <li><code>a/0</code> completes local configuration using <code>X</code>,
1669+ <code>Y</code>, and <code>Z</code>, and sets nothing.</li>
1670+</ul>
1671+<p>For example, in the hypothetical complex protocol described in the previous
1672+section, the metadata for charm <code>a</code> above would contain:</p>
1673+
1674+<pre class="prettyprint">
1675+requires:
1676+ ab:
1677+ interface: ab
1678+ sets:
1679+ - P: [X, Y]
1680+ - Q: [X, Y]
1681+ gets: [X, Y, Z]
1682+</pre>
1683+
1684+<p>...indicating that <code>P</code> and <code>Q</code> will only be written when
1685+<code>X</code> and <code>Y</code> have; and that configuration will not complete
1686+without <code>X</code>, <code>Y</code> and <code>Z</code>. Meanwhile charm
1687+<code>b</code> would contain:</p>
1688+
1689+<pre class="prettyprint">
1690+provides:
1691+ ab:
1692+ interface: ab
1693+ sets:
1694+ - X
1695+ - Y
1696+ - Z: [P, Q]
1697+ gets: [P, Q]
1698+</pre>
1699+
1700+<p>...indicating that it will always write <code>X</code> and <code>Y</code>, and
1701+that <code>Z</code> will be written when <code>P</code> and <code>Q</code> have; and
1702+that configuration will not be complete without <code>P</code> and <code>Q</code>.</p>
1703+
1704+<p>Peer relations are a different matter, in that peer relations are the mechanism
1705+by which service units share information internally. It's not unusual for peer
1706+service units to maintain convenient caches of distributed information in their
1707+own peer settings, and this inevitably involves generating settings keys at
1708+runtime.</p>
1709+</section>
1710+</article>
1711+<!--Postamble-->
1712+ </div>
1713+ </div>
1714+ </section>
1715+ </div>
1716+</div>
1717+<!--End-Postamble-->
1718+<!--Footer-->
1719+ <footer class="global clearfix" role="contentinfo">
1720+ <nav role="navigation">
1721+ <div class="footer-a">
1722+ <div class="clearfix">
1723+ <ul>
1724+ <li>
1725+ <h2><a href="/">Juju</a></h2>
1726+ <ul>
1727+ <li><a href="/charms">Charms</a></li>
1728+ <li><a href="/features">Features</a></li>
1729+ <li><a href="/deployment">Deployment</a></li>
1730+ </ul>
1731+ </li>
1732+ <li>
1733+ <h2><a href="/resources">Resources</a></h2>
1734+ <ul>
1735+ <li><a href="/resources/juju-overview/">Overview</a></li>
1736+ <li><a href="/docs/">Documentation</a></li>
1737+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
1738+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
1739+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
1740+ <li><a href="/resources/videos/">Videos</a></li>
1741+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
1742+ </ul>
1743+ </li>
1744+ <li>
1745+ <h2><a href="/community">Community</a></h2>
1746+ <ul>
1747+ <li><a href="/community/blog/">Juju Blog</a></li>
1748+ <li><a href="/events/">Events</a></li>
1749+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
1750+ <li><a href="/community/charmers/">Charmers</a></li>
1751+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
1752+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
1753+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
1754+ </ul>
1755+ </li>
1756+ <li>
1757+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
1758+ <ul>
1759+ <li><a href="https://jujucharms.com/">Charm store</a></li>
1760+ <li><a href="/download/">Download Juju</a></li>
1761+ </ul>
1762+ </li>
1763+ </ul>
1764+ </div>
1765+ </div>
1766+ </nav>
1767+ <div class="legal clearfix">
1768+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
1769+ </div>
1770+ </footer>
1771+
1772+<!--End-Footer-->
1773+<!--Scripts-->
1774+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
1775+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
1776+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
1777+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
1778+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
1779+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
1780+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
1781+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
1782+ <!-- google analytics -->
1783+ <script>
1784+ var _gaq = _gaq || [];
1785+ _gaq.push(['_setAccount', 'UA-1018242-41']);
1786+ _gaq.push(['_trackPageview']);
1787+
1788+ (function() {
1789+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
1790+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
1791+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
1792+ })();
1793+ </script>
1794+<!--End-Scripts-->
1795+
1796+</body></html>
1797
1798=== added file 'htmldocs/authors-charm-metadata.html'
1799--- htmldocs/authors-charm-metadata.html 1970-01-01 00:00:00 +0000
1800+++ htmldocs/authors-charm-metadata.html 2013-10-09 20:07:46 +0000
1801@@ -0,0 +1,376 @@
1802+<!DOCTYPE html>
1803+<html>
1804+<!--Head-->
1805+ <head>
1806+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1807+ <title>Juju Documentation</title>
1808+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
1809+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
1810+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
1811+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
1812+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
1813+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
1814+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
1815+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
1816+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
1817+ <link href="./css/main.css" rel="stylesheet" type="text/css">
1818+
1819+ <!--[if lt IE 9]>
1820+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
1821+ <![endif]-->
1822+ </head>
1823+<!--End-Head-->
1824+
1825+
1826+ <body class="resources">
1827+<!--Header-->
1828+
1829+ <header class="banner global" role="banner">
1830+ <nav role="navigation" class="nav-primary nav-right">
1831+ <div class="logo">
1832+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
1833+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
1834+ <span>Juju</span>
1835+ </a>
1836+ </div>
1837+ <ul>
1838+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
1839+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
1840+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
1841+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
1842+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
1843+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
1844+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
1845+ </ul>
1846+ <div id="box-search">
1847+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
1848+ <label class="off-left" for="s">Search:</label>
1849+ <input class="form-text" type="text" value="" name="s" id="s" />
1850+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
1851+ </form>
1852+ </div>
1853+ </nav>
1854+ </header>
1855+<!--End-Header-->
1856+<!--Preamble-->
1857+<div class="wrapper">
1858+ <div id="main-content" class="inner-wrapper" role="main">
1859+ <div class="row no-border">
1860+ <div class="header-navigation-secondary"></div>
1861+ <h2 class="pagetitle">Juju documentation</h2>
1862+ </div>
1863+ <section id="content" class="container-12">
1864+ <div class="grid-12 doc-container">
1865+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
1866+ <div class="grid-9 doc-content">
1867+<!--End-Preamble-->
1868+<article>
1869+
1870+<section id="charm-metadata">
1871+<h1>Charm metadata</h1>
1872+
1873+<p>The only file that must be present in a charm is <code>metadata.yaml</code>, in
1874+the root directory. A metadata file must be a valid yaml dictionary, containing at
1875+least the following fields:</p>
1876+<ul>
1877+ <li><code>name</code> is the charm name, which is used to form the charm URL.
1878+ It must contain only <code>a-z</code>, <code>0-9</code>, and <code>-</code>;
1879+ must start with <code>a-z</code>; must not end with a <code>-</code>; and may
1880+ only end with digits if the digits are <em>not</em> directly preceded by a
1881+ space. Stick with names like <code>foo</code> and <code>foo-bar-baz</code>
1882+ and you needn't pay further attention to the restrictions.</li>
1883+ <li><code>summary</code> is a one-line description of the charm.</li>
1884+ <li><code>description</code> is a long-form description of the charm and its
1885+ features. It will also appear in the juju GUI.</li>
1886+</ul>
1887+
1888+<p>Here's a valid metadata file:</p>
1889+<pre class="prettyprint lang-yaml">
1890+name: minecraft
1891+summary: Minecraft Server
1892+description: |
1893+ Will deploy OpenJDK 6 JRE and the latest Minecraft server
1894+</pre>
1895+
1896+<p>With only those fields, a metadata file is valid, but not very useful. Charms
1897+for use in the Charm Store should always set the following fields as well,
1898+for categorization and display in the GUI:</p>
1899+<ul>
1900+ <li><code>maintainer</code> is the name and email address for the main point
1901+ of contact for the development and maintenance of the charm. Or, at least, it
1902+ should be: in frequent practice, it's just a name. Please update your charms
1903+ as you get the opportunity.</li>
1904+ <li><code>categories</code> is a list containing one or more of the following:
1905+ <ul>
1906+ <li>applications</li>
1907+ <li>app-servers</li>
1908+ <li>cache-proxy</li>
1909+ <li>databases</li>
1910+ <li>file-servers</li>
1911+ <li>mis</li>
1912+ </ul>
1913+ <p>In almost all cases, only one category will be appropriate. The categories help keep the Charm Store organised.</p></li>
1914+</ul>
1915+
1916+<p>Finally, a metadata file defines the charm's relations, and whether it's
1917+designed for deployment as a <a href="./authors-subordinate-services.html">subordinate service</a>.</p>
1918+<ul>
1919+ <li><code>subordinate</code> should be set to true if the charm is a
1920+ subordinate. If omitted, the charm will be presumed not to be subordinate.</li>
1921+ <li><code>provides</code>, <code>requires</code>, and <code>peers</code> define
1922+ the various relations the charm will participate in.</li>
1923+ <li>if the charm is subordinate, it must contain at least one <code>requires</code>
1924+ relation with container scope.</li>
1925+</ul>
1926+
1927+<p>Other field names should be considered to be reserved; please don't use any
1928+not listed above to avoid issues with future versions of Juju.</p>
1929+</section>
1930+
1931+<section id="simple-relations">
1932+<h2>Simple relations</h2>
1933+
1934+<p>The <code>provides</code> and <code>requires</code> keys are used to define
1935+pairings of charms that are likely to be fruitful. Consider a simple mongodb
1936+charm's metadata:</p>
1937+
1938+<pre class="prettyprint lang-yaml">
1939+name: my-mongodb
1940+...
1941+provides:
1942+ server: mongodb
1943+</pre>
1944+
1945+<p>...and that of a simple node.js application charm:</p>
1946+
1947+<pre class="prettyprint lang-yaml">
1948+name: my-node-app
1949+...
1950+requires:
1951+ database: mongodb
1952+provides:
1953+ website: http
1954+</pre>
1955+
1956+<p>Put together, these files indicate that a relation can be made between services
1957+running the respective charms. The my-mongodb charm <code>provides</code> a relation named
1958+<code>server</code> with the <code>mongodb</code> interface, and the my-node-app charm
1959+<code>requires</code> a relation named <code>database</code> with the <code>mongodb</code>
1960+interface.</p>
1961+
1962+<p>The my-node-app charm also <code>provides</code> a relation named <code>website</code>
1963+with the <code>http</code> interface, but that's irrelevant to the mongodb charm. (But an
1964+haproxy charm might well define, say, <code>reverseproxy</code>, that <code>requires</code>
1965+the <code>http</code> interface provided by my-node-app.)</p>
1966+</section>
1967+
1968+<section id="relation-interfaces">
1969+<h2>Relation interfaces</h2>
1970+
1971+<p>An interface is a string that must only contain <code>a-z</code> and <code>-</code>,
1972+and neither start nor end with <code>-</code>. It's the single determiner of
1973+compatibility between charms; and it carries with it nothing more than a mutual
1974+promise that the provider and requirer somehow know the communication protocol
1975+implied by the name.</p>
1976+
1977+<p>So, the relation namespace is essentially unrestricted (with one enforced
1978+exception: you may not <em>provide</em> a relation named <code>juju</code>, or
1979+starting with <code>juju-</code>). This allows for rapid development in some
1980+situations; but, in the example above, there is a potential problem: we've picked
1981+<em>two</em> interface names that already have meanings in the charm ecosystem,
1982+and that means we have to be <a href="./authors-charm-interfaces.html">compatible</a>;
1983+but that's a concern for a bit later, when we're actually writing the relation hooks.</p>
1984+</section>
1985+
1986+<section id="peer-relations">
1987+<h2>Peer relations</h2>
1988+
1989+<p>Alongside <code>provides</code> and <code>requires</code>, charms can declare
1990+relations under <code>peers</code>. Where <code>provides</code> relations integrate
1991+with <code>requires</code> ones, such that providers respond to requirers and vice
1992+versa, the <code>peers</code> relation causes each unit of a single service to
1993+respond to the other units in the same service. A peer relation is otherwise defined
1994+in exactly the same way as any other relation.</p>
1995+</section>
1996+
1997+<section id="relation-config">
1998+<h2>Configuring relations</h2>
1999+
2000+<p>There's an alternative syntax for specifying relations, which allows you to
2001+set additional fields by replacing the interface name with a dictionary. In this case, the <code>interface</code> key must be specified explicitly, and a number of other possibilities become available:</p>
2002+<ul>
2003+ <li><code>scope</code> defaults to <code>global</code>, but may be set to
2004+ <code>container</code>. The scope controls the set of remote units that are
2005+ reported to the unit as members of the relation: container-scoped relations
2006+ are restricted to reporting details of a single principal unit to a single
2007+ subordinate, and vice versa, while global relations consider all possible
2008+ remote units.<br />
2009+ <a href="authors-charm-subordinates.html">Subordinate</a> charms are only
2010+ valid if they have at least one <code>requires</code> relation with
2011+ <code>container</code> scope.</li>
2012+ <li><code>limit</code> is ignored by juju, but if present should be a positive
2013+ integer N indicating that the charm is not designed to use this interface in more
2014+ than N relations at once.<br />
2015+ For example, if you're writing a really simple exploratory charm for your
2016+ particular data store, you could just create a single shared store and
2017+ write the same access credentials for every relation. A limit of 1 is
2018+ thus useful in that it does <em>document</em> the restriction, even though
2019+ it's not automatically enforced today.</li>
2020+ <li><code>optional</code> is ignored by juju, but if present should only be
2021+ set to true, on <code>requires</code> relations, to indicate that the charm
2022+ can still function effectively without having those relations added.<br />
2023+ For example, the my-node-app charm might also define:<br />
2024+<pre class="prettyprint lang-yaml">
2025+requires:
2026+ database: mongodb
2027+ memcache:
2028+ interface: memcached
2029+ optional: true
2030+</code></pre><br />
2031+ ...to indicate that it can integrate with memcached if it's available, but
2032+ that it can't be expected to do anything useful without a mongodb service
2033+ available.</li>
2034+ <li><code>gets</code> and <code>sets</code> are ignored by juju at present,
2035+ but are valuable <a href="./authors-charm-interfaces.html">documentation</a>.</li>
2036+</ul>
2037+
2038+</section>
2039+
2040+<section id="examples">
2041+<h2>Sample metadata.yaml files</h2>
2042+<p> The MySQL charm metadata: </p>
2043+<pre class="prettyprint">
2044+ name: mysql
2045+ summary: MySQL is a fast, stable and true multi-user, multi-threaded SQL database
2046+ maintainer: Marco Ceppi
2047+ description: |
2048+ MySQL is a fast, stable and true multi-user, multi-threaded SQL database
2049+ server. SQL (Structured Query Language) is the most popular database query
2050+ language in the world. The main goals of MySQL are speed, robustness and
2051+ ease of use.
2052+ categories:
2053+ - databases
2054+ provides:
2055+ db:
2056+ interface: mysql
2057+ db-admin:
2058+ interface: mysql-root
2059+ shared-db:
2060+ interface: mysql-shared
2061+ master:
2062+ interface: mysql-oneway-replication
2063+ munin:
2064+ interface: munin-node
2065+ monitors:
2066+ interface: monitors
2067+ local-monitors:
2068+ interface: local-monitors
2069+ scope: container
2070+
2071+peers:
2072+ cluster:
2073+ interface: mysql-ha
2074+
2075+requires:
2076+ slave:
2077+ interface: mysql-oneway-replication
2078+ ceph:
2079+ interface: ceph-client
2080+ ha:
2081+ interface: hacluster
2082+ scope: container
2083+</pre>
2084+
2085+
2086+</section>
2087+
2088+
2089+</article>
2090+<!--Postamble-->
2091+ </div>
2092+ </div>
2093+ </section>
2094+ </div>
2095+</div>
2096+<!--End-Postamble-->
2097+<!--Footer-->
2098+ <footer class="global clearfix" role="contentinfo">
2099+ <nav role="navigation">
2100+ <div class="footer-a">
2101+ <div class="clearfix">
2102+ <ul>
2103+ <li>
2104+ <h2><a href="/">Juju</a></h2>
2105+ <ul>
2106+ <li><a href="/charms">Charms</a></li>
2107+ <li><a href="/features">Features</a></li>
2108+ <li><a href="/deployment">Deployment</a></li>
2109+ </ul>
2110+ </li>
2111+ <li>
2112+ <h2><a href="/resources">Resources</a></h2>
2113+ <ul>
2114+ <li><a href="/resources/juju-overview/">Overview</a></li>
2115+ <li><a href="/docs/">Documentation</a></li>
2116+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
2117+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
2118+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
2119+ <li><a href="/resources/videos/">Videos</a></li>
2120+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
2121+ </ul>
2122+ </li>
2123+ <li>
2124+ <h2><a href="/community">Community</a></h2>
2125+ <ul>
2126+ <li><a href="/community/blog/">Juju Blog</a></li>
2127+ <li><a href="/events/">Events</a></li>
2128+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
2129+ <li><a href="/community/charmers/">Charmers</a></li>
2130+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
2131+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
2132+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
2133+ </ul>
2134+ </li>
2135+ <li>
2136+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
2137+ <ul>
2138+ <li><a href="https://jujucharms.com/">Charm store</a></li>
2139+ <li><a href="/download/">Download Juju</a></li>
2140+ </ul>
2141+ </li>
2142+ </ul>
2143+ </div>
2144+ </div>
2145+ </nav>
2146+ <div class="legal clearfix">
2147+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
2148+ </div>
2149+ </footer>
2150+
2151+<!--End-Footer-->
2152+<!--Scripts-->
2153+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
2154+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
2155+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
2156+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
2157+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
2158+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
2159+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
2160+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
2161+ <!-- google analytics -->
2162+ <script>
2163+ var _gaq = _gaq || [];
2164+ _gaq.push(['_setAccount', 'UA-1018242-41']);
2165+ _gaq.push(['_trackPageview']);
2166+
2167+ (function() {
2168+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
2169+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
2170+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
2171+ })();
2172+ </script>
2173+<!--End-Scripts-->
2174+
2175+
2176+</body></html>
2177+
2178
2179=== modified file 'htmldocs/authors-charm-policy.html'
2180--- htmldocs/authors-charm-policy.html 2013-09-27 14:53:30 +0000
2181+++ htmldocs/authors-charm-policy.html 2013-10-09 20:07:46 +0000
2182@@ -23,6 +23,8 @@
2183
2184
2185
2186+
2187+
2188 <body class="resources">
2189
2190 <!--Header-->
2191@@ -94,7 +96,7 @@
2192
2193 <h2>metadata.yaml</h2>
2194
2195- <p>This file is an important component of a charm, see <a href="authors-charm-anatomy.html">Anatomy of a Charm</a> for the structure.</p>
2196+ <p>This file is an <a href="authors-charm-contents.html">important component</a> of a charm.</p>
2197 <p>Check out the <a href="https://bazaar.launchpad.net/~charmers/charms/precise/mysql/trunk/view/head:/metadata.yaml">MySQL metadata.yaml</a> as an example.</p>
2198
2199
2200@@ -212,4 +214,6 @@
2201 <!--End-Scripts-->
2202
2203
2204+
2205+
2206 </body></html>
2207
2208=== modified file 'htmldocs/authors-charm-quality.html'
2209--- htmldocs/authors-charm-quality.html 2013-09-27 14:53:30 +0000
2210+++ htmldocs/authors-charm-quality.html 2013-10-09 20:07:46 +0000
2211@@ -23,6 +23,8 @@
2212
2213
2214
2215+
2216+
2217 <body class="resources">
2218
2219 <!--Header-->
2220@@ -295,4 +297,6 @@
2221 <!--End-Scripts-->
2222
2223
2224+
2225+
2226 </body></html>
2227
2228=== modified file 'htmldocs/authors-charm-store.html'
2229--- htmldocs/authors-charm-store.html 2013-09-27 14:53:30 +0000
2230+++ htmldocs/authors-charm-store.html 2013-10-09 20:07:46 +0000
2231@@ -23,6 +23,8 @@
2232
2233
2234
2235+
2236+
2237 <body class="resources">
2238
2239 <!--Header-->
2240@@ -297,4 +299,6 @@
2241 <!--End-Scripts-->
2242
2243
2244+
2245+
2246 </body></html>
2247
2248=== added file 'htmldocs/authors-charm-upgrades.html'
2249--- htmldocs/authors-charm-upgrades.html 1970-01-01 00:00:00 +0000
2250+++ htmldocs/authors-charm-upgrades.html 2013-10-09 20:07:46 +0000
2251@@ -0,0 +1,212 @@
2252+<!DOCTYPE html>
2253+<html>
2254+ <head>
2255+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2256+ <title>Juju Documentation - Charm Upgrades</title>
2257+ <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' />
2258+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" />
2259+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" />
2260+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" />
2261+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" />
2262+ <link rel='stylesheet' id='stacktack-css' href='//juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2' type='text/css' media='all' />
2263+ <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/>
2264+
2265+ <!--[if lt IE 9]>
2266+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
2267+ <![endif]-->
2268+</head>
2269+ <body class="resources">
2270+ <header class="global clearfix" role="banner">
2271+ <div class="header-navigation">
2272+ <div>
2273+ <nav role="navigation">
2274+ <ul>
2275+ <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li>
2276+ <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li>
2277+ <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
2278+ <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li>
2279+ <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li>
2280+ <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li>
2281+ <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li>
2282+ <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li>
2283+ <li>
2284+ <form id="form-search" method="get" action="https://juju.ubuntu.com/">
2285+ <fieldset>
2286+ <input id="input-search" type="text" name="s" value="Search" />
2287+ </fieldset>
2288+ </form>
2289+ </li>
2290+ </ul>
2291+ </nav>
2292+ </div>
2293+ </div>
2294+ <div class="header-content">
2295+ <div class="clearfix">
2296+ <img src="https://juju.ubuntu.com/wp-content/themes/juju-website/img/arrow-nav.png" width="9" height="5" style="left:455px; display: block;" class="arrow-nav">
2297+ <div class="header-navigation-secondary"></div>
2298+ <div class="header-image"></div>
2299+ <h1>Resources</h1>
2300+ <h2>A collection of some of the most important online references for Juju users and developers.</h2>
2301+ </div>
2302+ </div>
2303+</header>
2304+
2305+ <section id="content" class="container-12">
2306+ <div class="grid-12 doc-container">
2307+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
2308+ <div class="grid-9 doc-content">
2309+ <article>
2310+
2311+
2312+<!--Actual docs start here-->
2313+
2314+<section id="charm-upgrades">
2315+<h1>Charm upgrades</h1>
2316+
2317+<p>A service's charm can be changed at runtime with the <code>upgrade-charm</code>
2318+command. By default, it changes to the latest available version of the same charm; if
2319+<code>--revision</code> is specified, it changes to that revision of the same charm; and
2320+if <code>--switch</code> is specified it changes to any arbitrary charm, inferred from the
2321+argument in the same way as in <code>juju deploy</code>.</p>
2322+
2323+<p>For a charm to replace another, though, there is a minimum standard of
2324+compatibility, which applies regardless of the particular change. That is:</p>
2325+<ul>
2326+ <li>a subordinate charm must be replaced by a subordinate charm, and a
2327+ principal charm must be replaced by a principal charm.</li>
2328+ <li>every runtime relation used by the service must exist in both charms.</li>
2329+ <li class=" sub">charm relations that are defined, but not in use at runtime,
2330+ may be removed freely.</li>
2331+ <li class=" sub">in particular, it's not possible to remove a peer relation by
2332+ upgrading, because peer relations are always in use.</li>
2333+</ul>
2334+<p>No other factor is used in determining compatibility: configuration settings
2335+in particular are converted completely naively, such that any settings from
2336+the original charm that share a name and type are preserved; any incompatible
2337+settings are removed; and any new settings take defaults as though freshly
2338+deployed.</p>
2339+
2340+<p>When a service has been upgraded but a particular unit has not, the unit will
2341+continue to see the configuration settings from before conversion; these settings
2342+will not be affected by subsequent changes to the service's settings.</p>
2343+</section>
2344+
2345+<section id="forced-upgrades">
2346+<h2>Forced charm upgrades</h2>
2347+
2348+<p>Juju defines the upgrade-charm <a href="./authors-hook-kinds.html">hook</a> for
2349+resolving differences between versions of the same charm. No notice is given of
2350+charm upgrades; a charm upgrade may run at any time the unit is started, and the
2351+only opportunity for resolution that exists occurs *after* the change has taken
2352+place.</p>
2353+
2354+<p>This is quite a tight restriction, but nonetheless valuable, so long as you can
2355+guarantee it'll run. However, it's important to understand that the upgrade-charm
2356+accepts a <code>--force</code> flag: a forced charm upgrade will upgrade even units
2357+that are currently in an <a href="./authors-hook-errors.html">error</a> state, at
2358+the cost of skipping the <code>upgrade-charm</code> hook for those units.</p>
2359+
2360+<p>This is useful for charm authors who want to push a new version of a failed hook
2361+(they can <code>upgrade-charm --force</code> and then <code>resolved --retry</code>
2362+to run it immediately without otherwise disturbing the system); but it's potentially
2363+dangerous if abused. We recommend that use of the feature be restricted to charm
2364+authors while developing their own charms, and that it's not sensible to devote
2365+serious effort to recovering from inappropriately forced upgrades.</p>
2366+</section>
2367+
2368+<section id="upgrade-errors">
2369+<h2>Charm upgrade errors</h2>
2370+
2371+<p>These will only occur as a result of conflicts between the contents of the
2372+charm directory written at runtime, and should never be seen by a user; users
2373+certainly cannot be expected to understand the structure of your charm well
2374+enough to solve the conflicts sanely.</p>
2375+
2376+<p>When you're writing a new version of a charm, you should always test upgrading
2377+it from (at least) the previous version, to ensure these errors don't slip out
2378+into the wild.</p>
2379+
2380+<p>You can completely avoid these errors by <em>never</em> writing to the charm
2381+directory; and you can also avoid them by rigorously delineating the parts of
2382+your charm directory that you write to at runtime, and ensuring you never add a
2383+file to the raw charm that could conflict with the runtime state.</p>
2384+
2385+<p>If you're writing your hooks in python, you should be doubly aware of this: if
2386+you don't configure python to suppress bytecode caching, it will write <code>.pyc</code>
2387+files next to your python files at runtime, and effectively prevent you from
2388+rearranging those directories in future. This is not an unreasonable burden to
2389+bear, but it's important to know you're taking it on.</p>
2390+
2391+<p>If you encounter a charm upgrade error, you can run <code>git status</code> in
2392+the charm directory to see what the problem is, and use the knowledge thus gleaned to
2393+fix the charm and try to upgrade again.</p>
2394+</section>
2395+
2396+
2397+ </article>
2398+ </div>
2399+ </div>
2400+ </section>
2401+ <div class="shadow"></div>
2402+ <footer class="global clearfix" role="contentinfo">
2403+ <div class="row">
2404+ <div class="inner-wrapper">
2405+ <nav role="navigation" class="clearfix">
2406+ <ul class="footer-a">
2407+ <li class="grid-3 first-col">
2408+ <h4><a href="/get-started">Get started</a></h4>
2409+ <ul>
2410+ <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li>
2411+ <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li>
2412+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li>
2413+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li>
2414+ <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li>
2415+ <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li>
2416+ </ul>
2417+ </li>
2418+ <li class="grid-3">
2419+ <h4><a href="/resources">Resources</a></h4>
2420+ <ul>
2421+ <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li>
2422+ <li><a href="/resources/videos/">Videos</a></li>
2423+ <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li>
2424+ </ul>
2425+ </li>
2426+ <li class="grid-3">
2427+ <h4><a href="/community">Community</a></h4>
2428+ <ul>
2429+ <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li>
2430+ <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li>
2431+ <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li>
2432+ <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li>
2433+ <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li>
2434+ <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li>
2435+ </ul>
2436+ </li>
2437+ <li class="grid-3 last-col">
2438+ <h4><a href="https://launchpad.net/juju">Code</a></h4>
2439+ <ul>
2440+ <li><a href="https://launchpad.net/juju-core">Juju Core</a></li>
2441+ <li><a href="https://launchpad.net/charms">Charms</a></li>
2442+ </ul>
2443+ </li>
2444+ </ul>
2445+ </nav>
2446+ </div>
2447+ </div>
2448+ <div class="row no-border">
2449+ <div class="legal inner-wrapper">
2450+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p>
2451+ <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p>
2452+ </div>
2453+ </div>
2454+</footer>
2455+
2456+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
2457+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
2458+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
2459+ <script type="text/javascript" src="js/main.js"></script>
2460+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
2461+ </body>
2462+</html>
2463+
2464
2465=== modified file 'htmldocs/authors-charm-writing.html'
2466--- htmldocs/authors-charm-writing.html 2013-10-03 07:29:32 +0000
2467+++ htmldocs/authors-charm-writing.html 2013-10-09 20:07:46 +0000
2468@@ -23,6 +23,8 @@
2469
2470
2471
2472+
2473+
2474 <body class="resources">
2475
2476 <!--Header-->
2477@@ -166,7 +168,7 @@
2478 <span class="number" > 4 </span>
2479 <div class="step" id="step04">
2480 <h2>Writing hooks</h2>
2481- <p>As you will know from your through reading of <a href="./authors-charm-anatomy.html"> the anatomy of a charm</a> The hooks are the important scripts that actually do things. You can write hooks in whatever language you can reasonably expect to execute on an Ubuntu server</p>
2482+ <p>As you will know from your thorough reading of the <a href="./authors-charm-contents.html">charm contents</a>, the hooks are the important scripts that actually do things. You can write hooks in whatever language you can reasonably expect to execute on an Ubuntu server.</p>
2483 <p>For our charm, the hooks we will need to create are:</p>
2484 <ul>
2485 <li>start - for when the service needs to be started.</li>
2486@@ -416,4 +418,6 @@
2487 <!--End-Scripts-->
2488
2489
2490+
2491+
2492 </body></html>
2493
2494=== removed file 'htmldocs/authors-charms-in-action.html'
2495--- htmldocs/authors-charms-in-action.html 2013-09-27 14:53:30 +0000
2496+++ htmldocs/authors-charms-in-action.html 1970-01-01 00:00:00 +0000
2497@@ -1,296 +0,0 @@
2498-<!DOCTYPE html>
2499-<html>
2500-<!--Head-->
2501- <head>
2502- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
2503- <title>Juju Documentation</title>
2504- <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
2505- <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
2506- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
2507- <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
2508- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
2509- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
2510- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
2511- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
2512- <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
2513- <link href="./css/main.css" rel="stylesheet" type="text/css">
2514-
2515- <!--[if lt IE 9]>
2516- <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
2517- <![endif]-->
2518- </head>
2519-<!--End-Head-->
2520-
2521-
2522-
2523- <body class="resources">
2524-
2525-<!--Header-->
2526-
2527- <header class="banner global" role="banner">
2528- <nav role="navigation" class="nav-primary nav-right">
2529- <div class="logo">
2530- <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
2531- <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
2532- <span>Juju</span>
2533- </a>
2534- </div>
2535- <ul>
2536- <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
2537- <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
2538- <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
2539- <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
2540- <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
2541- <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
2542- <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
2543- </ul>
2544- <div id="box-search">
2545- <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
2546- <label class="off-left" for="s">Search:</label>
2547- <input class="form-text" type="text" value="" name="s" id="s" />
2548- <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
2549- </form>
2550- </div>
2551- </nav>
2552- </header>
2553-<!--End-Header-->
2554-<!--Preamble-->
2555-<div class="wrapper">
2556- <div id="main-content" class="inner-wrapper" role="main">
2557- <div class="row no-border">
2558- <div class="header-navigation-secondary"></div>
2559- <h2 class="pagetitle">Juju documentation</h2>
2560- </div>
2561- <section id="content" class="container-12">
2562- <div class="grid-12 doc-container">
2563- <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
2564- <div class="grid-9 doc-content">
2565-<!--End-Preamble-->
2566- <article>
2567- <section id="charm-in-action">
2568- <h1 id="charms-in-action">Charms in action</h1>
2569- <p>This document describes the behaviour of the go implementation of the unit agent, whose behaviour differs in some respects from that of the python implementation. This information is largely relevant to charm authors, and potentially to developers interested in the unit agent.</p>
2570-
2571- <h2 id="hooks">Hooks</h2>
2572- <p>A service unit's direct action is entirely defined by its charm's hooks. Hooks are executable files in a charm's hooks directory; hooks with particular names will be invoked by the juju unit agent at particular times, and thereby cause changes to the world.</p>
2573- <p>Whenever a hook-worthy event takes place, the unit agent tries to run the hook with the appropriate name. If the hook doesn't exist, the agent continues without complaint; if it does, it is invoked without arguments in a specific environment, and its output is written to the unit agent's log. If it returns a non-zero exit code, the agent enters an error state and awaits resolution; otherwise it continues to process environment changes as before.</p>
2574- <p>In general, a unit will run hooks in a clear sequence, about which a number of useful guarantees are made. All such guarantees come with the caveat that there is [TODO: will be: <code>remove-unit --force</code>] a mechanism for forcible termination of a unit, and that a unit so terminated will just stop, dead, and completely fail to run anything else ever again. This shouldn't actually be a big deal in practice.</p>
2575-
2576- <h2 id="errors-in-hooks">Errors in hooks</h2>
2577- <p>Hooks should ideally be idempotent, so that they can fail and be re-executed from scratch without trouble. As a hook author, you don't have complete control over the times your hook might be stopped: if the unit agent process is killed for any reason while running a hook, then when it recovers it will treat that hook as having failed -- just as if it had returned a non-zero exit code -- and request user intervention.</p>
2578- <p>It is unrealistic to expect great sophistication on the part of the average user, and as a charm author you should expect that users will attempt to re-execute failed hooks before attempting to investigate or understand the situation. You should therefore make every effort to ensure your hooks are idempotent when aborted and restarted.</p>
2579- <p>[TODO: I have a vague feeling that <code>juju resolved</code> actually defaults to &quot;just pretend the hook ran successfully&quot; mode. I'm not sure that's really the best default, but I'm also not sure we're in a position to change the UI that much.]</p>
2580- <p>The most sophisticated charms will consider the nature of their operations with care, and will be prepared to internally retry any operations they suspect of having failed transiently, to ensure that they only request user intervention in the most trying circumstances; and will also be careful to log any relevant information or advice before signalling the error.</p>
2581- <p>[TODO: I just thought; it would be really nice to have a juju-fail hook tool, which would allow charm authors to explicity set the unit's error status to something a bit more sophisticated than &quot;X hook failed&quot;. Wishlist, really.]</p>
2582-
2583- <h2 id="charm-deployment">Charm deployment</h2>
2584- <ul>
2585- <li>A charm is deployed into a directory that is entirely owned and controlled by juju.</li>
2586- <li>At certain times, control of the directory is ceded to the charm (by running a hook) or to the user (by entering an error state).</li>
2587- <li>At these times, and only at these times, should the charm directory be used by anything other than juju itself.</li>
2588- </ul>
2589-
2590- <p>The most important consequence of this is that it is a mistake to conflate the state of the charm with the state of the software deployed by the charm: it's fine to store <em>charm</em> state in the charm directory, but the charm must deploy its actual software elsewhere on the system.</p>
2591- <p>To put it another way: deleting the charm directory should not impact the software deployed by the charm in any way; and there is currently no mechanism by which deployed software can safely feed information back into the charm and/or expect that it will be acted upon in a timely way.</p>
2592- <p>[TODO: this sucks a bit. We have plans for a tool called <code>juju-run</code>, which would allow an arbitrary script to be invoked as though it were a hook at any time (well, it'd block until no other hook were running, but still). Probably isn't even that hard but it's still rolling around my brain, might either click soon or be overridden by higher priorities and be left for ages. I'm less sure, but have a suspicion, that <code>juju ssh &lt;unit&gt;</code> should also default to a juju-run environment: primarily because, without this, in the context of forced upgrades, the system cannot offer <em>any</em> guarantees about what it might suddenly do to the charm directory while the user's doing things with it. The alternative is to allow unguarded ssh, but tell people that they have to use something like <code>juju-run --interactive</code> before they modify the charm dir; this feels somewhat user-hostile, though.]</p>
2593-
2594- <h2 id="execution-environment">Execution environment</h2>
2595- <p>Every hook is run in the deployed charm directory, in an environment with the following characteristics:</p>
2596- <ul>
2597- <li>$PATH is prefixed by a directory containing command line tools through which the hooks can interact with juju.</li>
2598- <li>$CHARM_DIR holds the path to the charm directory.</li>
2599- <li>$JUJU_UNIT_NAME holds the name of the local unit.</li>
2600- <li><span class="math"><em>J</em><em>U</em><em>J</em><em>U</em><sub><em>C</em></sub><em>O</em><em>N</em><em>T</em><em>E</em><em>X</em><em>T</em><sub><em>I</em></sub><em>D</em><em>a</em><em>n</em><em>d</em></span>JUJU_AGENT_SOCKET are set (but should not be messed with: the command line tools won't work without them).</li>
2601- <li>$JUJU_API_ADDRESSES holds a space separated list of juju API addresses.</li>
2602- </ul>
2603- <h2 id="hook-tools">Hook tools</h2>
2604- <p>All hooks can directly use the following tools:</p>
2605- <ul>
2606- <li>juju-log (write arguments direct to juju's log (potentially redundant, hook output is all logged anyway, but --debug may remain useful))</li>
2607- <li>unit-get (returns the local unit's private-address or public-address)</li>
2608- <li>open-port (marks the supplied port/protocol as ready to open when the service is exposed)</li>
2609- <li>close-port (reverses the effect of open-port)</li>
2610- <li>config-get (get current service configuration values)</li>
2611- <li>relation-get (get the settings of some related unit)</li>
2612- <li>relation-set (write the local unit's relation settings)</li>
2613- <li>relation-ids (list all relations using a given charm relation)</li>
2614- <li>relation-list (list all units of a related service)</li>
2615- </ul>
2616- <p>Within the context of a single hook execution, the above tools present a sandboxed view of the system with the following properties:</p>
2617- <ul>
2618- <li>Any data retrieved corresponds to the real value of the underlying state at some point in time.</li>
2619- <li>Once state data has been observed within a given hook execution, further requests for the same data will produce the same results, unless that data has been explicitly changed with relation-set.</li>
2620- <li>Data changed by relation-set is only written to global state when the hook completes without error; changes made by a failing hook will be discarded and never observed by any other part of the system.</li>
2621- <li>Not actually sandboxed: open-port and close-port operate directly on state. [TODO: lp:1089304 - might be a little tricky.]</li>
2622- </ul>
2623-
2624- <h2 id="hook-kinds">Hook kinds</h2>
2625- <p>There are 5 <code>unit hooks</code> with predefined names that can be implemented by any charm:</p>
2626- <ul>
2627- <li>install</li>
2628- <li>config-changed</li>
2629- <li>start</li>
2630- <li>upgrade-charm</li>
2631- <li>stop</li>
2632- </ul>
2633- <p>For every relation defined by a charm, an additional 4 <code>relation hooks</code> can be implemented, named after the charm relation:</p>
2634- <ul>
2635- <li><name>-relation-joined</li>
2636- <li><name>-relation-changed</li>
2637- <li><name>-relation-departed</li>
2638- <li><name>-relation-broken</li>
2639- </ul>
2640-
2641- <h2 id="unit-hooks">Unit hooks</h2>
2642- <p>The <code>install</code> hook always runs once, and only once, before any other hook.</p>
2643- <p>The <code>config-changed</code> hook always runs once immediately after the install hook, and likewise after the upgrade-charm hook. It also runs whenever the service configuration changes, and when recovering from transient unit agent errors.</p>
2644- <p>The <code>start</code> hook always runs once immediately after the first config-changed hook; there are currently no other circumstances in which it will be called, but this may change in the future.</p>
2645- <p>The <code>upgrade-charm</code> hook always runs once immediately after the charm directory contents have been changed by an unforced charm upgrade operation, and <em>may</em> do so after a forced upgrade; but will <em>not</em> be run after a forced upgrade from an existing error state. (Consequently, neither will the config-changed hook that would ordinarily follow the upgrade-charm.)</p>
2646- <p>The <code>stop</code> hook is the last hook to be run before the unit is destroyed. In the future, it may be called in other situations.</p>
2647- <p>In normal operation, a unit will run at least the install, start, config-changed and stop hooks over the course of its lifetime.</p>
2648- <p>It should be noted that, while all hook tools are available to all hooks, the relation-* tools are not useful to the install, start, and stop hooks; this is because the first two are run before the unit has any opportunity to participate in any relations, and the stop hooks will not be run while the unit is still participating in one.</p>
2649-
2650- <h2 id="relation-hooks">Relation hooks</h2>
2651- <p>For each charm relation, any or all of the 4 relation hooks can be implemented. Relation hooks operate in an environment slightly different to that of unit hooks, in the following ways:</p>
2652- <ul>
2653- <li>JUJU_RELATION is set to the name of the charm relation. This is of limited value, because every relation hook already &quot;knows&quot; what charm relation it was written for; that is, in the &quot;foo-relation-joined&quot; hook, JUJU_RELATION is &quot;foo&quot;.</li>
2654- <li>JUJU_RELATION_ID is more useful, because it serves as unique identifier for a particular relation, and thereby allows the charm to handle distinct relations over a single endpoint. In hooks for the &quot;foo&quot; charm relation, JUJU_RELATION_ID always has the form &quot;foo:<id>&quot;, where id uniquely but opaquely identifies the runtime relation currently in play.</li>
2655- <li>The relation-* hook tools, which ordinarily require that a relation be specified, assume they're being called with respect to the current relation. The default can of course be overridden as usual.</li>
2656- </ul>
2657- <p>Furthermore, all relation hooks except relation-broken are notifications about some specific unit of a related service, and operate in an environment with the following additional properties:</p>
2658- <ul>
2659- <li>JUJU_REMOTE_UNIT is set to the name of the current related unit.</li>
2660- <li>The relation-get hook tool, which ordinarily requires that a related unit be specified, assumes that it is being called with respect to the current related unit. The default can of course be overridden as usual.</li>
2661- </ul>
2662- <p>For every relation in which a unit partcipates, hooks for the appropriate charm relation are run according to the following rules.</p>
2663- <p>The &quot;relation-joined&quot; hook always runs once when a related unit is first seen.</p>
2664- <p>The &quot;relation-changed&quot; hook for a given unit always runs once immediately following the relation-joined hook for that unit, and subsequently whenever the related unit changes its settings (by calling relation-set and exiting without error). Note that &quot;immediately&quot; only applies within the context of this particular runtime relation -- that is, when &quot;foo-relation-joined&quot; is run for unit &quot;bar/99&quot; in relation id &quot;foo:123&quot;, the only guarantee is that the next hook to be run <em>in relation id &quot;foo:123&quot;</em> will be &quot;foo-relation-changed&quot; for &quot;bar/99&quot;. Unit hooks may intervene, as may hooks for other relations, and even for other &quot;foo&quot; relations.</p>
2665- <p>The &quot;relation-departed&quot; hook for a given unit always runs once when a related unit is no longer related. After the &quot;relation-departed&quot; hook has run, no further notifications will be received from that unit; however, its settings will remain accessible via relation-get for the complete lifetime of the relation.</p>
2666- <p>The &quot;relation-broken&quot; hook is not specific to any unit, and always runs once when the local unit is ready to depart the relation itself. Before this hook is run, a relation-departed hook will be executed for every unit known to be related; it will never run while the relation appears to have members, but it may be the first and only hook to run for a given relation. The stop hook will not run while relations remain to be broken.</p>
2667- <h2 id="relations-in-depth">Relations in depth</h2>
2668- <p>A unit's <code>scope</code> consists of the group of units that are transitively connected to that unit within a particular relation. So, for a globally-scoped relation, that means every unit of each service in the relation; for a locally-scoped relation, it means only those sets of units which are deployed alongside one another. That is to say: a globally-scoped relation has a single unit scope, whilst a locally-scoped relation has one for each principal unit.</p>
2669- <p>When a unit becomes aware that it is a member of a relation, its only self- directed action is to <code>join</code> its scope within that relation. This involves two steps:</p>
2670- <ul>
2671- <li>Write initial relation settings (just one value, &quot;private-address&quot;), to ensure that they will be available to observers before they're triggered by the next step;</li>
2672- <li>Signal its existence, and role in the relation, to the rest of the system.</li>
2673- </ul>
2674- <p>The unit then starts observing and reacting to any other units in its scope which are playing a role in which it is interested. To be specific:</p>
2675- <ul>
2676- <li>Each provider unit observes every requirer unit</li>
2677- <li>Each requirer unit observes every provider unit</li>
2678- <li>Each peer unit observes every other peer unit</li>
2679- </ul>
2680- <p>Now, suppose that some unit as the very first unit to join the relation; and let's say it's a requirer. No provider units are present, so no hooks will fire. But, when a provider unit joins the relation, the requirer and provider become aware of each other almost simultaneously. (Similarly, the first two units in a peer relation become aware of each other almost simultaneously.)</p>
2681- <p>So, concurrently, the units on each side of the relation run their relation-joined and relation-changed hooks with respect to their counterpart. The intent is that they communicate appropriate information to each other to set up some sort of connection, by using the relation-set and relation-get hook tools; but neither unit is safe to assume that any particular setting has yet been set by its counterpart.</p>
2682- <p>This sounds kinda tricky to deal with, but merely requires suitable respect for the relation-get tool: it is important to realise that relation-get is <em>never</em> guaranteed to contain any values at all, because we have decided that it's perfectly legitimate for a unit to delete its own private-address value.</p>
2683- <p>[TODO: There is a school of thought that maintains that we should add an independent &quot;juju-private-address&quot; setting that <em>is</em> guaranteed, but for now the reality is that relation-get can <em>always</em> fail to produce any given value. However, in the name of sanity, it's probably reasonable to treat a missing private-address as an error, and assume that <code>relation-get private-address</code> is always safe. For all other values, we must operate with the understanding that relation-get can always fail.]</p>
2684- <p>In one specific kind of hook, this is easy to deal with. A relation-changed hook can always exit without error when the current remote unit is missing data, because the hook is guaranteed to be run again when that data changes -- and, assuming the remote unit is running a charm that agrees on how to implement the interface, the data <em>will</em> change and the hook <em>will</em> be run again.</p>
2685- <p>In <em>all</em> other cases -- unit hooks, relation hooks for a different relation, relation hooks for a different remote unit in the same relation, and even relation hooks other than -changed for the <em>same</em> remote unit -- there is no such guarantee. These hooks all run on their own schedule, and there is no reason to expect them to be re-run on a predictable schedule, or in some cases ever again.</p>
2686- <p>This means that all such hooks need to be able to handle missing relation data, and to complete successfully; they mustn't fail, because the user is powerless to resolve the situation, and they can't even wait for state to change, because they all see their own sandboxed composite snapshot of fairly-recent state, which never changes.</p>
2687- <p>So, outside a vey narrow range of circumstances, relation-get should be treated with particular care. The corresponding advice for relation-set is very simple by comparison: relation-set should be called early and often. Because the unit agent serializes hook execution, there is never any danger of concurrent changes to the data, and so a null setting change can be safely ignored, and will not cause other units to react.</p>
2688- <h2 id="departing-relations">Departing relations</h2>
2689- <p>A unit will depart a relation when either the relation or the unit itself is marked for termination. In either case, it follows the same sequence:</p>
2690- <ul>
2691- <li>For every known related unit -- those which have joined and not yet departed -- run the relation-departed hook.</li>
2692- <li>Run the relation-broken hook.</li>
2693- <li><code>depart</code> from its scope in the relation.</li>
2694- </ul>
2695- <p>The unit's departure from its scope will in turn be detected by units of the related service, and cause them to run relation-departed hooks. A unit's relation settings persist beyond its own departure from the relation; the final unit to depart a relation marked for termination is responsible for destroying the relation and all associated data.</p>
2696- <h2 id="debugging-charms">Debugging charms</h2>
2697- <p>Facilities are currently not good.</p>
2698- <ul>
2699- <li>juju ssh</li>
2700- <li>juju debug-hooks</li>
2701- <li>juju debug-log</li>
2702- </ul>
2703- <p>It may be helpful to note that the charm directory is a git repository that holds the complete hook-by-hook history of the deployment. This property is not guaranteed, and charms should not depend upon it, but humans who need to dig around in charm directories should be aware of it.</p>
2704-</article>
2705- </section>
2706-<!--Postamble-->
2707- </div>
2708- </div>
2709- </section>
2710- </div>
2711-</div>
2712-<!--End-Postamble-->
2713-<!--Footer-->
2714- <footer class="global clearfix" role="contentinfo">
2715- <nav role="navigation">
2716- <div class="footer-a">
2717- <div class="clearfix">
2718- <ul>
2719- <li>
2720- <h2><a href="/">Juju</a></h2>
2721- <ul>
2722- <li><a href="/charms">Charms</a></li>
2723- <li><a href="/features">Features</a></li>
2724- <li><a href="/deployment">Deployment</a></li>
2725- </ul>
2726- </li>
2727- <li>
2728- <h2><a href="/resources">Resources</a></h2>
2729- <ul>
2730- <li><a href="/resources/juju-overview/">Overview</a></li>
2731- <li><a href="/docs/">Documentation</a></li>
2732- <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
2733- <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
2734- <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
2735- <li><a href="/resources/videos/">Videos</a></li>
2736- <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
2737- </ul>
2738- </li>
2739- <li>
2740- <h2><a href="/community">Community</a></h2>
2741- <ul>
2742- <li><a href="/community/blog/">Juju Blog</a></li>
2743- <li><a href="/events/">Events</a></li>
2744- <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
2745- <li><a href="/community/charmers/">Charmers</a></li>
2746- <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
2747- <li><a href="/docs/contributing.html">Help with documentation</a></li>
2748- <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
2749- </ul>
2750- </li>
2751- <li>
2752- <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
2753- <ul>
2754- <li><a href="https://jujucharms.com/">Charm store</a></li>
2755- <li><a href="/download/">Download Juju</a></li>
2756- </ul>
2757- </li>
2758- </ul>
2759- </div>
2760- </div>
2761- </nav>
2762- <div class="legal clearfix">
2763- <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
2764- </div>
2765- </footer>
2766-
2767-<!--End-Footer-->
2768-
2769-<!--Scripts-->
2770- <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
2771- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
2772- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
2773- <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
2774- <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
2775- <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
2776- <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
2777- <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
2778- <!-- google analytics -->
2779- <script>
2780- var _gaq = _gaq || [];
2781- _gaq.push(['_setAccount', 'UA-1018242-41']);
2782- _gaq.push(['_trackPageview']);
2783-
2784- (function() {
2785- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
2786- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
2787- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
2788- })();
2789- </script>
2790-<!--End-Scripts-->
2791-
2792-
2793-</body></html>
2794\ No newline at end of file
2795
2796=== added file 'htmldocs/authors-hook-debug.html'
2797--- htmldocs/authors-hook-debug.html 1970-01-01 00:00:00 +0000
2798+++ htmldocs/authors-hook-debug.html 2013-10-09 20:07:46 +0000
2799@@ -0,0 +1,169 @@
2800+<!DOCTYPE html>
2801+<html>
2802+ <head>
2803+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2804+ <title>Juju Documentation - Hook Debugging</title>
2805+ <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' />
2806+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" />
2807+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" />
2808+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" />
2809+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" />
2810+ <link rel='stylesheet' id='stacktack-css' href='//juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2' type='text/css' media='all' />
2811+ <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/>
2812+
2813+ <!--[if lt IE 9]>
2814+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
2815+ <![endif]-->
2816+</head>
2817+ <body class="resources">
2818+ <header class="global clearfix" role="banner">
2819+ <div class="header-navigation">
2820+ <div>
2821+ <nav role="navigation">
2822+ <ul>
2823+ <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li>
2824+ <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li>
2825+ <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
2826+ <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li>
2827+ <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li>
2828+ <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li>
2829+ <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li>
2830+ <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li>
2831+ <li>
2832+ <form id="form-search" method="get" action="https://juju.ubuntu.com/">
2833+ <fieldset>
2834+ <input id="input-search" type="text" name="s" value="Search" />
2835+ </fieldset>
2836+ </form>
2837+ </li>
2838+ </ul>
2839+ </nav>
2840+ </div>
2841+ </div>
2842+ <div class="header-content">
2843+ <div class="clearfix">
2844+ <img src="https://juju.ubuntu.com/wp-content/themes/juju-website/img/arrow-nav.png" width="9" height="5" style="left:455px; display: block;" class="arrow-nav">
2845+ <div class="header-navigation-secondary"></div>
2846+ <div class="header-image"></div>
2847+ <h1>Resources</h1>
2848+ <h2>A collection of some of the most important online references for Juju users and developers.</h2>
2849+ </div>
2850+ </div>
2851+</header>
2852+
2853+ <section id="content" class="container-12">
2854+ <div class="grid-12 doc-container">
2855+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
2856+ <div class="grid-9 doc-content">
2857+ <article>
2858+
2859+
2860+<section id="debugging-hooks">
2861+<h1>Debugging hooks</h1>
2862+
2863+<p>The <code>juju debug-hooks</code> command accepts a unit and an optional list
2864+of hooks to debug, which must each be named individually -- or all omitted, causing all
2865+hooks to be debugged.</p>
2866+
2867+<p>When you start a debug-hooks session, juju creates a tmux session on the
2868+machine running the requested unit; while that session persists, all hook
2869+executions will be replaced with new windows in that session, which run an
2870+<a href="./authors-hook-environment.html">environment</a> matching that of the
2871+appropriate hook (with one addition: <code>$JUJU_HOOK_NAME</code>) and which are
2872+marked as succeeded or failed depending on the exit code of the window.</p>
2873+
2874+<p>You can stop debugging by closing all windows in the tmux session.</p>
2875+</section>
2876+
2877+<section id="intercept-install">
2878+<h2>Debugging early hooks</h2>
2879+
2880+<p>The <code>install</code>, <code>config-changed</code>, and <code>start</code>
2881+hooks often execute quite soon after the unit comes up, making it difficult to start
2882+a debug-hooks session in time to intercept them. If you're having difficulties, you
2883+can temporarily return an error code from your <code>install</code> hook, and start
2884+your session only when the unit reports an <a href="./authors-hook-errors.html">error
2885+status</a>; then run <code>juju resolved --retry</code> for the affected unit, and go
2886+back to the debug-hooks session to interact.</p>
2887+</section>
2888+
2889+<section id="notes">
2890+<h2>Special considerations</h2>
2891+
2892+<p>While you're debugging hooks for one unit on a machine, you're blocking
2893+execution of all hooks on that machine. This is generally helpful, because
2894+you don't want to have to contend with concurrent changes to the machine's
2895+software, but you should be aware that multiple debug-hooks sessions for
2896+units assigned to the same machine will block one another, and that you
2897+can't control relative execution order directly (other than by erroring out
2898+of hooks you don't want to run yet, and retrying them later).</p>
2899+</section>
2900+
2901+
2902+ </article>
2903+ </div>
2904+ </div>
2905+ </section>
2906+ <div class="shadow"></div>
2907+ <footer class="global clearfix" role="contentinfo">
2908+ <div class="row">
2909+ <div class="inner-wrapper">
2910+ <nav role="navigation" class="clearfix">
2911+ <ul class="footer-a">
2912+ <li class="grid-3 first-col">
2913+ <h4><a href="/get-started">Get started</a></h4>
2914+ <ul>
2915+ <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li>
2916+ <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li>
2917+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li>
2918+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li>
2919+ <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li>
2920+ <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li>
2921+ </ul>
2922+ </li>
2923+ <li class="grid-3">
2924+ <h4><a href="/resources">Resources</a></h4>
2925+ <ul>
2926+ <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li>
2927+ <li><a href="/resources/videos/">Videos</a></li>
2928+ <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li>
2929+ </ul>
2930+ </li>
2931+ <li class="grid-3">
2932+ <h4><a href="/community">Community</a></h4>
2933+ <ul>
2934+ <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li>
2935+ <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li>
2936+ <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li>
2937+ <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li>
2938+ <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li>
2939+ <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li>
2940+ </ul>
2941+ </li>
2942+ <li class="grid-3 last-col">
2943+ <h4><a href="https://launchpad.net/juju">Code</a></h4>
2944+ <ul>
2945+ <li><a href="https://launchpad.net/juju-core">Juju Core</a></li>
2946+ <li><a href="https://launchpad.net/charms">Charms</a></li>
2947+ </ul>
2948+ </li>
2949+ </ul>
2950+ </nav>
2951+ </div>
2952+ </div>
2953+ <div class="row no-border">
2954+ <div class="legal inner-wrapper">
2955+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p>
2956+ <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p>
2957+ </div>
2958+ </div>
2959+</footer>
2960+
2961+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
2962+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
2963+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
2964+ <script type="text/javascript" src="js/main.js"></script>
2965+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
2966+ </body>
2967+</html>
2968+
2969
2970=== added file 'htmldocs/authors-hook-environment.html'
2971--- htmldocs/authors-hook-environment.html 1970-01-01 00:00:00 +0000
2972+++ htmldocs/authors-hook-environment.html 2013-10-09 20:07:46 +0000
2973@@ -0,0 +1,561 @@
2974+<!DOCTYPE html>
2975+<html>
2976+<!--Head-->
2977+ <head>
2978+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
2979+ <title>Juju Documentation</title>
2980+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
2981+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
2982+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
2983+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
2984+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
2985+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
2986+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
2987+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
2988+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
2989+ <link href="./css/main.css" rel="stylesheet" type="text/css">
2990+
2991+ <!--[if lt IE 9]>
2992+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
2993+ <![endif]-->
2994+ </head>
2995+<!--End-Head-->
2996+
2997+ <body class="resources">
2998+<!--Header-->
2999+
3000+ <header class="banner global" role="banner">
3001+ <nav role="navigation" class="nav-primary nav-right">
3002+ <div class="logo">
3003+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
3004+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
3005+ <span>Juju</span>
3006+ </a>
3007+ </div>
3008+ <ul>
3009+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
3010+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
3011+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
3012+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
3013+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
3014+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
3015+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
3016+ </ul>
3017+ <div id="box-search">
3018+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
3019+ <label class="off-left" for="s">Search:</label>
3020+ <input class="form-text" type="text" value="" name="s" id="s" />
3021+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
3022+ </form>
3023+ </div>
3024+ </nav>
3025+ </header>
3026+<!--End-Header-->
3027+<!--Preamble-->
3028+<div class="wrapper">
3029+ <div id="main-content" class="inner-wrapper" role="main">
3030+ <div class="row no-border">
3031+ <div class="header-navigation-secondary"></div>
3032+ <h2 class="pagetitle">Juju documentation</h2>
3033+ </div>
3034+ <section id="content" class="container-12">
3035+ <div class="grid-12 doc-container">
3036+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
3037+ <div class="grid-9 doc-content">
3038+<!--End-Preamble-->
3039+<article>
3040+<section id="hook-execution-environment">
3041+<h1>Hook execution environment</h1>
3042+
3043+<p>When a charm is deployed onto a unit, the raw charm is extracted into a
3044+directory; this directory is known as the charm directory. It's owned and
3045+operated by juju, and juju sometimes temporarily cedes control of it to
3046+user code, by running a hook inside it.</p>
3047+
3048+<p>When a hook's running, it should be considered to have sole access to the
3049+charm directory; at all other times, you should consider that juju may be
3050+making arbitrarily scary changes to the directory, and that it is not safe
3051+to read or write to anything in there at all.</p>
3052+
3053+<p>This is to say that the software you install must, once it's running, be
3054+entirely independent of the charm that created it. It's fine (and encouraged,
3055+with some caveats) to store <em>charm</em> state in the charm directory, but the
3056+state of your <em>software</em> must remain unperturbed by direct changes to the
3057+charm.</p>
3058+
3059+<p>So, every hook runs with easy access to the charm files. Every hook also runs
3060+as root, with a number of useful variables set, and has access to hook-specific
3061+tools that let you interrogate and affect the juju environment.</p>
3062+
3063+<p>No more than one hook will execute on a given system at a given time. A unit in
3064+a container is considered to be on a different system to any unit on the
3065+container's host machine.</p>
3066+</section>
3067+
3068+<section id="environment-variables">
3069+<h2>Environment variables</h2>
3070+
3071+<p>The following variables are always available.</p>
3072+<ul>
3073+ <li>The <code>$CHARM_DIR</code> variable is the path to the charm directory.</li>
3074+ <li>The <code>$PATH</code> variable is prefixed with the path to the hook tools
3075+ directory.</li>
3076+ <li>The <code>$JUJU_UNIT_NAME</code> variable holds the name of the unit.</li>
3077+ <li>The <code>$JUJU_API_ADDRESSES</code> variable holds a space-separated list of API
3078+ server addresses.</li>
3079+</ul>
3080+<p>In addition, every relation hook makes available relation-specific variables.</p>
3081+<ul>
3082+ <li>The <code>$JUJU_RELATION</code> variable holds the relation name. This
3083+ information is of limited value, because it's always the same as the part of
3084+ the hook name just before &quot;-relation-&quot;.</li>
3085+ <li>The <code>$JUJU_RELATION_ID</code> variable holds an opaque relation
3086+ identifier, used to distinguish between multiple relations with the same name.
3087+ It is vitally important, because it's the only reasonable way of telling the
3088+ difference between (say) a database service's many independent clients.</li>
3089+</ul>
3090+<p>...and, if that relation hook is not a -broken hook:</p>
3091+<ul>
3092+ <li>The <code>$JUJU_REMOTE_UNIT</code> variable holds the name of the unit which
3093+ is being reported to have -joined, -changed, or -departed.</li>
3094+</ul>
3095+<p>Juju does <em>not</em> pay any attention to the values of the above variables when
3096+running hook tools: they're a one-way communication channel from juju to
3097+the charm only. Finally, in all cases:</p>
3098+<ul>
3099+ <li>The <code>$JUJU_AGENT_SOCKET</code> and <code>$JUJU_CONTEXT_ID</code> variables
3100+ allow the hook tools to work: juju <em>does</em> pay attention to them, but you
3101+ should treat them as opaque and avoid messing with them.</li>
3102+</ul>
3103+<p>Finally, if you're <a href="./authors-hook-debug.html">debugging</a>, you'll also
3104+have access to:</p>
3105+<ul>
3106+ <li>The <code>$JUJU_HOOK_NAME</code> variable, which will be set to the current
3107+ hook name.</li>
3108+</ul>
3109+</section>
3110+
3111+<section id="hook-tools">
3112+<h2>Hook tools</h2>
3113+
3114+<p>All hook tools are available in all hooks. Many of the tools produce output,
3115+and those that do accept a <code>--format</code> flag whose value can be set to
3116+<code>json</code> or <code>yaml</code> as desired. If it's not specified, the format
3117+defaults to <code>smart</code>, which transforms the basic output as follows:</p>
3118+<ul>
3119+ <li>strings are left untouched</li>
3120+ <li>boolean values are converted to the strings <code>True</code> and
3121+ <code>False</code></li>
3122+ <li>ints and floats are converted directly to strings</li>
3123+ <li>lists of strings are converted to a single newline-separated string</li>
3124+ <li>all other types (in general, dictionaries) are formatted as YAML</li>
3125+</ul>
3126+<p>Tools which do not produce output also accept the <code>--format</code> flag,
3127+but ignore it, for compatibility reasons.</p>
3128+
3129+<p>The various &quot;relation-&quot; tools infer context from the hook where
3130+possible. If they're running in a relation hook, the current relation id is set
3131+as the default; and if they're running in a -joined, -changed, or -broken hook,
3132+the current remote unit is set as the default.</p>
3133+
3134+<p>Best use of relation hooks will be made by those who understand the
3135+<a href="./authors-relations-in-depth">relation model</a>.</p>
3136+</section>
3137+
3138+<section id="juju-log">
3139+<h3>juju-log</h3>
3140+
3141+<p><code>juju-log</code> writes its arguments directly to the unit's log file.
3142+All hook output is currently logged anyway, so it's theoretically redundant with
3143+<code>echo</code>, but this is an implementation detail and should not be depended
3144+upon. If it's important, please <code>juju-log</code> it.</p>
3145+
3146+<pre class="prettyprint lang-bash">
3147+juju-log "some important text"
3148+</pre>
3149+
3150+<p>It accepts a <code>--debug</code> flag which causes the message to be logged
3151+at <code>DEBUG</code> level; in all other cases it's logged at <code>INFO</code>
3152+level. The <code>-l</code>/<code>--level</code> argument is ignored, and is present
3153+only to prevent legacy charms from entirely failing to run; the inability to specify
3154+logging levels and targets in more detail is a known
3155+<a href="https://bugs.launchpad.net/juju-core/+bug/1223325">bug</a>.</p>
3156+</section>
3157+
3158+<section id="unit-get">
3159+<h3>unit-get</h3>
3160+
3161+<p><code>unit-get</code> returns information about the local unit. It accepts a
3162+single argument, which must be <code>private-address</code> or
3163+<code>public-address</code>. It is not affected by context.</p>
3164+
3165+<pre class="prettyprint">
3166+unit-get private-address
3167+10.0.1.101
3168+</pre>
3169+
3170+<pre class="prettyprint">
3171+unit-get public-address
3172+foo.example.com
3173+</pre>
3174+
3175+</section>
3176+
3177+<section id="config-get">
3178+<h3>config-get</h3>
3179+
3180+<p><code>config-get</code> returns information about the service configuration (as
3181+defined by the charm). If called without arguments, it returns a dictionary
3182+containing all config settings that are either explicitly set, or which
3183+have a non-nil default value. If the <code>--all</code> flag is passed, it returns
3184+a dictionary containing all definied config settings including nil values
3185+(for those without defaults). If called with a single argument, it returns
3186+the value of that config key. Missing config keys are reported as having a
3187+value of nil, and do not return an error.</p>
3188+
3189+<p>Get the interesting bits of the config:</p>
3190+<pre class="prettyprint">
3191+config-get
3192+
3193+key: some-value
3194+another-key: default-value
3195+</pre>
3196+<p>Get the whole config including nulls:</p>
3197+<pre class="prettyprint">
3198+config-get --all
3199+
3200+key: some-value
3201+another-key: default-value
3202+no-default: null
3203+</pre>
3204+<p>Retrieve a specific value:</p>
3205+<pre class="prettyprint">
3206+config-get _key_
3207+
3208+default-value
3209+</pre>
3210+<p>Get a config setting with no value:</p>
3211+<pre class="prettyprint lang-bash">
3212+config-get no-default
3213+</pre>
3214+<p>Get a config setting that doesn't exist:</p>
3215+<pre class="prettyprint lang-bash">
3216+config-get missing-key
3217+</pre>
3218+<p class = "note"><strong>Note: </strong> The above two examples are not misprints
3219+ - asking for a value which doesn't exist or has not been set returns nothing and
3220+raises no errors.</p>
3221+</section>
3222+
3223+<section id="open-port">
3224+<h3>open-port</h3>
3225+
3226+<p><code>open-port</code> marks a port on the local system as appropriate to
3227+open, if and when the service is exposed to the outside world. It accepts a single
3228+port with an optional protocol, which may be <code>udp</code> or <code>tcp</code>,
3229+where <code>tcp</code> is the default.</p>
3230+<p>Examples:</p>
3231+<p>Open 80/tcp if and when the service is exposed:</p>
3232+<pre class="prettyprint lang-bash">
3233+open-port 80
3234+</pre>
3235+<p>Open 1234/udp if and when the service is exposed:</p>
3236+<pre class="prettyprint lang-bash">
3237+open-port 1234/udp
3238+</code></pre>
3239+
3240+<p><code>open-port</code> will not have any effect if the service is not exposed,
3241+and may have a somewhat delayed effect even if it is. It accepts and ignores
3242+<code>--format</code>, because it doesn't produce any output.</p>
3243+
3244+</section>
3245+
3246+<section id="close-port">
3247+<h3>close-port</h3>
3248+<p><code>close-port</code> unmarks a local system port. If the service is not
3249+exposed, it has no effect; otherwise the port is marked for imminent closure. It
3250+accepts the same flags and arguments as <code>open-port</code>.</p>
3251+<p>Examples:</p>
3252+<p>Close 1234/udp if it was open:</p>
3253+<pre class="prettyprint lang-bash">
3254+close-port 1234/udp
3255+</pre>
3256+<p>Close port 80 if it was open:</p>
3257+<pre class="prettyprint lang-bash">
3258+close-port 80
3259+</pre>
3260+</section>
3261+
3262+<section id="relation-set">
3263+<h3>relation-set</h3>
3264+
3265+<p><code>relation-set</code> writes the local unit's settings for some relation. It
3266+accepts any number of <code>key=value</code> strings, and an optional <code>-r</code>
3267+argument, which defaults to the current relation id. If it's not running in a relation
3268+hook, <code>-r</code> needs to be specified. The <code>value</code> part of an argument
3269+is not inspected, and is stored directly as a string. Setting an empty string causes
3270+the setting to be removed.</p>
3271+<p>Examples:</p>
3272+<p>Set a pair of values for the local unit in the default relation:</p>
3273+<pre class="prettyprint lang-bash">
3274+echo $JUJU_RELATION_ID
3275+
3276+ server:3
3277+
3278+relation-set username=bob password=2db673e81ffa264c
3279+</pre>
3280+
3281+<p>Set a pair of values for the local unit in a specific relation:</p>
3282+<pre class="prettyprint lang-bash">
3283+relation-set -r server:3 username=jim password=12345
3284+</pre>
3285+<p>Clear a value for the local unit in the default relation:</p>
3286+<pre class="prettyprint lang-bash">
3287+echo $JUJU_RELATION_ID
3288+server:3
3289+relation-set deprecated-or-unused=
3290+</pre>
3291+
3292+<p><code>relation-set</code> is the single tool at your disposal for communicating
3293+your own configuration to units of related services. At least by convention, the
3294+charm that <code>provides</code> an interface is likely to set values, and a charm
3295+that <code>requires</code> that interface will read them; but there's nothing
3296+forcing this. Whatever information you need to propagate for the remote charm to
3297+work must be propagated via relation-set, with the single exception of the
3298+<code>private-address</code> key, which is always set before the unit joins.</p>
3299+
3300+<p>You may wish to overwrite the <code>private-address</code> setting, for example
3301+if you're writing a charm that serves as a proxy for some external service; but
3302+you should in general avoid <em>removing</em> that key, because most charms expect
3303+that value to exist unconditionally.</p>
3304+
3305+<p>All values set are stored locally until the hook completes; at that point,
3306+if the hook exit code is 0, all changed values will be communicated to the
3307+rest of the system, causing -changed hooks to run in all related units.</p>
3308+
3309+<p>There is no way to write settings for any unit other than the local unit; but
3310+any hook on the local unit can write settings for any relation the local unit is
3311+participating in.</p>
3312+
3313+</section>
3314+
3315+<section id="relation-get">
3316+<h3>relation-get</h3>
3317+
3318+<p><code>relation-get</code> reads the settings of the local unit, or of any
3319+remote unit, in a given relation (set with <code>-r</code>, defaulting to the
3320+current relation, as in <code>relation-set</code>). The first argument specifies
3321+the settings key, and the second the remote unit, which may be omitted if a
3322+default is available (that is, when running a relation hook other than -broken).</p>
3323+
3324+<p>If the first argument is omitted, a dictionary of all current keys and values
3325+will be printed; all values are always plain strings without any interpretation.
3326+If you need to specify a remote unit but want to see all settings, use <code>-</code>
3327+for the first argument.</p>
3328+
3329+<p>Get all settings from the default remote unit in the default relation:</p>
3330+<pre class="prettyprint lang-bash">
3331+$ echo $JUJU_RELATION_ID
3332+db:1
3333+$ echo $JUJU_REMOTE_UNIT
3334+mongodb/2
3335+$ relation-get
3336+username: jim
3337+password: "12345"
3338+</pre>
3339+<p>Get one setting from the default remote unit in the default relation:</p>
3340+<pre class="prettyprint lang-bash">
3341+echo $JUJU_RELATION_ID
3342+db:1
3343+
3344+echo $JUJU_REMOTE_UNIT
3345+mongodb/2
3346+
3347+relation-get username
3348+jim
3349+</pre>
3350+<p>Get all settings from a particular remote unit in a particular relation:</p>
3351+<pre class="prettyprint lang-bash">
3352+echo $JUJU_RELATION_ID
3353+
3354+relation-get -r database:7 - mongodb/5
3355+
3356+ username: bob
3357+ password: 2db673e81ffa264c
3358+</pre>
3359+
3360+<p>Note that <code>relation-get</code> produces results that are <em>consistent</em>
3361+but not necessarily <em>accurate</em>, in that you will always see settings that:</p>
3362+<ul>
3363+ <li>were accurate at some point in the reasonably recent past
3364+ <li>are always the same within a single hook run...
3365+ <li class=" sub"><em>except</em> when inspecting the unit's own relation settings,
3366+ in which case local changes from <code>relation-set</code> will be seen correctly.</li>
3367+</ul>
3368+<p>You should never depend upon the presence of any given key in <code>relation-get</code>
3369+output. Processing that depends on specific values (other than
3370+<code>private-addres</code>) should be restricted to -changed hooks for the relevant
3371+unit, and the absence of a remote unit's value should never be treated as an
3372+<a href="./authors-hook-errors.html">error</a> in the local unit.</p>
3373+
3374+<p>In practice, it is common and encouraged for -relation-changed hooks to exit
3375+early, without error, after inspecting <code>relation-get</code> output and
3376+determining it to be inadequate; and for <a href="./authors-hook-kinds.html">all
3377+other hooks</a> to be resilient in the face of missing keys, such that
3378+-relation-changed hooks will be sufficient to complete all configuration that
3379+depends on remote unit settings.</p>
3380+
3381+<p>Settings for remote units already known to have departed remain accessible
3382+for the lifetime of the relation.</p>
3383+
3384+<p><code>relation-get</code> currently has a
3385+<a href="https://bugs.launchpad.net/juju-core/+bug/1223339">bug</a> that allows units
3386+of the same service to see each other's settings outside of a peer relation. Depending
3387+on this behaviour is foolish in the extreme: if you need to share settings between
3388+units of the same service, always use a peer relation to do so, or you may be
3389+seriously inconvenienced when the hole is closed without notice.</p>
3390+
3391+</section>
3392+
3393+<section id="relation-list">
3394+<h3>relation-list</h3>
3395+
3396+<p><code>relation-list</code> accepts the <code>-r</code> flag as above, and
3397+outputs the names of every remote unit currently known to be in the relation.</p>
3398+<p>Examples:</p>
3399+<p>Show all remote units in the current relation</p>
3400+<pre class="prettyprint lang-bash">
3401+$ echo $JUJU_RELATION_ID
3402+db:1
3403+
3404+$ relation-list
3405+mongodb/0
3406+mongodb/2
3407+mongodb/3
3408+</pre>
3409+
3410+<p>Show all remote units in a specific relation:</p>
3411+<pre class="prettyprint lang-bash">
3412+echo $JUJU_RELATION_ID
3413+relation-list -r website:2
3414+
3415+haproxy/0
3416+</pre>
3417+
3418+</section>
3419+
3420+<section id="relation-ids">
3421+<h3>relation-ids</h3>
3422+
3423+<p><code>relation-ids</code> accepts a single argument which, in a relation
3424+hook, defaults to the name of the current relation.</p>
3425+<p>Examples:</p>
3426+<p>Show all relations like the current one:</p>
3427+<pre class="prettyprint lang-bash">
3428+$ echo $JUJU_RELATION
3429+server
3430+$ relation-ids
3431+server:1
3432+server:7
3433+server:9
3434+</pre>
3435+<p>Show all relations with the given name:</p>
3436+<pre class="prettyprint lang-bash">
3437+$ echo $JUJU_RELATION_ID
3438+
3439+$ relation-ids reverseproxy
3440+reverseproxy:3
3441+</pre>
3442+
3443+<p>Note again that all commands that produce output accept <code>--format json</code>
3444+and <code>--format yaml</code>, and you may consider it smarter to use those for
3445+clarity's sake than to depend on the default <code>smart</code> format.
3446+</section>
3447+</article>
3448+<!--Postamble-->
3449+ </div>
3450+ </div>
3451+ </section>
3452+ </div>
3453+</div>
3454+<!--End-Postamble-->
3455+<!--Footer-->
3456+ <footer class="global clearfix" role="contentinfo">
3457+ <nav role="navigation">
3458+ <div class="footer-a">
3459+ <div class="clearfix">
3460+ <ul>
3461+ <li>
3462+ <h2><a href="/">Juju</a></h2>
3463+ <ul>
3464+ <li><a href="/charms">Charms</a></li>
3465+ <li><a href="/features">Features</a></li>
3466+ <li><a href="/deployment">Deployment</a></li>
3467+ </ul>
3468+ </li>
3469+ <li>
3470+ <h2><a href="/resources">Resources</a></h2>
3471+ <ul>
3472+ <li><a href="/resources/juju-overview/">Overview</a></li>
3473+ <li><a href="/docs/">Documentation</a></li>
3474+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
3475+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
3476+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
3477+ <li><a href="/resources/videos/">Videos</a></li>
3478+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
3479+ </ul>
3480+ </li>
3481+ <li>
3482+ <h2><a href="/community">Community</a></h2>
3483+ <ul>
3484+ <li><a href="/community/blog/">Juju Blog</a></li>
3485+ <li><a href="/events/">Events</a></li>
3486+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
3487+ <li><a href="/community/charmers/">Charmers</a></li>
3488+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
3489+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
3490+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
3491+ </ul>
3492+ </li>
3493+ <li>
3494+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
3495+ <ul>
3496+ <li><a href="https://jujucharms.com/">Charm store</a></li>
3497+ <li><a href="/download/">Download Juju</a></li>
3498+ </ul>
3499+ </li>
3500+ </ul>
3501+ </div>
3502+ </div>
3503+ </nav>
3504+ <div class="legal clearfix">
3505+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
3506+ </div>
3507+ </footer>
3508+
3509+<!--End-Footer-->
3510+<!--Scripts-->
3511+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
3512+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
3513+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
3514+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
3515+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
3516+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
3517+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
3518+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
3519+ <!-- google analytics -->
3520+ <script>
3521+ var _gaq = _gaq || [];
3522+ _gaq.push(['_setAccount', 'UA-1018242-41']);
3523+ _gaq.push(['_trackPageview']);
3524+
3525+ (function() {
3526+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
3527+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
3528+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
3529+ })();
3530+ </script>
3531+<!--End-Scripts-->
3532+
3533+</body></html>
3534+
3535
3536=== added file 'htmldocs/authors-hook-errors.html'
3537--- htmldocs/authors-hook-errors.html 1970-01-01 00:00:00 +0000
3538+++ htmldocs/authors-hook-errors.html 2013-10-09 20:07:46 +0000
3539@@ -0,0 +1,194 @@
3540+<!DOCTYPE html>
3541+<html>
3542+ <head>
3543+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
3544+ <title>Juju Documentation - Hook Errors</title>
3545+ <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' />
3546+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" />
3547+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" />
3548+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" />
3549+ <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" />
3550+ <link rel='stylesheet' id='stacktack-css' href='//juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2' type='text/css' media='all' />
3551+ <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/>
3552+
3553+ <!--[if lt IE 9]>
3554+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
3555+ <![endif]-->
3556+</head>
3557+ <body class="resources">
3558+ <header class="global clearfix" role="banner">
3559+ <div class="header-navigation">
3560+ <div>
3561+ <nav role="navigation">
3562+ <ul>
3563+ <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li>
3564+ <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li>
3565+ <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
3566+ <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li>
3567+ <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li>
3568+ <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li>
3569+ <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li>
3570+ <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li>
3571+ <li>
3572+ <form id="form-search" method="get" action="https://juju.ubuntu.com/">
3573+ <fieldset>
3574+ <input id="input-search" type="text" name="s" value="Search" />
3575+ </fieldset>
3576+ </form>
3577+ </li>
3578+ </ul>
3579+ </nav>
3580+ </div>
3581+ </div>
3582+ <div class="header-content">
3583+ <div class="clearfix">
3584+ <img src="https://juju.ubuntu.com/wp-content/themes/juju-website/img/arrow-nav.png" width="9" height="5" style="left:455px; display: block;" class="arrow-nav">
3585+ <div class="header-navigation-secondary"></div>
3586+ <div class="header-image"></div>
3587+ <h1>Resources</h1>
3588+ <h2>A collection of some of the most important online references for Juju users and developers.</h2>
3589+ </div>
3590+ </div>
3591+</header>
3592+
3593+ <section id="content" class="container-12">
3594+ <div class="grid-12 doc-container">
3595+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
3596+ <div class="grid-9 doc-content">
3597+ <article>
3598+
3599+
3600+<section id="hook-errors">
3601+<h1>Hook errors</h1>
3602+
3603+<p>If any of your hooks returns a non-zero exit code, juju will stop managing the
3604+unit directly and will wait for user intervention. This is a Bad Thing, and you
3605+should make every effort to avoid it, because the average user may not be in a
3606+position to diagnose the fault with any great degree of sophistication.</p>
3607+
3608+<p>So, in general, you should write your hooks as robustly as possible: if an
3609+operation suffers a possibly-transient failure, it's wise to wait a moment and
3610+retry a couple of times, to avoid needlessly bothering the user with a decision
3611+or call to action that they're not necessarily equipped to make.</p>
3612+
3613+<p>However, you will no doubt encounter errors on occasion -- in particular, if
3614+the unit agent is aborted while it's running a hook, it'll set an error status
3615+for that hook when it comes back up. You will in that case have to deal with
3616+users' potentially underinformed responses to those errors.</p>
3617+</section>
3618+
3619+<section id="error-status">
3620+<h2>Error status</h2>
3621+
3622+<p>When a unit agent sets an error status, it stops running hooks and relinquishes
3623+control over the charm directory. This means that it's generally safe to
3624+<code>juju ssh</code> into the unit and use it as though you were the sole
3625+administrator; juju will only take back control of the directory when explicitly
3626+requested, in response to either <code>juju resolved</code> or
3627+<code>juju upgrade-charm --force</code>.
3628+<ul>
3629+ <li><code>juju resolved</code> causes the unit to unblock itself and continue
3630+ as though the hook had completed successfuly. The ideal charm will be aware of
3631+ this possibility and will therefore trust information from its
3632+ <a href="./authors-hook-environment.html">environment</a> to be more recent and
3633+ correct than anything it may have previously have recorded in the local
3634+ <a href="./authors-charm-contents.html">charm directory</a>.</li>
3635+
3636+ <li><code>juju resolved --retry</code> reverts the charm directory's contents
3637+ to whatever they were at the start of the failed hook, and runs the hook again
3638+ exactly as before. This, in combination with the
3639+ <a href="./authors-hook-debug.html">debug-hooks</a> command, is your main entry
3640+ point for investigating an error in detail. If the hook fails again when retried,
3641+ it will set an error as before and wait again for user resolution.</li>
3642+
3643+ <li><code>juju upgrade-charm --force</code> merges into the charm directory the
3644+ contents of the newer charm version, and continues blocking in the original hook
3645+ error state. Each time a new upgrade is forced, the charm directory is rolled
3646+ back to the state from which it was originally upgraded before proceeding; this
3647+ means that a forced upgrade back to the original charm will always be a no-op,
3648+ regardless of what other upgrade attempts have been made in the interim.</li>
3649+</ul>
3650+<p>Once you have issued one of the above commands, the charm directory should
3651+once again be treated as inaccessible.</p>
3652+</section>
3653+
3654+<section id="upgrade-errors">
3655+<h2>Charm upgrade errors</h2>
3656+
3657+<p>Finally, there's another reason a unit might set an error status: a
3658+<a href="./authors-charm-upgrades.html">charm upgrade</a> conflict, which
3659+should never happen except during development.</p>
3660+
3661+<p>They can be resolved either by forcing an upgrade to a different charm version,
3662+or by manually resolving the git conflicts in the charm directory and running
3663+<code>juju resolved</code> to cause the unit agent to continue.</p>
3664+</section>
3665+
3666+
3667+ </article>
3668+ </div>
3669+ </div>
3670+ </section>
3671+ <div class="shadow"></div>
3672+ <footer class="global clearfix" role="contentinfo">
3673+ <div class="row">
3674+ <div class="inner-wrapper">
3675+ <nav role="navigation" class="clearfix">
3676+ <ul class="footer-a">
3677+ <li class="grid-3 first-col">
3678+ <h4><a href="/get-started">Get started</a></h4>
3679+ <ul>
3680+ <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li>
3681+ <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li>
3682+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li>
3683+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li>
3684+ <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li>
3685+ <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li>
3686+ </ul>
3687+ </li>
3688+ <li class="grid-3">
3689+ <h4><a href="/resources">Resources</a></h4>
3690+ <ul>
3691+ <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li>
3692+ <li><a href="/resources/videos/">Videos</a></li>
3693+ <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li>
3694+ </ul>
3695+ </li>
3696+ <li class="grid-3">
3697+ <h4><a href="/community">Community</a></h4>
3698+ <ul>
3699+ <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li>
3700+ <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li>
3701+ <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li>
3702+ <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li>
3703+ <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li>
3704+ <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li>
3705+ </ul>
3706+ </li>
3707+ <li class="grid-3 last-col">
3708+ <h4><a href="https://launchpad.net/juju">Code</a></h4>
3709+ <ul>
3710+ <li><a href="https://launchpad.net/juju-core">Juju Core</a></li>
3711+ <li><a href="https://launchpad.net/charms">Charms</a></li>
3712+ </ul>
3713+ </li>
3714+ </ul>
3715+ </nav>
3716+ </div>
3717+ </div>
3718+ <div class="row no-border">
3719+ <div class="legal inner-wrapper">
3720+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p>
3721+ <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p>
3722+ </div>
3723+ </div>
3724+</footer>
3725+
3726+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
3727+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
3728+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
3729+ <script type="text/javascript" src="js/main.js"></script>
3730+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
3731+ </body>
3732+</html>
3733+
3734
3735=== added file 'htmldocs/authors-hook-kinds.html'
3736--- htmldocs/authors-hook-kinds.html 1970-01-01 00:00:00 +0000
3737+++ htmldocs/authors-hook-kinds.html 2013-10-09 20:07:46 +0000
3738@@ -0,0 +1,402 @@
3739+<!DOCTYPE html>
3740+<html>
3741+<!--Head-->
3742+ <head>
3743+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
3744+ <title>Juju Documentation</title>
3745+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
3746+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
3747+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
3748+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
3749+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
3750+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
3751+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
3752+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
3753+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
3754+ <link href="./css/main.css" rel="stylesheet" type="text/css">
3755+
3756+ <!--[if lt IE 9]>
3757+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
3758+ <![endif]-->
3759+ </head>
3760+<!--End-Head-->
3761+
3762+
3763+ <body class="resources">
3764+<!--Header-->
3765+
3766+ <header class="banner global" role="banner">
3767+ <nav role="navigation" class="nav-primary nav-right">
3768+ <div class="logo">
3769+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
3770+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
3771+ <span>Juju</span>
3772+ </a>
3773+ </div>
3774+ <ul>
3775+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
3776+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
3777+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
3778+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
3779+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
3780+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
3781+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
3782+ </ul>
3783+ <div id="box-search">
3784+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
3785+ <label class="off-left" for="s">Search:</label>
3786+ <input class="form-text" type="text" value="" name="s" id="s" />
3787+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
3788+ </form>
3789+ </div>
3790+ </nav>
3791+ </header>
3792+<!--End-Header-->
3793+<!--Preamble-->
3794+<div class="wrapper">
3795+ <div id="main-content" class="inner-wrapper" role="main">
3796+ <div class="row no-border">
3797+ <div class="header-navigation-secondary"></div>
3798+ <h2 class="pagetitle">Juju documentation</h2>
3799+ </div>
3800+ <section id="content" class="container-12">
3801+ <div class="grid-12 doc-container">
3802+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
3803+ <div class="grid-9 doc-content">
3804+<!--End-Preamble-->
3805+<article>
3806+<section id="charm-hooks">
3807+<h1>Charm hooks</h1>
3808+
3809+<p>A service unit's direct action is entirely defined by its charm's hooks. Hooks
3810+are executable files in a charm's <code>hooks</code> directory; hooks with particular
3811+names (see below) will be invoked by the juju unit agent at particular times, and thereby cause
3812+changes to the world.</p>
3813+
3814+<p>Whenever a hook-worthy event takes place, the unit agent first checks whether
3815+that hook is being <a href="./authors-hook-debug.html">debugged</a>, and if so
3816+hands over control to the user. Otherwise, it tries to find a hook with precisely
3817+the right name. If the hook doesn't exist, the agent continues without complaint;
3818+if it does, it is invoked without arguments in a specific
3819+<a href="./authors-hook-environment.html">environment</a>, and its output is written
3820+to the unit agent's log. If it returns a non-zero exit code, the agent enters an
3821+<a href="./authors-hook-errors.html">error state</a> and awaits user intervention.</p>
3822+
3823+<p>The agent will also enter an error state if the unit agent process is aborted
3824+during hook execution.</p>
3825+
3826+<p>There are two types of hooks, described in more detail in the following sections.</p>
3827+
3828+<p class = "note"><strong>Note: </strong>None of the unit or relation hooks are required; if you don't implement a hook,
3829+it just doesn't get run. When a hook event occurs, Juju will look for the corresponding hook file to execute, but if it finds none, will continue running without generating an error.</p>
3830+</section>
3831+
3832+<section id="unit-hooks">
3833+<h2>Unit hooks</h2>
3834+
3835+<p>There are 5 &quot;unit hooks&quot; with predefined names that can be implemented
3836+by any charm:</p>
3837+<ul>
3838+ <li>install</li>
3839+ <li>config-changed</li>
3840+ <li>start</li>
3841+ <li>upgrade-charm</li>
3842+ <li>stop</li>
3843+</ul>
3844+
3845+<p>For every relation defined by a charm, an additional 4 &quot;relation hooks&quot;
3846+can be implemented, named after the charm relation:</p>
3847+<ul>
3848+ <li>&lt;name&gt;-relation-joined</li>
3849+ <li>&lt;name&gt;-relation-changed</li>
3850+ <li>&lt;name&gt;-relation-departed</li>
3851+ <li>&lt;name&gt;-relation-broken</li>
3852+</ul>
3853+<p>None of the unit or relation hooks are required; if you don't implement a hook,
3854+it just doesn't get run, except when debugging. When a hook event occurs, Juju will look for the corresponding hook file to execute, but if it finds none, will continue running without generating an error.</p>
3855+</section>
3856+
3857+<p>The unit hooks are run under the following circumstances.</p>
3858+</section>
3859+
3860+<section id="hook-install">
3861+<h3>install</h3>
3862+
3863+<p><code>install</code> runs just once, before any other hook. It should be used to
3864+perform one-time setup operations only.</p>
3865+</section>
3866+
3867+<section id="hook-config-changed">
3868+<h3>config-changed</h3>
3869+
3870+<p><code>config-changed</code> runs in several different situations.</p>
3871+<ul>
3872+ <li>immediately after "install"</li>
3873+ <li>immediately after "upgrade-charm"</li>
3874+ <li>at least once when the unit agent is restarted (but, if the unit is in
3875+ an <a href="./authors-hook-errors.html">error state</a>, it won't be run
3876+ until after the error state is cleared).</li>
3877+</ul>
3878+<p>It cannot assume that the software has already been started; it should not
3879+start stopped software, but should (if appropriate) restart running software
3880+to take configuration changes into account.</p>
3881+</section>
3882+
3883+<section id="hook-start">
3884+<h3>start</h3>
3885+<p><code>start</code> runs immediately after the first <code>config-changed</code>
3886+hook. It should be used to ensure the charm's software is running. Note that the
3887+charm's software should be configured so as to persist through reboots without further
3888+intervention on juju's part.
3889+</section>
3890+
3891+<section id="hook-upgrade-charm">
3892+<h3>upgrade-charm</h3>
3893+
3894+<p><code>upgrade-charm</code> runs immediately after any
3895+<a href="./authors-charm-upgrades.html">upgrade</a> operation that does <em>not</em>
3896+itself interrupt an existing <a href="./authors-hook-errors.html">error state.</a>. It
3897+should be used to reconcile local state written by some other version of the charm into
3898+whatever form it needs to take to be manipulated by the current version.</p>
3899+
3900+<p>While the forced upgrade functionality is intended as a developer tool, and is
3901+not generally suitable for end users, it's somewhat optimistic to depend on the
3902+functionality never being abused. In light of this, if you need to run an
3903+<code>upgrade-charm</code> hook before your other hooks will work correctly,
3904+it may be wise to preface all your other hooks with a quick call to your
3905+(idempotent)<code>upgrade-charm</code>.</p>
3906+</section>
3907+
3908+<section id="hook-stop">
3909+<h3>stop</h3>
3910+
3911+<p><code>stop</code> runs immediately before the end of the unit's destruction
3912+sequence. It should be used to ensure that the charm's software is not running, and
3913+will not start again on reboot.</p>
3914+</section>
3915+
3916+<section id="relation-hooks">
3917+<h2>Relation hooks</h2>
3918+
3919+<p>Units will only participate in relations after they're been started, and before
3920+they've been stopped. Within that time window, the unit may participate in several
3921+different relations at a time, <em>including</em> multiple relations with the
3922+same name.</p>
3923+
3924+<p>To illustrate, consider a database service that will be used by multiple client
3925+services. Units of a single client service will surely want to connect to, and
3926+use, the same database; but if units of another client service were to use that
3927+same database, the consequences could be catastrophic for all concerned.</p>
3928+
3929+<p>If juju respected the <code>limit</code> field in relation
3930+<a href="./authors-charm-metadata.html">metadata</a>, it would be possible
3931+to work around this, but it's not a high-priority
3932+<a href="https://bugs.launchpad.net/bugs/1089297">bug</a>: most provider services
3933+<em>should</em> be able to handle multiple requirers anyway; and most requirers will
3934+only be connected to one provider anyway.</p>
3935+
3936+<p>When a unit running a given charm participates in a given relation, it runs at
3937+least three hooks for every remote unit it becomes aware of in that relation.</p>
3938+</section>
3939+
3940+<section id="hook-relation-joined">
3941+<h3>&lt;name&gt;-relation-joined</h3>
3942+
3943+<p><code>&lt;name&gt;-relation-joined</code> is run once only, when that remote
3944+unit is first observed by the unit. It should be used to <code>relation-set</code> any
3945+local unit settings that can be determined using no more than the name of the joining
3946+unit and the remote <code>private-address</code> setting, which is always available
3947+when the relation is created and is by convention not deleted.</p>
3948+
3949+<p>You should not depend upon any other relation settings in the -joined hook
3950+because they're not guaranteed to be present; if you need more information
3951+you should wait for a -changed hook that presents the right information.</p>
3952+</section>
3953+
3954+<section id="hook-relation-changed">
3955+<h3>&lt;name&gt;-relation-changed</h3>
3956+
3957+<p><code>&lt;name&gt;-relation-changed</code> is always run once, after -joined, and
3958+will subsequently be run whenever that remote unit changes its settings for the
3959+relation. It should be the <em>only</em> hook that <em>relies</em> upon remote relation
3960+settings from <code>relation-get</code>, and it should <em>not</em> error if the
3961+settings are incomplete: you can guarantee that when the remote unit changes its
3962+settings, the hook will be run again.</p>
3963+
3964+<p>The settings that you can get, and that you should set, are determined by
3965+the relation's <a href="./authors-charm-interfaces.html">interface</a>.</p>
3966+</section>
3967+
3968+<section id="hook-relation-departed">
3969+<h3>&lt;name&gt;-relation-departed</h3>
3970+
3971+<p><code>&lt;name&gt;-relation-departed</code> is run once only, when the remote unit
3972+is known to be leaving the relation; it will only run once at least one -changed has
3973+been run, and after -departed has run, no further -changeds will be run. This should
3974+be used to remove all references to the remote unit, because there's no guarantee that
3975+it's still part of the system; it's perfectly probable (although not guaranteed) that
3976+the system running that unit has already shut down.</p>
3977+
3978+<p>When a unit's own participation in a relation is known to be ending, the unit
3979+agent continues to uphold the ordering guarantees above; but within those
3980+constraints, it will run the fewest possible hooks to notify the charm of the
3981+departure of each individual remote unit.</p>
3982+
3983+<p>Once all necessary -departed hooks have been run for such a relation, the unit
3984+agent will run the final relation hook:</p>
3985+</section>
3986+
3987+<section id="hook-relation-broken">
3988+<h3>&lt;name&gt;-relation-broken</h3>
3989+
3990+<p><code>&lt;name&gt;-relation-broken</code> indicates that the current relation is
3991+no longer valid, and that the charm's software must be configured as though the
3992+relation had never existed. It will only be called after every necessary -departed
3993+hook has been run; if it's being executed, you can be sure that no remote units are
3994+currently known locally.</p>
3995+
3996+<p>It is important to note that the -broken hook might run even if no other units
3997+have ever joined the relation. This is not a bug: even if no remote units have ever
3998+joined, the fact of the unit's participation can be detected in other hooks via the
3999+<code>relation-ids</code> tool, and the -broken hook needs to execute to give the
4000+charm an opportunity to clean up any optimistically-generated configuration.</p>
4001+
4002+<p>And, again, it's important to internalise the fact that there may be multiple
4003+runtime relations in play with the same name, and that they're independent:
4004+one -broken hook does not mean that <em>every</em> such relation is broken.</p>
4005+</section>
4006+
4007+<section id="writing-hooks">
4008+<h2>Writing hooks</h2>
4009+
4010+<p>If you follow the <a href="./authors-charm-writing.html">tutorial</a>, you'll
4011+get a good sense of the basics. To fill out your knowledge, you'll want to study
4012+the hook <a href="./authors-hook-environment.html">environment and tools</a>, and
4013+to experiment with <a href="./authors-hook-debug.html">debug-hooks</a>.</p>
4014+
4015+<p>Independent of the nuts and bolts, though, good hooks display a number of
4016+useful high-level properties:</p>
4017+<ul>
4018+ <li>They are <em>idempotent</em>: that is to say that there should be no
4019+ observable difference between running a hook once, and running it N times
4020+ in a row. If this property does not hold, you are likely to be making your
4021+ own life unnecesarily difficult: apart from anything else, the average user's
4022+ most likely first response to a failed hook will be to try to run it again
4023+ (if they don't just skip it).</li>
4024+
4025+ <li>They are <em>easy to read</em> and understand. It's tempting to write a
4026+ single file that does everything, and which just calls different functions
4027+ internally depending on the value of <code>argv[0]</code>, and to symlink that
4028+ one file for every hook; but such structures quickly become unwieldy.<br />
4029+ The time taken to write a library, separate from the hooks, is very likely
4030+ to be well spent: it lets you write single hooks that are clear and focused,
4031+ and insulates the maintainer from irrelevant details.</li>
4032+
4033+ <li>Where possible, they reuse
4034+ <a href="https://launchpad.net/charm-tools">common code</a> already written to
4035+ ease or solve common use cases.</li>
4036+
4037+ <li>They do not return <a href="./authors-hook-errors.html">errors</a> unless
4038+ there is a good reason to believe that they cannot be resolved without user
4039+ intervention. Doing so is an admission of defeat: a user who sees your charm
4040+ returning an error state is unlikely to have the specific expertise necessary
4041+ to resolve it. If you have to return an error, please be sure to at least write
4042+ any context you can to the log before you do so.</li>
4043+
4044+ <li>They write only <em>very</em> sparingly to the
4045+ <a href="./authors-charm-contents.html">charm directory</a>.</li>
4046+</ul>
4047+
4048+<p>We recommend you also familiarize yourself with the
4049+<a href="./authors-charm-best-practice.html">best practices</a> and, if you
4050+plan to distribute your charm, the
4051+<a href="./authors-charm-policy.html">charm store policy</a>.</p>
4052+</section>
4053+ </article>
4054+<!--Postamble-->
4055+ </div>
4056+ </div>
4057+ </section>
4058+ </div>
4059+</div>
4060+<!--End-Postamble-->
4061+<!--Footer-->
4062+ <footer class="global clearfix" role="contentinfo">
4063+ <nav role="navigation">
4064+ <div class="footer-a">
4065+ <div class="clearfix">
4066+ <ul>
4067+ <li>
4068+ <h2><a href="/">Juju</a></h2>
4069+ <ul>
4070+ <li><a href="/charms">Charms</a></li>
4071+ <li><a href="/features">Features</a></li>
4072+ <li><a href="/deployment">Deployment</a></li>
4073+ </ul>
4074+ </li>
4075+ <li>
4076+ <h2><a href="/resources">Resources</a></h2>
4077+ <ul>
4078+ <li><a href="/resources/juju-overview/">Overview</a></li>
4079+ <li><a href="/docs/">Documentation</a></li>
4080+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
4081+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
4082+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
4083+ <li><a href="/resources/videos/">Videos</a></li>
4084+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
4085+ </ul>
4086+ </li>
4087+ <li>
4088+ <h2><a href="/community">Community</a></h2>
4089+ <ul>
4090+ <li><a href="/community/blog/">Juju Blog</a></li>
4091+ <li><a href="/events/">Events</a></li>
4092+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
4093+ <li><a href="/community/charmers/">Charmers</a></li>
4094+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
4095+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
4096+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
4097+ </ul>
4098+ </li>
4099+ <li>
4100+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
4101+ <ul>
4102+ <li><a href="https://jujucharms.com/">Charm store</a></li>
4103+ <li><a href="/download/">Download Juju</a></li>
4104+ </ul>
4105+ </li>
4106+ </ul>
4107+ </div>
4108+ </div>
4109+ </nav>
4110+ <div class="legal clearfix">
4111+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
4112+ </div>
4113+ </footer>
4114+
4115+<!--End-Footer-->
4116+<!--Scripts-->
4117+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
4118+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
4119+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
4120+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
4121+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
4122+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
4123+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
4124+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
4125+ <!-- google analytics -->
4126+ <script>
4127+ var _gaq = _gaq || [];
4128+ _gaq.push(['_setAccount', 'UA-1018242-41']);
4129+ _gaq.push(['_trackPageview']);
4130+
4131+ (function() {
4132+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
4133+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
4134+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
4135+ })();
4136+ </script>
4137+<!--End-Scripts-->
4138+
4139+
4140+</body></html>
4141
4142=== removed file 'htmldocs/authors-hooks.html'
4143--- htmldocs/authors-hooks.html 2013-09-27 14:53:30 +0000
4144+++ htmldocs/authors-hooks.html 1970-01-01 00:00:00 +0000
4145@@ -1,185 +0,0 @@
4146-<!DOCTYPE html>
4147-<html>
4148-<!--Head-->
4149- <head>
4150- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4151- <title>Juju Documentation</title>
4152- <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
4153- <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
4154- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
4155- <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
4156- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
4157- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
4158- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
4159- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
4160- <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
4161- <link href="./css/main.css" rel="stylesheet" type="text/css">
4162-
4163- <!--[if lt IE 9]>
4164- <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
4165- <![endif]-->
4166- </head>
4167-<!--End-Head-->
4168-
4169-
4170-
4171- <body class="resources">
4172-
4173-<!--Header-->
4174-
4175- <header class="banner global" role="banner">
4176- <nav role="navigation" class="nav-primary nav-right">
4177- <div class="logo">
4178- <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
4179- <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
4180- <span>Juju</span>
4181- </a>
4182- </div>
4183- <ul>
4184- <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
4185- <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
4186- <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
4187- <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
4188- <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
4189- <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
4190- <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
4191- </ul>
4192- <div id="box-search">
4193- <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
4194- <label class="off-left" for="s">Search:</label>
4195- <input class="form-text" type="text" value="" name="s" id="s" />
4196- <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
4197- </form>
4198- </div>
4199- </nav>
4200- </header>
4201-<!--End-Header-->
4202-<!--Preamble-->
4203-<div class="wrapper">
4204- <div id="main-content" class="inner-wrapper" role="main">
4205- <div class="row no-border">
4206- <div class="header-navigation-secondary"></div>
4207- <h2 class="pagetitle">Juju documentation</h2>
4208- </div>
4209- <section id="content" class="container-12">
4210- <div class="grid-12 doc-container">
4211- <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
4212- <div class="grid-9 doc-content">
4213-<!--End-Preamble-->
4214- <article>
4215- <section id ="hook-debugging">
4216- <h1>Hook debugging</h1>
4217-
4218- <p>An important facility in any distributed system is the ability to introspect the running system, and to debug it. Within juju the actions performed by the system are executing charm defined hooks. The <span class="pre">debug-log</span> cli provides for inspecting the total state of the system via capturing the logs of all agents and output of all hooks run by the system.</p>
4219- <p>To facilitate better debugging of hooks, the <tt class="docutils literal"><span class="pre">debug-hooks</span></tt> cli provides for interactive shell usage as a substitute for running a hook. This allows a charm author or system adminstrator the ability to interact with the system in a live environment and either develop or debug a hook.</p>
4220-
4221- <h2>How it works</h2>
4222- <p>When the juju user utilizes the hook debug command like so:</p>
4223- <pre>juju debug-hooks unit_name [hook_name]</pre>
4224-
4225- <p>juju is instructed to replace the execution of the hook from the charm of the respective service unit, and instead to execute it in a shell associated to a tmux session. If no hook name is given, then all hooks will be debugged in this fashion. Multiple hook names can also be specified on the command line. Shell regular expressions can also be utilized to specify hook names.</p>
4226- <p>The <tt class="docutils literal"><span class="pre">debug-hooks</span></tt> command line invocation will immediately connect to the remote machine of the remote unit and start a named shell connected to the same tmux session there.</p>
4227- <p>The native capabilities of tmux can be exploited to construct a full debug/development environment on the remote machine.</p>
4228- <p>When a debugged hook is executed a new named window will pop up in the tmux session with the hook shell started. The new window's title will match the hook name, and the shell environment will have all the juju environment variables in place, and all of the hook cli API may be utilized (relation-get, relation-set, relation-list, etc.).</p>
4229- <p>It's important to note that juju serializes hook execution, so while the shell is active, no other hooks will be executed on the unit. Once the experimentation is done, the user must stop the hook by exiting the shell session. At this point the system is then free to execute additional hooks.</p>
4230- <p>It's important to note that any state changes performed while in the hook window via relation-set are buffered till the hook is done executing, in the same way performed for all the relation hooks when running outside of a debug session.</p>
4231- <p>The debug-hooks can be used to debug the same hook being invoked multiple times as long as the user has not closed the debug screen session.</p>
4232- <p>The user can exit debug mode by exiting the tmux session (e.g. exiting all shells). The unit will then resume its normal processing.</p>
4233-
4234- <h2>Internals</h2>
4235- <p>Internally the <tt class="docutils literal"><span class="pre">debug-hooks</span></tt> cli begins by verifying its arguments, namely the unit exists, and the named hook is valid for the charm. After that it modifies the zookeeper state of the unit node, setting a flag noting the hook to debug. It then establishes an ssh connection to the machine and executes the tmux command.</p>
4236- <p>The unit-agent will establish a watch on its own debug settings, on changes introspecting the debug flag, and pass any named hook values down to the hook executor, which will construct debug hook scripts on the fly for matching hooks. These debug hook scripts are responsible for connecting to tmux and monitoring the execution of the hook therein.</p>
4237- <p>Special care will be taken to ensure the viability of the tmux session and that debug mode is active before creating the interactive hook window in tmux.</p>
4238- </section>
4239- </article>
4240- </div>
4241- </div>
4242- </section>
4243-<!--Postamble-->
4244- </div>
4245- </div>
4246- </section>
4247- </div>
4248-</div>
4249-<!--End-Postamble-->
4250-<!--Footer-->
4251- <footer class="global clearfix" role="contentinfo">
4252- <nav role="navigation">
4253- <div class="footer-a">
4254- <div class="clearfix">
4255- <ul>
4256- <li>
4257- <h2><a href="/">Juju</a></h2>
4258- <ul>
4259- <li><a href="/charms">Charms</a></li>
4260- <li><a href="/features">Features</a></li>
4261- <li><a href="/deployment">Deployment</a></li>
4262- </ul>
4263- </li>
4264- <li>
4265- <h2><a href="/resources">Resources</a></h2>
4266- <ul>
4267- <li><a href="/resources/juju-overview/">Overview</a></li>
4268- <li><a href="/docs/">Documentation</a></li>
4269- <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
4270- <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
4271- <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
4272- <li><a href="/resources/videos/">Videos</a></li>
4273- <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
4274- </ul>
4275- </li>
4276- <li>
4277- <h2><a href="/community">Community</a></h2>
4278- <ul>
4279- <li><a href="/community/blog/">Juju Blog</a></li>
4280- <li><a href="/events/">Events</a></li>
4281- <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
4282- <li><a href="/community/charmers/">Charmers</a></li>
4283- <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
4284- <li><a href="/docs/contributing.html">Help with documentation</a></li>
4285- <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
4286- </ul>
4287- </li>
4288- <li>
4289- <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
4290- <ul>
4291- <li><a href="https://jujucharms.com/">Charm store</a></li>
4292- <li><a href="/download/">Download Juju</a></li>
4293- </ul>
4294- </li>
4295- </ul>
4296- </div>
4297- </div>
4298- </nav>
4299- <div class="legal clearfix">
4300- <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
4301- </div>
4302- </footer>
4303-
4304-<!--End-Footer-->
4305-
4306-<!--Scripts-->
4307- <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
4308- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
4309- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
4310- <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
4311- <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
4312- <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
4313- <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
4314- <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
4315- <!-- google analytics -->
4316- <script>
4317- var _gaq = _gaq || [];
4318- _gaq.push(['_setAccount', 'UA-1018242-41']);
4319- _gaq.push(['_trackPageview']);
4320-
4321- (function() {
4322- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
4323- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
4324- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
4325- })();
4326- </script>
4327-<!--End-Scripts-->
4328-
4329-
4330-</body></html>
4331
4332=== modified file 'htmldocs/authors-implicit-relations.html'
4333--- htmldocs/authors-implicit-relations.html 2013-09-27 14:53:30 +0000
4334+++ htmldocs/authors-implicit-relations.html 2013-10-09 20:07:46 +0000
4335@@ -23,6 +23,8 @@
4336
4337
4338
4339+
4340+
4341 <body class="resources">
4342
4343 <!--Header-->
4344@@ -186,4 +188,6 @@
4345 <!--End-Scripts-->
4346
4347
4348+
4349+
4350 </body></html>
4351
4352=== modified file 'htmldocs/authors-interfaces.html'
4353--- htmldocs/authors-interfaces.html 2013-09-27 14:53:30 +0000
4354+++ htmldocs/authors-interfaces.html 2013-10-09 20:07:46 +0000
4355@@ -23,6 +23,8 @@
4356
4357
4358
4359+
4360+
4361 <body class="resources">
4362
4363 <!--Header-->
4364@@ -362,4 +364,6 @@
4365 <!--End-Scripts-->
4366
4367
4368+
4369+
4370 </body></html>
4371
4372=== modified file 'htmldocs/authors-intro.html'
4373--- htmldocs/authors-intro.html 2013-09-27 14:53:30 +0000
4374+++ htmldocs/authors-intro.html 2013-10-09 20:07:46 +0000
4375@@ -21,6 +21,8 @@
4376 </head>
4377 <!--End-Head-->
4378
4379+
4380+
4381 <body class="resources">
4382 <!--Header-->
4383
4384@@ -67,7 +69,7 @@
4385 <section id='author-intro'>
4386 <h1>Becoming a charm author</h1>
4387 <p>Juju makes deploying cloud services spectacularly easy. One of the key components of the Juju ecosystem that makes this possible is the wealth of quality, reliable charms enabling users to quickly and reliably deploy all sorts of software, from simple web-based forums to a complete OpenStack install.</p>
4388- <p>There are however times when the particular service you want to use doesn't have a charm available - maybe it is your own project? Or perhaps the existing charm for a service doesn't work in precisely the way you want. Whatever your reasons for writing a charm, this section of the documentation will guide you through the process. You might want to start by looking at <a href="authors-charm-anatomy.html">the anatomy of a charm</a>, which breaks down and explains the different components that go into making a charm. Or you may want to dive right in with the <a href="authors-charm-writing.html">walkthrough for writing an example charm</a>.</p>
4389+ <p>There are however times when the particular service you want to use doesn't have a charm available - maybe it is your own project? Or perhaps the existing charm for a service doesn't work in precisely the way you want. Whatever your reasons for writing a charm, this section of the documentation will guide you through the process. You might want to start by looking at <a href="authors-charm-anatomy.html">what makes a charm</a>, which breaks down and explains the different components that go into making a charm. Or you may want to dive right in with the <a href="authors-charm-writing.html">walkthrough for writing an example charm</a>.</p>
4390 </article>
4391 <!--Postamble-->
4392 </div>
4393@@ -154,4 +156,6 @@
4394 </script>
4395 <!--End-Scripts-->
4396
4397+
4398+
4399 </body></html>
4400
4401=== added file 'htmldocs/authors-relations-in-depth.html'
4402--- htmldocs/authors-relations-in-depth.html 1970-01-01 00:00:00 +0000
4403+++ htmldocs/authors-relations-in-depth.html 2013-10-09 20:07:46 +0000
4404@@ -0,0 +1,187 @@
4405+<!DOCTYPE html>
4406+<html>
4407+<!--Head-->
4408+ <head>
4409+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4410+ <title>Juju Documentation</title>
4411+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
4412+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
4413+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
4414+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
4415+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
4416+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
4417+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
4418+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
4419+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
4420+ <link href="./css/main.css" rel="stylesheet" type="text/css">
4421+
4422+ <!--[if lt IE 9]>
4423+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
4424+ <![endif]-->
4425+ </head>
4426+<!--End-Head-->
4427+
4428+ <body class="resources">
4429+<!--Header-->
4430+
4431+ <header class="banner global" role="banner">
4432+ <nav role="navigation" class="nav-primary nav-right">
4433+ <div class="logo">
4434+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
4435+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
4436+ <span>Juju</span>
4437+ </a>
4438+ </div>
4439+ <ul>
4440+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
4441+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
4442+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
4443+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
4444+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
4445+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
4446+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
4447+ </ul>
4448+ <div id="box-search">
4449+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
4450+ <label class="off-left" for="s">Search:</label>
4451+ <input class="form-text" type="text" value="" name="s" id="s" />
4452+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
4453+ </form>
4454+ </div>
4455+ </nav>
4456+ </header>
4457+<!--End-Header-->
4458+<!--Preamble-->
4459+<div class="wrapper">
4460+ <div id="main-content" class="inner-wrapper" role="main">
4461+ <div class="row no-border">
4462+ <div class="header-navigation-secondary"></div>
4463+ <h2 class="pagetitle">Juju documentation</h2>
4464+ </div>
4465+ <section id="content" class="container-12">
4466+ <div class="grid-12 doc-container">
4467+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
4468+ <div class="grid-9 doc-content">
4469+<!--End-Preamble-->
4470+<article>
4471+ <section id="relations-in-depth">
4472+ <h1>Relations in depth</h1>
4473+
4474+ <p>A unit's <code>scope</code> consists of the group of units that are transitively connected to that unit within a particular relation. So, for a globally-scoped relation, that means every unit of each service in the relation; for a container-scoped relation, it means only those sets of units which are deployed alongside one another. That is to say: a globally-scoped relation has a single unit scope, whilst a container-scoped relation has one for each principal unit.</p>
4475+ <p>When a unit becomes aware that it is a member of a relation, its only self- directed action is to <code>join</code> its scope within that relation. This involves two steps:</p>
4476+ <ul>
4477+ <li>Write initial relation settings (just one value, <code>private-address</code>), to ensure that they will be available to observers before they're triggered by the next step;</li>
4478+ <li>Signal its existence, and role in the relation, to the rest of the system.</li>
4479+ </ul>
4480+ <p>The unit then starts observing and reacting to any other units in its scope which are playing a role in which it is interested. To be specific:</p>
4481+ <ul>
4482+ <li>Each provider unit observes every requirer unit</li>
4483+ <li>Each requirer unit observes every provider unit</li>
4484+ <li>Each peer unit observes every other peer unit</li>
4485+ </ul>
4486+ <p>Now, suppose that some unit as the very first unit to join the relation; and let's say it's a requirer. No provider units are present, so no hooks will fire. But, when a provider unit joins the relation, the requirer and provider become aware of each other almost simultaneously. (Similarly, the first two units in a peer relation become aware of each other almost simultaneously.)</p>
4487+ <p>So, concurrently, the units on each side of the relation run their relation-joined and relation-changed hooks with respect to their counterpart. The intent is that they communicate appropriate information to each other to set up some sort of connection, by using the relation-set and relation-get hook tools; but neither unit is safe to assume that any particular setting has yet been set by its counterpart.</p>
4488+ <p>This sounds kinda tricky to deal with, but merely requires suitable respect for the relation-get tool: it is important to realise that relation-get is never <em>guaranteed</em> to contain any values at all, because we have decided that it's perfectly legitimate for a unit to delete its own private-address value. But in normal circumstances, it's reasonable to treat <code>private-address</code> as guaranteed.</p>
4489+ <p>In one specific kind of hook, this is easy to deal with. A relation-changed hook can always exit without error when the current remote unit is missing data, because the hook is guaranteed to be run again when that data changes -- and, assuming the remote unit is running a charm that agrees on how to implement the interface, the data <em>will</em> change and the hook <em>will</em> be run again.</p>
4490+ <p>In <em>all</em> other cases -- unit hooks, relation hooks for a different relation, relation hooks for a different remote unit in the same relation, and even relation hooks other than -changed for the <em>same</em> remote unit -- there is no such guarantee. These hooks all run on their own schedule, and there is no reason to expect them to be re-run on a predictable schedule, or in some cases ever again.</p>
4491+ <p>This means that all such hooks need to be able to handle missing relation data, and to complete successfully; they mustn't fail, because the user is powerless to resolve the situation, and they can't even wait for state to change, because they all see their own sandboxed composite snapshot of fairly-recent state, which never changes.</p>
4492+ <p>So, outside a vey narrow range of circumstances, relation-get should be treated with particular care. The corresponding advice for relation-set is very simple by comparison: relation-set should be called early and often. Because the unit agent serializes hook execution, there is never any danger of concurrent changes to the data, and so a null setting change can be safely ignored, and will not cause other units to react.</p>
4493+ </section>
4494+
4495+ <section id="relations-in-depth">
4496+ <h2 id="departing-relations">Departing relations</h2>
4497+ <p>A unit will depart a relation when either the relation or the unit itself is marked for termination. In either case, it follows the same sequence:</p>
4498+ <ul>
4499+ <li>For every known related unit -- those which have joined and not yet departed -- run the relation-departed hook.</li>
4500+ <li>Run the relation-broken hook.</li>
4501+ <li><code>depart</code> from its scope in the relation.</li>
4502+ </ul>
4503+ <p>The unit's eventual departure from its scope will in turn be detected by units of the related service (if they have not already inferred its imminent departure by other means) and cause them to run relation-departed hooks. A unit's relation settings persist beyond its own departure from the relation; the final unit to depart a relation marked for termination is responsible for destroying the relation and all associated data.</p>
4504+ </section>
4505+</article>
4506+<!--Postamble-->
4507+ </div>
4508+ </div>
4509+ </section>
4510+ </div>
4511+</div>
4512+<!--End-Postamble-->
4513+<!--Footer-->
4514+ <footer class="global clearfix" role="contentinfo">
4515+ <nav role="navigation">
4516+ <div class="footer-a">
4517+ <div class="clearfix">
4518+ <ul>
4519+ <li>
4520+ <h2><a href="/">Juju</a></h2>
4521+ <ul>
4522+ <li><a href="/charms">Charms</a></li>
4523+ <li><a href="/features">Features</a></li>
4524+ <li><a href="/deployment">Deployment</a></li>
4525+ </ul>
4526+ </li>
4527+ <li>
4528+ <h2><a href="/resources">Resources</a></h2>
4529+ <ul>
4530+ <li><a href="/resources/juju-overview/">Overview</a></li>
4531+ <li><a href="/docs/">Documentation</a></li>
4532+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
4533+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
4534+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
4535+ <li><a href="/resources/videos/">Videos</a></li>
4536+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
4537+ </ul>
4538+ </li>
4539+ <li>
4540+ <h2><a href="/community">Community</a></h2>
4541+ <ul>
4542+ <li><a href="/community/blog/">Juju Blog</a></li>
4543+ <li><a href="/events/">Events</a></li>
4544+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
4545+ <li><a href="/community/charmers/">Charmers</a></li>
4546+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
4547+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
4548+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
4549+ </ul>
4550+ </li>
4551+ <li>
4552+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
4553+ <ul>
4554+ <li><a href="https://jujucharms.com/">Charm store</a></li>
4555+ <li><a href="/download/">Download Juju</a></li>
4556+ </ul>
4557+ </li>
4558+ </ul>
4559+ </div>
4560+ </div>
4561+ </nav>
4562+ <div class="legal clearfix">
4563+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
4564+ </div>
4565+ </footer>
4566+
4567+<!--End-Footer-->
4568+<!--Scripts-->
4569+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
4570+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
4571+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
4572+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
4573+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
4574+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
4575+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
4576+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
4577+ <!-- google analytics -->
4578+ <script>
4579+ var _gaq = _gaq || [];
4580+ _gaq.push(['_setAccount', 'UA-1018242-41']);
4581+ _gaq.push(['_trackPageview']);
4582+
4583+ (function() {
4584+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
4585+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
4586+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
4587+ })();
4588+ </script>
4589+<!--End-Scripts-->
4590+
4591+</body></html>
4592
4593=== added file 'htmldocs/authors-service-config.html'
4594--- htmldocs/authors-service-config.html 1970-01-01 00:00:00 +0000
4595+++ htmldocs/authors-service-config.html 2013-10-09 20:07:46 +0000
4596@@ -0,0 +1,210 @@
4597+<!DOCTYPE html>
4598+<html>
4599+<!--Head-->
4600+ <head>
4601+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4602+ <title>Juju Documentation</title>
4603+ <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
4604+ <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
4605+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
4606+ <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
4607+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
4608+ <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
4609+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
4610+ <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
4611+ <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
4612+ <link href="./css/main.css" rel="stylesheet" type="text/css">
4613+
4614+ <!--[if lt IE 9]>
4615+ <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
4616+ <![endif]-->
4617+ </head>
4618+<!--End-Head-->
4619+
4620+
4621+
4622+
4623+ <body class="resources">
4624+
4625+<!--Header-->
4626+
4627+ <header class="banner global" role="banner">
4628+ <nav role="navigation" class="nav-primary nav-right">
4629+ <div class="logo">
4630+ <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
4631+ <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
4632+ <span>Juju</span>
4633+ </a>
4634+ </div>
4635+ <ul>
4636+ <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
4637+ <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
4638+ <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
4639+ <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
4640+ <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
4641+ <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
4642+ <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
4643+ </ul>
4644+ <div id="box-search">
4645+ <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
4646+ <label class="off-left" for="s">Search:</label>
4647+ <input class="form-text" type="text" value="" name="s" id="s" />
4648+ <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
4649+ </form>
4650+ </div>
4651+ </nav>
4652+ </header>
4653+<!--End-Header-->
4654+<!--Preamble-->
4655+<div class="wrapper">
4656+ <div id="main-content" class="inner-wrapper" role="main">
4657+ <div class="row no-border">
4658+ <div class="header-navigation-secondary"></div>
4659+ <h2 class="pagetitle">Juju documentation</h2>
4660+ </div>
4661+ <section id="content" class="container-12">
4662+ <div class="grid-12 doc-container">
4663+ <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
4664+ <div class="grid-9 doc-content">
4665+<!--End-Preamble-->
4666+<article>
4667+<h1>Service configuration</h1>
4668+<h2>Introduction</h2>
4669+<p>A <a href="./charm.html">Charm</a> often will require access to specific options or configuration. Charms allow for the manipulation of the various configuration options which the charm author has chosen to expose. juju provides tools to help manage these options and respond to changes in these options over the lifetime of the service deployment. These options apply to the entire service, as opposed to only a specific unit or relation. Configuration is modified by an administrator at deployment time or over the lifetime of the services.</p>
4670+<p>As an example a wordpress service may expose a 'blog-title' option. This option would control the title of the blog being published. Changes to this option would be applied to all units implementing this service through the invocation of a hook on each of them.</p>
4671+<h2>Using configuration options</h2>
4672+<p>Configuration options are manipulated using a command line interface. juju provide a set command to aid the administrator in changing values.</p>
4673+<pre><code>juju set &lt;service name&gt; option=value [option=value]</code></pre>
4674+<p>This command allows changing options at runtime and takes one or more name/value pairs which will be set into the service options. Configuration options which are set together are delivered to the services for handling together. E.g. if you are changing a username and a password, changing them individually may yield bad results since the username will temporarily be set with an incorrect password.</p>
4675+<p>While its possible to set multiple configuration options on the command line its also convenient to pass multiple configuration options via the --file argument which takes the name of a YAML file. The contents of this file will be applied as though these elements had been passed to juju set.</p>
4676+<p>A configuration file may be provided at deployment time using the --config option, as follows:</p>
4677+<pre><code>juju deploy [--config local.yaml] wordpress myblog
4678+juju deploy [--config local.yaml] postgres</code></pre>
4679+<p>The service name is looked up inside the YAML file to allow for related service configuration options to be collected into a single file for the purposes of deployment and passed repeated to each juju deploy invocation.</p>
4680+<p>Below is an example local.yaml containing options which would be used during deployment of a service named myblog.</p>
4681+<pre><code>myblog:
4682+ blog-roll: [&#39;http://foobar.com&#39;, &#39;http://testing.com&#39;]
4683+ blog-title: Awesome Sauce
4684+ password: n0nsense
4685+postgres:
4686+ port: 5432
4687+ cluster-name: main</code></pre>
4688+<h2>Creating charms</h2>
4689+<p>Charm authors create a config.yaml file which resides in the charm's top-level directory. The configuration options supported by a service are defined within its respective charm. juju will only allow the manipulation of options which were explicitly defined as supported.</p>
4690+<p>The specification of possible configuration values is intentionally minimal, but still evolving. Currently the charm define a list of names which they react. Information includes a human readable description and an optional default value. Additionally type may be specified. All options have a default type of 'str' which means its value will only be treated as a text string. Other valid options are 'int' and 'float'.</p>
4691+<p>The following config.yaml would be included in the top level directory of a charm and includes a list of option definitions:</p>
4692+<pre><code>options:
4693+ port:
4694+ default: 80
4695+ type: int
4696+ description: Port to listen on
4697+ admin-email:
4698+ # type: str is implied
4699+ default: null
4700+ description: Email address for the site administrator.</code></pre>
4701+<p>To access these configuration options from a hook we provide the following:</p>
4702+<pre><code>config-get [option name]</code></pre>
4703+<p>config-get returns all the configuration options for a service as JSON data when no option name is specified. If an option name is specified the value of that option is output according to the normal rules and obeying the --output and --format arguments. Hooks implicitly know the service they are executing for and config-get always gets values from the service of the hook.</p>
4704+<p>Changes to options (see previous section) trigger the charm's config-changed hook. The config-changed hook is guaranteed to run after any changes are made to the configuration, but it is possible that multiple changes will be observed at once. Because its possible to set many configuration options on a single command line invocation it is easily possible to ensure related options are available to the service at the same time.</p>
4705+<p>The config-changed hook must be written in such a way as to deal with changes to one or more options and deal gracefully with options that are required by the charm but not yet set by an administrator. Errors in the config-changed hook force juju to assume the service is no longer properly configured. If the service is not already in a stopped state it will be stopped and taken out of service. The status command will be extended in the future to report on workflow and unit agent status which will help reveal error conditions of this nature.</p>
4706+<p>When options are passed using juju deploy their values will be read in from a file and made available to the service prior to the invocation of the its install hook. The install and start hooks will have access to config-get and thus complete access to the configuration options during their execution. If the install or start hooks don't directly need to deal with options they can simply invoke the config-changed hook.</p>
4707+<h2>Internals</h2>
4708+<blockquote>
4709+<p><strong>note</strong></p>
4710+<dl>
4711+<dt>This section explains details useful to the implementation but not of</dt>
4712+<dd><p>interest to the casual reader.</p>
4713+</dd>
4714+</dl>
4715+</blockquote>
4716+<p>Hooks normally attempt to provide a consistent view of the shared state of the system and the handling of config options within hooks (config-changed and the relation hooks) is no different. The first access to the configuration data of a service will retain a cached copy of the service options. Cached data will be used for the duration of the hook invocation.</p>
4717+</article>
4718+<!--Postamble-->
4719+ </div>
4720+ </div>
4721+ </section>
4722+ </div>
4723+</div>
4724+<!--End-Postamble-->
4725+<!--Footer-->
4726+ <footer class="global clearfix" role="contentinfo">
4727+ <nav role="navigation">
4728+ <div class="footer-a">
4729+ <div class="clearfix">
4730+ <ul>
4731+ <li>
4732+ <h2><a href="/">Juju</a></h2>
4733+ <ul>
4734+ <li><a href="/charms">Charms</a></li>
4735+ <li><a href="/features">Features</a></li>
4736+ <li><a href="/deployment">Deployment</a></li>
4737+ </ul>
4738+ </li>
4739+ <li>
4740+ <h2><a href="/resources">Resources</a></h2>
4741+ <ul>
4742+ <li><a href="/resources/juju-overview/">Overview</a></li>
4743+ <li><a href="/docs/">Documentation</a></li>
4744+ <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
4745+ <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
4746+ <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
4747+ <li><a href="/resources/videos/">Videos</a></li>
4748+ <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
4749+ </ul>
4750+ </li>
4751+ <li>
4752+ <h2><a href="/community">Community</a></h2>
4753+ <ul>
4754+ <li><a href="/community/blog/">Juju Blog</a></li>
4755+ <li><a href="/events/">Events</a></li>
4756+ <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
4757+ <li><a href="/community/charmers/">Charmers</a></li>
4758+ <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
4759+ <li><a href="/docs/contributing.html">Help with documentation</a></li>
4760+ <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
4761+ </ul>
4762+ </li>
4763+ <li>
4764+ <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
4765+ <ul>
4766+ <li><a href="https://jujucharms.com/">Charm store</a></li>
4767+ <li><a href="/download/">Download Juju</a></li>
4768+ </ul>
4769+ </li>
4770+ </ul>
4771+ </div>
4772+ </div>
4773+ </nav>
4774+ <div class="legal clearfix">
4775+ <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
4776+ </div>
4777+ </footer>
4778+
4779+<!--End-Footer-->
4780+
4781+<!--Scripts-->
4782+ <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
4783+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
4784+ <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
4785+ <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
4786+ <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
4787+ <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
4788+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
4789+ <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
4790+ <!-- google analytics -->
4791+ <script>
4792+ var _gaq = _gaq || [];
4793+ _gaq.push(['_setAccount', 'UA-1018242-41']);
4794+ _gaq.push(['_trackPageview']);
4795+
4796+ (function() {
4797+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
4798+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
4799+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
4800+ })();
4801+ </script>
4802+<!--End-Scripts-->
4803+
4804+
4805+
4806+</body></html>
4807
4808=== removed file 'htmldocs/authors-service-config.html'
4809--- htmldocs/authors-service-config.html 2013-09-27 14:53:30 +0000
4810+++ htmldocs/authors-service-config.html 1970-01-01 00:00:00 +0000
4811@@ -1,208 +0,0 @@
4812-<!DOCTYPE html>
4813-<html>
4814-<!--Head-->
4815- <head>
4816- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4817- <title>Juju Documentation</title>
4818- <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
4819- <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
4820- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
4821- <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
4822- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
4823- <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
4824- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
4825- <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
4826- <link rel="stylesheet" id="stacktack-css" href="https://juju.ubuntu.com/wp-content/plugins/stacktack/css/stacktack.min.css?ver=3.4.2" type="text/css" media="all">
4827- <link href="./css/main.css" rel="stylesheet" type="text/css">
4828-
4829- <!--[if lt IE 9]>
4830- <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
4831- <![endif]-->
4832- </head>
4833-<!--End-Head-->
4834-
4835-
4836-
4837- <body class="resources">
4838-
4839-<!--Header-->
4840-
4841- <header class="banner global" role="banner">
4842- <nav role="navigation" class="nav-primary nav-right">
4843- <div class="logo">
4844- <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
4845- <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
4846- <span>Juju</span>
4847- </a>
4848- </div>
4849- <ul>
4850- <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
4851- <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
4852- <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
4853- <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
4854- <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
4855- <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
4856- <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
4857- </ul>
4858- <div id="box-search">
4859- <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
4860- <label class="off-left" for="s">Search:</label>
4861- <input class="form-text" type="text" value="" name="s" id="s" />
4862- <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
4863- </form>
4864- </div>
4865- </nav>
4866- </header>
4867-<!--End-Header-->
4868-<!--Preamble-->
4869-<div class="wrapper">
4870- <div id="main-content" class="inner-wrapper" role="main">
4871- <div class="row no-border">
4872- <div class="header-navigation-secondary"></div>
4873- <h2 class="pagetitle">Juju documentation</h2>
4874- </div>
4875- <section id="content" class="container-12">
4876- <div class="grid-12 doc-container">
4877- <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
4878- <div class="grid-9 doc-content">
4879-<!--End-Preamble-->
4880-<article>
4881-<h1>Service configuration</h1>
4882-<h2>Introduction</h2>
4883-<p>A <a href="./charm.html">Charm</a> often will require access to specific options or configuration. Charms allow for the manipulation of the various configuration options which the charm author has chosen to expose. juju provides tools to help manage these options and respond to changes in these options over the lifetime of the service deployment. These options apply to the entire service, as opposed to only a specific unit or relation. Configuration is modified by an administrator at deployment time or over the lifetime of the services.</p>
4884-<p>As an example a wordpress service may expose a 'blog-title' option. This option would control the title of the blog being published. Changes to this option would be applied to all units implementing this service through the invocation of a hook on each of them.</p>
4885-<h2>Using configuration options</h2>
4886-<p>Configuration options are manipulated using a command line interface. juju provide a set command to aid the administrator in changing values.</p>
4887-<pre><code>juju set &lt;service name&gt; option=value [option=value]</code></pre>
4888-<p>This command allows changing options at runtime and takes one or more name/value pairs which will be set into the service options. Configuration options which are set together are delivered to the services for handling together. E.g. if you are changing a username and a password, changing them individually may yield bad results since the username will temporarily be set with an incorrect password.</p>
4889-<p>While its possible to set multiple configuration options on the command line its also convenient to pass multiple configuration options via the --file argument which takes the name of a YAML file. The contents of this file will be applied as though these elements had been passed to juju set.</p>
4890-<p>A configuration file may be provided at deployment time using the --config option, as follows:</p>
4891-<pre><code>juju deploy [--config local.yaml] wordpress myblog
4892-juju deploy [--config local.yaml] postgres</code></pre>
4893-<p>The service name is looked up inside the YAML file to allow for related service configuration options to be collected into a single file for the purposes of deployment and passed repeated to each juju deploy invocation.</p>
4894-<p>Below is an example local.yaml containing options which would be used during deployment of a service named myblog.</p>
4895-<pre><code>myblog:
4896- blog-roll: [&#39;http://foobar.com&#39;, &#39;http://testing.com&#39;]
4897- blog-title: Awesome Sauce
4898- password: n0nsense
4899-postgres:
4900- port: 5432
4901- cluster-name: main</code></pre>
4902-<h2>Creating charms</h2>
4903-<p>Charm authors create a config.yaml file which resides in the charm's top-level directory. The configuration options supported by a service are defined within its respective charm. juju will only allow the manipulation of options which were explicitly defined as supported.</p>
4904-<p>The specification of possible configuration values is intentionally minimal, but still evolving. Currently the charm define a list of names which they react. Information includes a human readable description and an optional default value. Additionally type may be specified. All options have a default type of 'str' which means its value will only be treated as a text string. Other valid options are 'int' and 'float'.</p>
4905-<p>The following config.yaml would be included in the top level directory of a charm and includes a list of option definitions:</p>
4906-<pre><code>options:
4907- port:
4908- default: 80
4909- type: int
4910- description: Port to listen on
4911- admin-email:
4912- # type: str is implied
4913- default: null
4914- description: Email address for the site administrator.</code></pre>
4915-<p>To access these configuration options from a hook we provide the following:</p>
4916-<pre><code>config-get [option name]</code></pre>
4917-<p>config-get returns all the configuration options for a service as JSON data when no option name is specified. If an option name is specified the value of that option is output according to the normal rules and obeying the --output and --format arguments. Hooks implicitly know the service they are executing for and config-get always gets values from the service of the hook.</p>
4918-<p>Changes to options (see previous section) trigger the charm's config-changed hook. The config-changed hook is guaranteed to run after any changes are made to the configuration, but it is possible that multiple changes will be observed at once. Because its possible to set many configuration options on a single command line invocation it is easily possible to ensure related options are available to the service at the same time.</p>
4919-<p>The config-changed hook must be written in such a way as to deal with changes to one or more options and deal gracefully with options that are required by the charm but not yet set by an administrator. Errors in the config-changed hook force juju to assume the service is no longer properly configured. If the service is not already in a stopped state it will be stopped and taken out of service. The status command will be extended in the future to report on workflow and unit agent status which will help reveal error conditions of this nature.</p>
4920-<p>When options are passed using juju deploy their values will be read in from a file and made available to the service prior to the invocation of the its install hook. The install and start hooks will have access to config-get and thus complete access to the configuration options during their execution. If the install or start hooks don't directly need to deal with options they can simply invoke the config-changed hook.</p>
4921-<h2>Internals</h2>
4922-<blockquote>
4923-<p><strong>note</strong></p>
4924-<dl>
4925-<dt>This section explains details useful to the implementation but not of</dt>
4926-<dd><p>interest to the casual reader.</p>
4927-</dd>
4928-</dl>
4929-</blockquote>
4930-<p>Hooks normally attempt to provide a consistent view of the shared state of the system and the handling of config options within hooks (config-changed and the relation hooks) is no different. The first access to the configuration data of a service will retain a cached copy of the service options. Cached data will be used for the duration of the hook invocation.</p>
4931-</article>
4932-<!--Postamble-->
4933- </div>
4934- </div>
4935- </section>
4936- </div>
4937-</div>
4938-<!--End-Postamble-->
4939-<!--Footer-->
4940- <footer class="global clearfix" role="contentinfo">
4941- <nav role="navigation">
4942- <div class="footer-a">
4943- <div class="clearfix">
4944- <ul>
4945- <li>
4946- <h2><a href="/">Juju</a></h2>
4947- <ul>
4948- <li><a href="/charms">Charms</a></li>
4949- <li><a href="/features">Features</a></li>
4950- <li><a href="/deployment">Deployment</a></li>
4951- </ul>
4952- </li>
4953- <li>
4954- <h2><a href="/resources">Resources</a></h2>
4955- <ul>
4956- <li><a href="/resources/juju-overview/">Overview</a></li>
4957- <li><a href="/docs/">Documentation</a></li>
4958- <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
4959- <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
4960- <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
4961- <li><a href="/resources/videos/">Videos</a></li>
4962- <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
4963- </ul>
4964- </li>
4965- <li>
4966- <h2><a href="/community">Community</a></h2>
4967- <ul>
4968- <li><a href="/community/blog/">Juju Blog</a></li>
4969- <li><a href="/events/">Events</a></li>
4970- <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
4971- <li><a href="/community/charmers/">Charmers</a></li>
4972- <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
4973- <li><a href="/docs/contributing.html">Help with documentation</a></li>
4974- <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
4975- </ul>
4976- </li>
4977- <li>
4978- <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
4979- <ul>
4980- <li><a href="https://jujucharms.com/">Charm store</a></li>
4981- <li><a href="/download/">Download Juju</a></li>
4982- </ul>
4983- </li>
4984- </ul>
4985- </div>
4986- </div>
4987- </nav>
4988- <div class="legal clearfix">
4989- <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
4990- </div>
4991- </footer>
4992-
4993-<!--End-Footer-->
4994-
4995-<!--Scripts-->
4996- <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
4997- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
4998- <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
4999- <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
5000- <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches