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
=== removed file 'htmldocs/authors-charm-anatomy.html'
--- htmldocs/authors-charm-anatomy.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-charm-anatomy.html 1970-01-01 00:00:00 +0000
@@ -1,525 +0,0 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25
26 <body class="resources">
27<!--Header-->
28
29 <header class="banner global" role="banner">
30 <nav role="navigation" class="nav-primary nav-right">
31 <div class="logo">
32 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
33 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
34 <span>Juju</span>
35 </a>
36 </div>
37 <ul>
38 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
39 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
40 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
41 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
42 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
43 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
44 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
45 </ul>
46 <div id="box-search">
47 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
48 <label class="off-left" for="s">Search:</label>
49 <input class="form-text" type="text" value="" name="s" id="s" />
50 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
51 </form>
52 </div>
53 </nav>
54 </header>
55<!--End-Header-->
56<!--Preamble-->
57<div class="wrapper">
58 <div id="main-content" class="inner-wrapper" role="main">
59 <div class="row no-border">
60 <div class="header-navigation-secondary"></div>
61 <h2 class="pagetitle">Juju documentation</h2>
62 </div>
63 <section id="content" class="container-12">
64 <div class="grid-12 doc-container">
65 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
66 <div class="grid-9 doc-content">
67<!--End-Preamble-->
68<article>
69<section id="charm-anatomy">
70<h1>Anatomy of a charm</h1>
71<p>Charms define how services integrate and how their service units
72react to events in the distributed environment, as orchestrated by
73juju.</p>
74<p>This specification describes how charms are defined, including their
75metadata and hooks. It also describes the resources available to hooks
76in working with the juju environment.</p>
77
78<h2>The metadata file</h2>
79<p>The <cite>metadata.yaml</cite> file, at the root of the charm directory,
80describes the charm. The following fields are supported:</p>
81<blockquote>
82<ul>
83<li><strong>name:</strong> - The charm name itself. Charm names are formed by
84lowercase letters, digits, and dashes, and must necessarily
85begin with a letter and have no digits alone in a dashed
86section.</li>
87<li><strong>summary:</strong> - A one-line description of the charm.</li>
88<li><strong>maintainer:</strong> - An RFC2822 compliant email address that should
89be the main point of contact for development of this charm.</li>
90<li><strong>description:</strong> - Long explanation of the charm and its
91features.</li>
92<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>
93<li><strong>provides:</strong> - The deployed service unit must have the given
94relations established with another service unit whose charm
95requires them for the service to work properly. See below for how
96to define a relation.</li>
97<li><strong>requires:</strong> - The deployed service unit must have the given
98relations established with another service unit whose charm
99provides them for the service to work properly. See below for how
100to define a relation.</li>
101<li><strong>peers:</strong> - Relations that are established with P2P semantics
102instead of a provides/requires (or client/server) style. When the
103charm is deployed as a service unit, all the units from the
104given service will automatically be made part of the relation.
105See below for how to define a relation.</li>
106</ul>
107</blockquote>
108
109<p>Relations available in <cite>provides</cite>, <cite>requires</cite>, and <cite>peers</cite> are defined
110as follows:</p>
111<blockquote>
112<ul>
113<li><p class="first"><strong>provides|requires|peers:</strong></p>
114<ul>
115<li><p class="first"><strong>&lt;relation name&gt;:</strong> - This name is a user-provided value which
116identifies the relation uniquely within the given charm.
117Examples include &quot;database&quot;, &quot;cache&quot;, &quot;proxy&quot;, and &quot;appserver&quot;.</p>
118<p>Each relation may have the following fields defined:</p>
119<ul>
120<li><strong>interface:</strong> - This field defines the type of the
121relation. The relation will only be established with service
122units that define a compatible relation with the same
123interface. Examples include &quot;http&quot;, &quot;mysql&quot;, and
124&quot;backup-schedule&quot;.</li>
125<li><strong>limit:</strong> - The maximum number of relations of this kind
126which may be established to other service units. Defaults to
1271 for <cite>requires</cite> relations, and to &quot;none&quot; (no limit) for
128<cite>provides</cite> and <cite>peers</cite> relations. While you may define it,
129this field is not yet enforced by juju.</li>
130<li><strong>optional:</strong> - Whether this relation is required for the
131service unit to function or not. Defaults to <cite>false</cite>, which
132means the relation is required. While you may define it, this
133field is not yet enforced by juju.</li>
134<li><strong>scope:</strong> - Controls which units of related-to services can
135be communicated with through this relationship. Juju supports
136the following scopes:<ul>
137<li><strong>global:</strong> <cite>default</cite> When a traditional relation is added
138between two services, all the service units for the first service will
139receive relation events about all service units for the second
140service.</li>
141<li><strong>container</strong>: Communication is restricted to units deployed
142in the same container. It is not possible to establish a
143container scoped relation between principal services. See
144<a href="authors-subordinate-services.html"><em>Subordinate services</em></a>.</li>
145</ul>
146</li>
147</ul>
148<p>As a shortcut, if these properties are not defined, and instead
149a single string value is provided next to the relation name, the
150string is taken as the interface value, as seen in this
151example:</p>
152<pre><code>requires:
153 db: mysql</code></pre>
154
155</li>
156</ul>
157</li>
158</ul>
159</blockquote>
160<p>Some sample charm definitions are provided at the end of this
161specification.</p>
162</section>
163
164<section id="hooks">
165<h2>Hooks</h2>
166<p>Juju uses hooks to notify a service unit about changes happening
167in its lifecycle or the larger distributed environment. A hook running
168for a service unit can query this environment, make any desired local
169changes on its underlying machine, and change the relation
170settings.</p>
171<p>Each hook for a charm is implemented by placing an executable with
172the desired hook name under the <span class="pre">hooks/</span> directory of the charm
173directory. juju will execute the hook based on its file name when
174the corresponding event occurs.</p>
175<p>All hooks are optional. Not including a corresponding executable in
176the charm is treated by juju as if the hook executed and then
177exited with an exit code of 0.</p>
178<p>All hooks are executed in the charm directory on the service unit.</p>
179<p>The following hooks are with respect to the lifecycle of a service unit:</p>
180<blockquote>
181<ul>
182<li><strong>install</strong> - Runs just once during the life time of a service
183unit. Currently this hook is the right place to ensure any package
184dependencies are met. However, in the future juju will use the
185charm metadata to perform this role instead.</li>
186<li><strong>config-changed</strong> - runs once after installation, and in response
187to configuration changes (e.g. <span class="pre">juju</span> <span class="pre">set</span>). Service configuration
188actions such as config file generation or runtime tuning should
189happen here.</li>
190<li><strong>start</strong> - Runs when the service unit is started. This happens
191before any relation hooks are called. The purpose of this hook is
192to get the service unit ready for relations to be established.</li>
193<li><strong>stop</strong> - Runs when the service unit is stopped. If relations
194exist, they will be broken and the respective hooks called before
195this hook is called.</li>
196</ul>
197</blockquote>
198<p>The following hooks are called on each service unit as the membership
199of an established relation changes:</p>
200<blockquote>
201<ul>
202<li><p class="first"><strong>&lt;relation name&gt;-relation-joined</strong> - Runs upon each time a remote
203service unit joins the relation.</p>
204</li>
205<li><p class="first"><strong>&lt;relation name&gt;-relation-changed</strong> - Runs upon each time the
206following events occur:</p>
207<ol class="arabic simple">
208<li>A remote service unit joins the relation, right after the
209<strong>&lt;relation name&gt;-relation-joined</strong> hook was called.</li>
210<li>A remote service unit changes its relation settings.</li>
211</ol>
212<p>This hook enables the charm to modify the service unit state
213(configuration, running processes, or anything else) to adapt to
214the relation settings of remote units.</p>
215<p>An example usage is that HAProxy needs to be aware of web servers
216as they become available, including details like its IP
217address. Web server service units can publish their availability
218by making the appropriate relation settings in the hook that makes
219the most sense. Assume the HAProxy uses the relation name of
220<span class="pre">server</span>. Then upon that happening, the HAProxy in its
221<span class="pre">server-relation-changed</span> <span class="pre">hook</span> can then change its own
222configuration as to what is available to be proxied.</p>
223</li>
224<li><p class="first"><strong>&lt;relation name&gt;-relation-departed</strong> - Runs upon each time a
225remote service unit leaves a relation. This could happen because
226the service unit has been removed, its service has been destroyed,
227or the relation between this service and the remote service has
228been removed.</p>
229<p>An example usage is that HAProxy needs to be aware of web servers
230when they are no longer available. It can remove each web server
231its configuration as the corresponding service unit departs the
232relation.</p>
233</li>
234</ul>
235</blockquote>
236<p>This relation hook is with respect to the relation itself:</p>
237<blockquote>
238<ul>
239<li><p class="first"><strong>&lt;relation name&gt;-relation-broken</strong> - Runs when a relation which
240had at least one other relation hook run for it (successfully or
241not) is now unavailable. The service unit can then clean up any
242established state.</p>
243<p>An example might be cleaning up the configuration changes which
244were performed when HAProxy was asked to load-balance for another
245service unit.</p>
246</li>
247</ul>
248</blockquote>
249<p>Note that the coupling between charms is defined by which settings
250are required and made available to them through the relation hooks and
251how these settings are used. Those conventions then define what the
252relation interface really is, and the <strong>interface</strong> name in the
253<cite>metadata.yaml</cite> file is simply a way to refer to them and avoid the
254attempting of incompatible conversations. Keep that in mind when
255designing your charms and relations, since it is a good idea to
256allow the implementation of the charm to change and be replaced with
257alternative versions without changing the relation conventions in a
258backwards incompatible way.</p>
259
260<h2>Hook environment</h2>
261<p>Hooks can expect to be invoked with a standard environment and
262context. The following environment variables are set:</p>
263<blockquote>
264<ul>
265<li><strong>$JUJU_UNIT_NAME</strong> - The name of the local unit executing,
266in 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>
267</ul>
268</blockquote>
269<p>Hooks called for relation changes will have the follow additional
270environment variables set:</p>
271<blockquote>
272<ul>
273<li><strong>$JUJU_RELATION</strong> - The relation name this hook is running
274for. It's redundant with the hook name, but is necessary for
275the command line tools to know the current context.</li>
276<li><strong>$JUJU_REMOTE_UNIT</strong> - The unit name of the remote unit
277which has triggered the hook execution.</li>
278</ul>
279</blockquote>
280
281<h2>Hook commands for working with relations</h2>
282<p>In implementing their functionality, hooks can leverage a set of
283command tools provided by juju for working with relations. These
284utilities enable the hook to collaborate on their relation settings,
285and to inquire about the peers the service unit has relations with.</p>
286<p>The following command line tools are made available:</p>
287<blockquote>
288<ul>
289<li><p class="first"><strong>relation-ids</strong> - List ids for established relations.</p>
290<p>Example:</p>
291<pre><span class="n">relation</span><span class="o">-</span><span class="n">ids</span>
292</pre>
293
294</li>
295<li><p class="first"><strong>relation-list</strong> - List all service units participating in the
296established relation. This list excludes the local service unit
297which is executing the command. For <cite>provides</cite> and <cite>requires</cite>
298relations, this command will always return a single service unit.</p>
299<p>Example:</p>
300<pre>MEMBERS=$(relation-list)</pre>
301
302</li>
303<li><p class="first"><strong>relation-get</strong> - Queries a setting from an established relation
304with one or more service units. This command will read some
305context information from environment variables (e.g.
306$JUJU_RELATION_NAME).</p>
307<p>Examples:</p>
308<p>Get the IP address from the remote unit which triggered the hook
309execution:</p>
310<pre>relation-get ip</pre>
311
312<p>Get all the settings from the remote unit which triggered the hook
313execution:</p>
314<span class="n">relation</span><span class="o">-</span><span class="n">get</span>
315
316
317<p>Get the port information from the <cite>wordpress/3</cite> unit:</p>
318<pre>relation-get port wordpress/3</pre>
319
320<p>Get all the settings from the <cite>wordpress/3</cite> unit, in JSON format:</p>
321<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>
322</pre>
323
324</li>
325<li><p class="first"><strong>relation-set</strong> - Changes a setting in an established relation.</p>
326<p>Examples:</p>
327<p>Set this unit's port number for other peers to use:</p>
328<pre>relation-set port=8080</pre>
329
330<p>Change two settings at once:</p>
331<pre>relation-set dbname=wordpress dbpass="super secur3"</pre>
332
333<p>Change several settings at once, with a JSON file:</p>
334<pre>cat settings.json | relation-set</pre>
335
336<p>Delete a setting:</p>
337<pre>relation-set name=</pre>
338
339</li>
340</ul>
341</blockquote>
342<p>Changes to relation settings are only committed if the hook exited
343with an exit code of 0. Such changes will then trigger further hook
344execution in the remote unit(s), through the <strong>&lt;relation
345name&gt;-relation-changed</strong> hook. This mechanism enables a general
346communication mechanism for service units to coordinate.</p>
347
348
349<h2>Hook commands for opening and closing ports></h2>
350<p>Service exposing determines which ports to expose by using the
351<span class="pre">open-port</span> and <span class="pre">close-port</span> commands in hooks. They may be
352executed within any charm hook. The commands take the same
353arguments:</p>
354<pre>open-port port[/protocol]
355
356close-port port[/protocol]</pre>
357
358<p>These commands are executed immediately; they do not depend on the
359exit status of the hook.</p>
360<p>As an example, consider the WordPress charm, which has been deployed
361as <span class="pre">my-wordpress</span>. After completing the setup and restart of Apache,
362the <span class="pre">wordpress</span> charm can then publish the available port in its
363<span class="pre">start</span> hook for a given service unit:</p>
364<pre>open-port 80</pre>
365
366<p>External access to the service unit is only allowed when both
367<span class="pre">open-port</span> is executed within any hook and the administrator has
368exposed its service. The order in which these happen is not
369important, however.</p>
370
371<p class="note"><strong>Note: </strong>Being able to use any hook may be important for your charm.
372Ideally, the service does not have ports that are vulnerable if
373exposed prior to the service being fully ready. But if that's the
374case, you can solve this problem by only opening the port in the
375appropriate hook and when the desired conditions are met.</p>
376
377<p>Alternatively, you may need to expose more than one port, or expose
378ports that don't use the TCP protocol. To expose ports for
379HTTP and HTTPS, your charm could instead make these settings:</p>
380<pre>open-port 80
381open-port 443</pre>
382
383<p>Or if you are writing a charm for a DNS server that you would like
384to expose, then specify the protocol to be UDP:</p>
385<pre>open-port 53/udp</pre>
386
387<p>When the service unit is removed or stopped for any reason, the
388firewall will again be changed to block traffic which was previously
389allowed to reach the exposed service. Your charm can also do this to
390close the port:</p>
391<pre>close-port 80</pre>
392
393<p>To be precise, the firewall is only open for the exposed ports during
394the time both these conditions hold:</p>
395<blockquote>
396<ul>
397<li>A service has been exposed.</li>
398<li>A corresponding <span class="pre">open-port</span> command has been run (without a
399subsequent <span class="pre">close-port</span>).</li>
400</ul>
401</blockquote>
402
403<h2>Sample metadata.yaml files</h2>
404<p>Below are presented some sample metadata files.</p>
405<p>MySQL:</p>
406<pre>name: mysql
407summary: "A pretty popular database"
408maintainer: "Juju Charmers &lt;juju@lists.ubuntu.com&gt;"
409
410provides:
411 db: mysql</pre>
412
413<p>Wordpress:</p>
414<pre>name: wordpress
415summary: "A pretty popular blog engine"
416maintainer: "Juju Charmers &lt;juju@lists.ubuntu.com&gt;"
417provides:
418 url:
419 interface: http
420
421requires:
422 db:
423 interface: mysql</pre>
424
425<p>Riak:</p>
426<pre>name: riak
427summary: "Scalable K/V Store in Erlang with Clocks :-)"
428maintainer: "Juju Charmers &lt;juju@lists.ubuntu.com&gt;"
429provides:
430 endpoint:
431 interface: http
432
433peers:
434 ring:
435 interface: riak</pre>
436
437</section>
438</article>
439<!--Postamble-->
440 </div>
441 </div>
442 </section>
443 </div>
444</div>
445<!--End-Postamble-->
446<!--Footer-->
447 <footer class="global clearfix" role="contentinfo">
448 <nav role="navigation">
449 <div class="footer-a">
450 <div class="clearfix">
451 <ul>
452 <li>
453 <h2><a href="/">Juju</a></h2>
454 <ul>
455 <li><a href="/charms">Charms</a></li>
456 <li><a href="/features">Features</a></li>
457 <li><a href="/deployment">Deployment</a></li>
458 </ul>
459 </li>
460 <li>
461 <h2><a href="/resources">Resources</a></h2>
462 <ul>
463 <li><a href="/resources/juju-overview/">Overview</a></li>
464 <li><a href="/docs/">Documentation</a></li>
465 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
466 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
467 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
468 <li><a href="/resources/videos/">Videos</a></li>
469 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
470 </ul>
471 </li>
472 <li>
473 <h2><a href="/community">Community</a></h2>
474 <ul>
475 <li><a href="/community/blog/">Juju Blog</a></li>
476 <li><a href="/events/">Events</a></li>
477 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
478 <li><a href="/community/charmers/">Charmers</a></li>
479 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
480 <li><a href="/docs/contributing.html">Help with documentation</a></li>
481 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
482 </ul>
483 </li>
484 <li>
485 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
486 <ul>
487 <li><a href="https://jujucharms.com/">Charm store</a></li>
488 <li><a href="/download/">Download Juju</a></li>
489 </ul>
490 </li>
491 </ul>
492 </div>
493 </div>
494 </nav>
495 <div class="legal clearfix">
496 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
497 </div>
498 </footer>
499
500<!--End-Footer-->
501<!--Scripts-->
502 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
503 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
504 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
505 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
506 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
507 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
508 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
509 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
510 <!-- google analytics -->
511 <script>
512 var _gaq = _gaq || [];
513 _gaq.push(['_setAccount', 'UA-1018242-41']);
514 _gaq.push(['_trackPageview']);
515
516 (function() {
517 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
518 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
519 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
520 })();
521 </script>
522<!--End-Scripts-->
523
524
525</body></html>
526\ No newline at end of file0\ No newline at end of file
5271
=== modified file 'htmldocs/authors-charm-best-practice.html'
--- htmldocs/authors-charm-best-practice.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-charm-best-practice.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -220,4 +222,6 @@
220<!--End-Scripts-->222<!--End-Scripts-->
221223
222224
225
226
223</body></html>227</body></html>
224228
=== added file 'htmldocs/authors-charm-components.html'
--- htmldocs/authors-charm-components.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-charm-components.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,235 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25 <body class="resources">
26<!--Header-->
27
28 <header class="banner global" role="banner">
29 <nav role="navigation" class="nav-primary nav-right">
30 <div class="logo">
31 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
32 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
33 <span>Juju</span>
34 </a>
35 </div>
36 <ul>
37 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
38 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
39 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
40 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
41 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
42 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
43 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
44 </ul>
45 <div id="box-search">
46 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
47 <label class="off-left" for="s">Search:</label>
48 <input class="form-text" type="text" value="" name="s" id="s" />
49 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
50 </form>
51 </div>
52 </nav>
53 </header>
54<!--End-Header-->
55<!--Preamble-->
56<div class="wrapper">
57 <div id="main-content" class="inner-wrapper" role="main">
58 <div class="row no-border">
59 <div class="header-navigation-secondary"></div>
60 <h2 class="pagetitle">Juju documentation</h2>
61 </div>
62 <section id="content" class="container-12">
63 <div class="grid-12 doc-container">
64 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
65 <div class="grid-9 doc-content">
66<!--End-Preamble-->
67<article>
68<section id="charm-contents">
69<h1>What makes a Charm?</h1>
70<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>
71</section>
72
73<section id="required-files">
74<h2>Required files</h2>
75<p>A charm requires only a single file in order to be considered valid by juju:
76<ul>
77<li><code>metadata.yaml</code> <a href="./authors-charm-metadata.html">describes the
78 charm</a> and the relations it can participate in.</li>
79</ul>
80<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>
81</section>
82
83<section id="special-files">
84<h2>Special files</h2>
85<p>The following files will be treated specially, if present:</p>
86<ul>
87 <li><code>/hooks</code> must be a directory holding
88 executables with specific names, that will be invoked by juju at the relevant times.
89 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>
90 <li><code>config.yaml</code> defines service configuration options.<a href="./authors-charm-config.html">
91 The config.yaml file is descibed more fully here</a>.</li>
92 <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>
93 <li><code>README</code> is made available in the charm store. It should be
94 comprehensible to a reasonably ignorant user.</li>
95 <li><code>revision</code> is now deprecated.</li>
96 <li> files matching <code>.juju*</code> should <strong>not</strong> be used.</li>
97</ul>
98</section>
99
100<section id="other-files">
101<h2>Other files</h2>
102
103<p>Any other files you know you'll need can be placed in the charm for convenience.
104It is recommended to leave the hooks directory for the executable hooks alone - library
105code may be included elsewhere in the charm.</p>
106
107<p>When hooks are actually running, they can read and write to the charm directory
108freely, but should carefully observe the caveats in the next section...</p>
109</section>
110
111<section id="runtime-files">
112<h2>Charm files at runtime</h2>
113
114<p>The files you store with your charm should <em>not</em> be used directly by the
115software installed by your charm. If the files are really needed by the software
116at runtime, copy them on the system alongside the software and reference those
117instead.</p>
118
119<p>This is because the software does <em>not</em> have control over the charm directory;
120<em>juju</em> has control over the charm directory, which it temporarily cedes to the
121charm only when running a hook. Juju will occasionally do things to the contents
122of that directory that assume it is neither read nor written outside a hook, and
123the results of such interactions can only be undefined.</p>
124
125<p>The only files you should be writing into the charm directory should be written
126by hooks and accessed only by hooks. If everything in your charm directory
127went away, that should be considered a <em>management</em> failure only; the software
128installed should continue to run, using its last known good configuration, and
129should do this by virtue of never having had the opportunity to observe the
130change.</p>
131
132<p>Finally, any file written at runtime constrains all future implementations of
133the charm. When <a href="./authors-charm-upgrades.html">upgrading a charm</a>, any
134change that would cause runtime state to be overwritten will cause juju to abort
135the operation and hand over to the user for resolution. This is inconvenient for
136the users and undermines confidence in the charm.</p>
137
138<p class="note"> <strong>Note: </strong> You need to be especially aware of the following
139when writing python code:
140Python packages run without bytecode suppression will write <code>.pyc</code> files into
141the package, and subsequent attempts to move or remove the package will fail:
142the .pyc files are treated as important hook-relevant runtime state information, to be
143recorded and tracked, and the loss of their directory will put the unit into
144an upgrade error state as referenced above.</p>
145</section>
146
147 </article>
148<!--Postamble-->
149 </div>
150 </div>
151 </section>
152 </div>
153</div>
154<!--End-Postamble-->
155<!--Footer-->
156 <footer class="global clearfix" role="contentinfo">
157 <nav role="navigation">
158 <div class="footer-a">
159 <div class="clearfix">
160 <ul>
161 <li>
162 <h2><a href="/">Juju</a></h2>
163 <ul>
164 <li><a href="/charms">Charms</a></li>
165 <li><a href="/features">Features</a></li>
166 <li><a href="/deployment">Deployment</a></li>
167 </ul>
168 </li>
169 <li>
170 <h2><a href="/resources">Resources</a></h2>
171 <ul>
172 <li><a href="/resources/juju-overview/">Overview</a></li>
173 <li><a href="/docs/">Documentation</a></li>
174 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
175 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
176 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
177 <li><a href="/resources/videos/">Videos</a></li>
178 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
179 </ul>
180 </li>
181 <li>
182 <h2><a href="/community">Community</a></h2>
183 <ul>
184 <li><a href="/community/blog/">Juju Blog</a></li>
185 <li><a href="/events/">Events</a></li>
186 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
187 <li><a href="/community/charmers/">Charmers</a></li>
188 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
189 <li><a href="/docs/contributing.html">Help with documentation</a></li>
190 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
191 </ul>
192 </li>
193 <li>
194 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
195 <ul>
196 <li><a href="https://jujucharms.com/">Charm store</a></li>
197 <li><a href="/download/">Download Juju</a></li>
198 </ul>
199 </li>
200 </ul>
201 </div>
202 </div>
203 </nav>
204 <div class="legal clearfix">
205 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
206 </div>
207 </footer>
208
209<!--End-Footer-->
210<!--Scripts-->
211 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
212 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
213 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
214 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
215 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
216 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
217 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
218 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
219 <!-- google analytics -->
220 <script>
221 var _gaq = _gaq || [];
222 _gaq.push(['_setAccount', 'UA-1018242-41']);
223 _gaq.push(['_trackPageview']);
224
225 (function() {
226 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
227 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
228 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
229 })();
230 </script>
231<!--End-Scripts-->
232
233
234</body></html>
235
0236
=== added file 'htmldocs/authors-charm-config.html'
--- htmldocs/authors-charm-config.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-charm-config.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,244 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25 <body class="resources">
26<!--Header-->
27
28 <header class="banner global" role="banner">
29 <nav role="navigation" class="nav-primary nav-right">
30 <div class="logo">
31 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
32 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
33 <span>Juju</span>
34 </a>
35 </div>
36 <ul>
37 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
38 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
39 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
40 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
41 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
42 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
43 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
44 </ul>
45 <div id="box-search">
46 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
47 <label class="off-left" for="s">Search:</label>
48 <input class="form-text" type="text" value="" name="s" id="s" />
49 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
50 </form>
51 </div>
52 </nav>
53 </header>
54<!--End-Header-->
55<!--Preamble-->
56<div class="wrapper">
57 <div id="main-content" class="inner-wrapper" role="main">
58 <div class="row no-border">
59 <div class="header-navigation-secondary"></div>
60 <h2 class="pagetitle">Juju documentation</h2>
61 </div>
62 <section id="content" class="container-12">
63 <div class="grid-12 doc-container">
64 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
65 <div class="grid-9 doc-content">
66<!--End-Preamble-->
67<article>
68
69<section id="charm-configuration">
70<h1>Charm configuration</h1>
71
72<p>The optional <code>config.yaml</code> file defines how a service running the
73charm can be configured by its user.</p>
74
75<p>If it exists, it must contain a dictionary of <code>options</code>, in which
76each possible setting is named by the key and defined by the value. An option
77definition may contain any number of the following fields:</p>
78<ul>
79 <li><code>type</code> can be <code>string</code>, <code>int</code>, <code>float</code>,
80 or <code>boolean</code>. If not present, it defaults to <code>string</code>.</li>
81 <li><code>description</code> should contain an explanation of what the user might
82 achieve by altering the setting.</li>
83 <li><code>default</code> should, if present, contain a value of the appropriate
84 type. If not present it is treated as null (which is always a valid value in this
85 context); an option with no default will not normally be reported by the
86 config-get <a href="./authors-hook-environment.html">hook tool</a> unless it
87 has been explicitly set.</li>
88</ul>
89</section>
90
91<section id="picking-options">
92<h2>What to expose to users</h2>
93
94<p>The charm configuration is deliberately somewhat restrictive, in the hope of
95encouraging charmers to expose only features that are clear and comprehensible.
96The user doesn't want to configure the software - they want to configure the
97<em>service</em>, which exists at a higher level of abstraction. A charm with
98a single opinionated <code>tuning</code> option is, from this perspective,
99infinitely superior to one that exposes 6 arcane options that correspond
100directly to flags or config settings for the software.</p>
101
102<p>In short, the config is part of the user interface for the charm - it needs to be concise and
103as easy to understand and use as possible. If you're considering using base64
104encoding to slip structured data through the deliberately restrictive configuration
105language, you're probably "Doing It Wrong".</p>
106</section>
107
108<section id="default-options">
109<h2>Default configuration</h2>
110
111<p>Your charm should operate correctly with no explicit configuration settings.
112The first time someone uses your charm, they're likely to run <code>juju deploy yourcharm</code>
113and see what happens; if it doesn't work out of the box ont the first go,
114many potential users won't give it a second try.</p>
115</section>
116
117
118<h2>Warning</h2>
119
120<p class="Warning"><strong>Warning: </strong> There's a <a href="https://bugs.launchpad.net/juju-core/+bug/1194945">bug</a>
121in the service configuration CLI at the moment; if a string-typed option has an
122explicit default that is <em>not</em> the empty string, it will become
123impossible to set the value to the empty string at runtime. If your option
124needs to accept an empty string value, it should make the empty string the
125explicit default value.</p>
126</section>
127
128<section id="examples">
129<h2>Sample config.yaml files</h2>
130
131<p> The MediaWiki has some simple but useful configuration options:</p>
132<pre class="prettyprint">
133 options:
134 name:
135 default: Please set name of wiki
136 description: The name, or Title of the Wiki
137 type: string
138 skin:
139 default: vector
140 description: skin for the Wiki
141 type: string
142 logo:
143 description: URL to fetch logo from
144 type: string
145 admins:
146 description: Admin users to create, user:pass
147 type: string
148 debug:
149 default: false
150 type: boolean
151 description: turn on debugging features of mediawiki
152</pre>
153
154</section>
155
156 </article>
157</article>
158<!--Postamble-->
159 </div>
160 </div>
161 </section>
162 </div>
163</div>
164<!--End-Postamble-->
165<!--Footer-->
166 <footer class="global clearfix" role="contentinfo">
167 <nav role="navigation">
168 <div class="footer-a">
169 <div class="clearfix">
170 <ul>
171 <li>
172 <h2><a href="/">Juju</a></h2>
173 <ul>
174 <li><a href="/charms">Charms</a></li>
175 <li><a href="/features">Features</a></li>
176 <li><a href="/deployment">Deployment</a></li>
177 </ul>
178 </li>
179 <li>
180 <h2><a href="/resources">Resources</a></h2>
181 <ul>
182 <li><a href="/resources/juju-overview/">Overview</a></li>
183 <li><a href="/docs/">Documentation</a></li>
184 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
185 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
186 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
187 <li><a href="/resources/videos/">Videos</a></li>
188 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
189 </ul>
190 </li>
191 <li>
192 <h2><a href="/community">Community</a></h2>
193 <ul>
194 <li><a href="/community/blog/">Juju Blog</a></li>
195 <li><a href="/events/">Events</a></li>
196 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
197 <li><a href="/community/charmers/">Charmers</a></li>
198 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
199 <li><a href="/docs/contributing.html">Help with documentation</a></li>
200 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
201 </ul>
202 </li>
203 <li>
204 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
205 <ul>
206 <li><a href="https://jujucharms.com/">Charm store</a></li>
207 <li><a href="/download/">Download Juju</a></li>
208 </ul>
209 </li>
210 </ul>
211 </div>
212 </div>
213 </nav>
214 <div class="legal clearfix">
215 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
216 </div>
217 </footer>
218
219<!--End-Footer-->
220<!--Scripts-->
221 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
222 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
223 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
224 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
225 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
226 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
227 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
228 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
229 <!-- google analytics -->
230 <script>
231 var _gaq = _gaq || [];
232 _gaq.push(['_setAccount', 'UA-1018242-41']);
233 _gaq.push(['_trackPageview']);
234
235 (function() {
236 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
237 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
238 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
239 })();
240 </script>
241<!--End-Scripts-->
242
243
244</body></html>
0245
=== added file 'htmldocs/authors-charm-hooks.html'
--- htmldocs/authors-charm-hooks.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-charm-hooks.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,387 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25 <body class="resources">
26<!--Header-->
27
28 <header class="banner global" role="banner">
29 <nav role="navigation" class="nav-primary nav-right">
30 <div class="logo">
31 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
32 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
33 <span>Juju</span>
34 </a>
35 </div>
36 <ul>
37 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
38 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
39 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
40 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
41 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
42 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
43 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
44 </ul>
45 <div id="box-search">
46 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
47 <label class="off-left" for="s">Search:</label>
48 <input class="form-text" type="text" value="" name="s" id="s" />
49 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
50 </form>
51 </div>
52 </nav>
53 </header>
54<!--End-Header-->
55<!--Preamble-->
56<div class="wrapper">
57 <div id="main-content" class="inner-wrapper" role="main">
58 <div class="row no-border">
59 <div class="header-navigation-secondary"></div>
60 <h2 class="pagetitle">Juju documentation</h2>
61 </div>
62 <section id="content" class="container-12">
63 <div class="grid-12 doc-container">
64 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
65 <div class="grid-9 doc-content">
66<!--End-Preamble-->
67<article>
68<section id="charm-hooks">
69<h1>Charm hooks</h1>
70
71<p>A service unit's direct action is entirely defined by its charm's hooks. Hooks
72are executable files in a charm's <code>hooks</code> directory; hooks with particular
73names (see below) will be invoked by the juju unit agent at particular times, and thereby cause
74changes to the world.</p>
75
76<p>Whenever a hook-worthy event takes place, the unit agent first checks whether
77that hook is being <a href="./authors-hook-debug.html">debugged</a>, and if so
78hands over control to the user. Otherwise, it tries to find a hook with precisely
79the right name. If the hook doesn't exist, the agent continues without complaint;
80if it does, it is invoked without arguments in a specific
81<a href="./authors-hook-environment.html">environment</a>, and its output is written
82to the unit agent's log. If it returns a non-zero exit code, the agent enters an
83<a href="./authors-hook-errors.html">error state</a> and awaits user intervention.</p>
84
85<p>The agent will also enter an error state if the unit agent process is aborted
86during hook execution.</p>
87
88<p>There are two types of hooks, described in more detail in the following sections.</p>
89
90<p class = "note"><strong>Note: </strong>None of the unit or relation hooks are required; if you don't implement a hook,
91it 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>
92</section>
93
94<section id="unit-hooks">
95<h2>Unit hooks</h2>
96
97<p>There are 5 &quot;unit hooks&quot; with predefined names that can be implemented
98by any charm:</p>
99<ul>
100 <li>install</li>
101 <li>config-changed</li>
102 <li>start</li>
103 <li>upgrade-charm</li>
104 <li>stop</li>
105</ul>
106
107<p>For every relation defined by a charm, an additional 4 &quot;relation hooks&quot;
108can be implemented, named after the charm relation:</p>
109<ul>
110 <li>&lt;name&gt;-relation-joined</li>
111 <li>&lt;name&gt;-relation-changed</li>
112 <li>&lt;name&gt;-relation-departed</li>
113 <li>&lt;name&gt;-relation-broken</li>
114</ul>
115
116<h3 id="hook-install">install</h3>
117
118<p><code>install</code> runs just once, before any other hook. It should be used to
119perform one-time setup operations only.</p>
120
121<h3 id="hook-config-changed">config-changed</h3>
122
123<p><code>config-changed</code> runs in several different situations.</p>
124<ul>
125 <li>immediately after "install"</li>
126 <li>immediately after "upgrade-charm"</li>
127 <li>at least once when the unit agent is restarted (but, if the unit is in
128 an <a href="./authors-hook-errors.html">error state</a>, it won't be run
129 until after the error state is cleared).</li>
130</ul>
131<p>It cannot assume that the software has already been started; it should not
132start stopped software, but should (if appropriate) restart running software
133to take configuration changes into account.</p>
134
135<h3 id="hook-start">start</h3>
136<p><code>start</code> runs immediately after the first <code>config-changed</code>
137hook. It should be used to ensure the charm's software is running. Note that the
138charm's software should be configured so as to persist through reboots without further
139intervention on juju's part.
140
141<h3 id="hook-upgrade-charm">upgrade-charm</h3>
142
143<p><code>upgrade-charm</code> runs immediately after any
144<a href="./authors-charm-upgrades.html">upgrade</a> operation that does <em>not</em>
145itself interrupt an existing <a href="./authors-hook-errors.html">error state.</a>. It
146should be used to reconcile local state written by some other version of the charm into
147whatever form it needs to take to be manipulated by the current version.</p>
148
149<p>While the forced upgrade functionality is intended as a developer tool, and is
150not generally suitable for end users, it's somewhat optimistic to depend on the
151functionality never being abused. In light of this, if you need to run an
152<code>upgrade-charm</code> hook before your other hooks will work correctly,
153it may be wise to preface all your other hooks with a quick call to your
154(idempotent)<code>upgrade-charm</code>.</p>
155
156<h3 id="hook-stop">stop</h3>
157
158<p><code>stop</code> runs immediately before the end of the unit's destruction
159sequence. It should be used to ensure that the charm's software is not running, and
160will not start again on reboot.</p>
161</section>
162
163<section id="relation-hooks">
164<h2>Relation hooks</h2>
165
166<p>Units will only participate in relations after they're been started, and before
167they've been stopped. Within that time window, the unit may participate in several
168different relations at a time, <em>including</em> multiple relations with the
169same name.</p>
170
171<p>To illustrate, consider a database service that will be used by multiple client
172services. Units of a single client service will surely want to connect to, and
173use, the same database; but if units of another client service were to use that
174same database, the consequences could be catastrophic for all concerned.</p>
175
176<p>If juju respected the <code>limit</code> field in relation
177<a href="./authors-charm-metadata.html">metadata</a>, it would be possible
178to work around this, but it's not a high-priority
179<a href="https://bugs.launchpad.net/bugs/1089297">bug</a>: most provider services
180<em>should</em> be able to handle multiple requirers anyway; and most requirers will
181only be connected to one provider anyway.</p>
182
183<p>When a unit running a given charm participates in a given relation, it runs at
184least three hooks for every remote unit it becomes aware of in that relation.</p>
185</section>
186
187<section id="hook-relation-joined">
188<h3>&lt;name&gt;-relation-joined</h3>
189
190<p><code>&lt;name&gt;-relation-joined</code> is run once only, when that remote
191unit is first observed by the unit. It should be used to <code>relation-set</code> any
192local unit settings that can be determined using no more than the name of the joining
193unit and the remote <code>private-address</code> setting, which is always available
194when the relation is created and is by convention not deleted.</p>
195
196<p>You should not depend upon any other relation settings in the -joined hook
197because they're not guaranteed to be present; if you need more information
198you should wait for a -changed hook that presents the right information.</p>
199</section>
200
201<section id="hook-relation-changed">
202<h3>&lt;name&gt;-relation-changed</h3>
203
204<p><code>&lt;name&gt;-relation-changed</code> is always run once, after -joined, and
205will subsequently be run whenever that remote unit changes its settings for the
206relation. It should be the <em>only</em> hook that <em>relies</em> upon remote relation
207settings from <code>relation-get</code>, and it should <em>not</em> error if the
208settings are incomplete: you can guarantee that when the remote unit changes its
209settings, the hook will be run again.</p>
210
211<p>The settings that you can get, and that you should set, are determined by
212the relation's <a href="./authors-charm-interfaces.html">interface</a>.</p>
213</section>
214
215<section id="hook-relation-departed">
216<h3>&lt;name&gt;-relation-departed</h3>
217
218<p><code>&lt;name&gt;-relation-departed</code> is run once only, when the remote unit
219is known to be leaving the relation; it will only run once at least one -changed has
220been run, and after -departed has run, no further -changeds will be run. This should
221be used to remove all references to the remote unit, because there's no guarantee that
222it's still part of the system; it's perfectly probable (although not guaranteed) that
223the system running that unit has already shut down.</p>
224
225<p>When a unit's own participation in a relation is known to be ending, the unit
226agent continues to uphold the ordering guarantees above; but within those
227constraints, it will run the fewest possible hooks to notify the charm of the
228departure of each individual remote unit.</p>
229
230<p>Once all necessary -departed hooks have been run for such a relation, the unit
231agent will run the final relation hook:</p>
232</section>
233
234<section id="hook-relation-broken">
235<h3>&lt;name&gt;-relation-broken</h3>
236
237<p><code>&lt;name&gt;-relation-broken</code> indicates that the current relation is
238no longer valid, and that the charm's software must be configured as though the
239relation had never existed. It will only be called after every necessary -departed
240hook has been run; if it's being executed, you can be sure that no remote units are
241currently known locally.</p>
242
243<p>It is important to note that the -broken hook might run even if no other units
244have ever joined the relation. This is not a bug: even if no remote units have ever
245joined, the fact of the unit's participation can be detected in other hooks via the
246<code>relation-ids</code> tool, and the -broken hook needs to execute to give the
247charm an opportunity to clean up any optimistically-generated configuration.</p>
248
249<p>And, again, it's important to internalise the fact that there may be multiple
250runtime relations in play with the same name, and that they're independent:
251one -broken hook does not mean that <em>every</em> such relation is broken.</p>
252</section>
253
254<section id="writing-hooks">
255<h2>Writing hooks</h2>
256
257<p>If you follow the <a href="./authors-charm-writing.html">tutorial</a>, you'll
258get a good sense of the basics. To fill out your knowledge, you'll want to study
259the hook <a href="./authors-hook-environment.html">environment and tools</a>, and
260to experiment with <a href="./authors-hook-debug.html">debug-hooks</a>.</p>
261
262<p>Independent of the nuts and bolts, though, good hooks display a number of
263useful high-level properties:</p>
264<ul>
265 <li>They are <em>idempotent</em>: that is to say that there should be no
266 observable difference between running a hook once, and running it N times
267 in a row. If this property does not hold, you are likely to be making your
268 own life unnecesarily difficult: apart from anything else, the average user's
269 most likely first response to a failed hook will be to try to run it again
270 (if they don't just skip it).</li>
271
272 <li>They are <em>easy to read</em> and understand. It's tempting to write a
273 single file that does everything, and which just calls different functions
274 internally depending on the value of <code>argv[0]</code>, and to symlink that
275 one file for every hook; but such structures quickly become unwieldy.<br />
276 The time taken to write a library, separate from the hooks, is very likely
277 to be well spent: it lets you write single hooks that are clear and focused,
278 and insulates the maintainer from irrelevant details.</li>
279
280 <li>Where possible, they reuse
281 <a href="https://launchpad.net/charm-tools">common code</a> already written to
282 ease or solve common use cases.</li>
283
284 <li>They do not return <a href="./authors-hook-errors.html">errors</a> unless
285 there is a good reason to believe that they cannot be resolved without user
286 intervention. Doing so is an admission of defeat: a user who sees your charm
287 returning an error state is unlikely to have the specific expertise necessary
288 to resolve it. If you have to return an error, please be sure to at least write
289 any context you can to the log before you do so.</li>
290
291 <li>They write only <em>very</em> sparingly to the
292 <a href="./authors-charm-contents.html">charm directory</a>.</li>
293</ul>
294
295<p>We recommend you also familiarize yourself with the
296<a href="./authors-charm-best-practice.html">best practices</a> and, if you
297plan to distribute your charm, the
298<a href="./authors-charm-policy.html">charm store policy</a>.</p>
299</section>
300 </article>
301<!--Postamble-->
302 </div>
303 </div>
304 </section>
305 </div>
306</div>
307<!--End-Postamble-->
308<!--Footer-->
309 <footer class="global clearfix" role="contentinfo">
310 <nav role="navigation">
311 <div class="footer-a">
312 <div class="clearfix">
313 <ul>
314 <li>
315 <h2><a href="/">Juju</a></h2>
316 <ul>
317 <li><a href="/charms">Charms</a></li>
318 <li><a href="/features">Features</a></li>
319 <li><a href="/deployment">Deployment</a></li>
320 </ul>
321 </li>
322 <li>
323 <h2><a href="/resources">Resources</a></h2>
324 <ul>
325 <li><a href="/resources/juju-overview/">Overview</a></li>
326 <li><a href="/docs/">Documentation</a></li>
327 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
328 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
329 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
330 <li><a href="/resources/videos/">Videos</a></li>
331 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
332 </ul>
333 </li>
334 <li>
335 <h2><a href="/community">Community</a></h2>
336 <ul>
337 <li><a href="/community/blog/">Juju Blog</a></li>
338 <li><a href="/events/">Events</a></li>
339 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
340 <li><a href="/community/charmers/">Charmers</a></li>
341 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
342 <li><a href="/docs/contributing.html">Help with documentation</a></li>
343 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
344 </ul>
345 </li>
346 <li>
347 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
348 <ul>
349 <li><a href="https://jujucharms.com/">Charm store</a></li>
350 <li><a href="/download/">Download Juju</a></li>
351 </ul>
352 </li>
353 </ul>
354 </div>
355 </div>
356 </nav>
357 <div class="legal clearfix">
358 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
359 </div>
360 </footer>
361
362<!--End-Footer-->
363<!--Scripts-->
364 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
365 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
366 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
367 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
368 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
369 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
370 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
371 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
372 <!-- google analytics -->
373 <script>
374 var _gaq = _gaq || [];
375 _gaq.push(['_setAccount', 'UA-1018242-41']);
376 _gaq.push(['_trackPageview']);
377
378 (function() {
379 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
380 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
381 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
382 })();
383 </script>
384<!--End-Scripts-->
385
386
387</body></html>
0388
=== modified file 'htmldocs/authors-charm-icon.html'
--- htmldocs/authors-charm-icon.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-charm-icon.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -242,4 +244,6 @@
242<!--End-Scripts-->244<!--End-Scripts-->
243245
244246
247
248
245</body></html>249</body></html>
246250
=== added file 'htmldocs/authors-charm-interfaces.html'
--- htmldocs/authors-charm-interfaces.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-charm-interfaces.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,340 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24 <body class="resources">
25<!--Header-->
26
27 <header class="banner global" role="banner">
28 <nav role="navigation" class="nav-primary nav-right">
29 <div class="logo">
30 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
31 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
32 <span>Juju</span>
33 </a>
34 </div>
35 <ul>
36 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
37 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
38 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
39 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
40 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
41 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
42 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
43 </ul>
44 <div id="box-search">
45 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
46 <label class="off-left" for="s">Search:</label>
47 <input class="form-text" type="text" value="" name="s" id="s" />
48 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
49 </form>
50 </div>
51 </nav>
52 </header>
53<!--End-Header-->
54<!--Preamble-->
55<div class="wrapper">
56 <div id="main-content" class="inner-wrapper" role="main">
57 <div class="row no-border">
58 <div class="header-navigation-secondary"></div>
59 <h2 class="pagetitle">Juju documentation</h2>
60 </div>
61 <section id="content" class="container-12">
62 <div class="grid-12 doc-container">
63 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
64 <div class="grid-9 doc-content">
65<!--End-Preamble-->
66<article>
67<section id="relation-interfaces">
68<h1>Charm relation interfaces</h1>
69
70<p>As described <a href="./authors-charm-metadata.html">elsewhere</a>, picking an
71interface is a strong statement; whether you're providing or requiring a given
72interface, you need to be compatible with all providers and requirers of that
73interface.</p>
74
75<p>In short, this means that you need to set the same settings as do all the
76other charms with the same role for the interface; and you should only expect
77to be able to read those settings set by the other charms with the counterpart
78role.</p>
79</section>
80
81<section id="determining-interfaces">
82<h2>Determining charm relation interfaces</h2>
83
84<p>This is in some respects an uncomfortable situation to be in. If two charms
85declare compatibility, but fail when run together due to disagreement about
86the actual definition of that interface; it's not immediately clear which is
87at fault, because the &quot;standard&quot; is defined only by consensus among the
88existing charms that provide or require that interface.</p>
89
90<p>On the upside, this means that reading any charm that already implements the
91interface is <em>theoretically</em> good enough to figure it out; in practice, it's
92sometimes hard to understand the code in isolation. The incontrovertible way
93to determine the protocol defined by an interface is to deploy a pair of charms
94that already use that interface, and <a href="./authors-hook-debug.html">intercept</a>
95the communications between them.</p>
96
97<pre class="prettyprint">
98juju deploy mongodb
99juju deploy node-app
100</pre>
101
102<p>In a separate window, once node-app/0 reports <code>started</code> status:</p>
103
104<pre class="prettyprint">
105juju debug-hooks node-app/0 *
106</pre>
107
108<p>This opens a tmux session; when the unit wants to run a hook, it'll create a
109new window in which you can interactively inspect the environment. In a relation
110hook, you'll want to run the following commands:</p>
111
112<pre class="prettyprint">
113# discover what's been set by the unit on the other end of the relation:
114$ relation-get $JUJU_REMOTE_UNIT
115
116address: example.com:37070
117username: bob
118password: seekrit
119
120# get the local unit's relation settings, for comparison afterwards:
121$ relation-get $JUJU_UNIT_NAME
122# (no results)
123
124# run the actual hook:
125$ ./hooks/$JUJU_HOOK_NAME
126
127# get the local settings again, to see if any changes were made by the hook:
128$ relation-get $JUJU_UNIT_NAME
129# (no results)
130</pre>
131
132<p>...and then close that tmux window and wait to see if another one opens for the
133next hook. Assuming you started debugging before creating the relation, you'll
134see exactly one -joined hook, and at least one -changed hook, and you're only
135done when new -changed hooks stop popping up.</p>
136
137<p>The relation-get <a href="./authors-hook-environment.html">tool</a> accepts a
138<code>--format</code> parameter that accepts <code>json</code> and <code>yaml</code>
139values, in case you want to consume them programmatically.</p>
140
141<p>In practice, what you'll most likely find is that one side sets a couple of keys,
142the other side gets them, and that's that... in no more than two changed hooks.
143Be aware, though, that it is possible in principle for an interface to imply
144a more demanding interface, involving multiple rounds of setting and getting.</p>
145</section>
146
147<section id="documenting-interfaces">
148<h2>Documenting charm relation interfaces</h2>
149
150<p>In light of the above, there is a clear need for some means of documenting the
151above. The optional <code>gets</code> and <code>sets</code> fields in a charm's
152relation <a href="./authors-charm-metadata.html">metadata</a> should be used for
153this purpose.</p>
154
155<p>Please be especially careful to note that this format is <em>not</em> checked
156by juju today. But it does encode the information that's most helpful to your fellow
157charmers, and by doing so in a consistent and machine-readable format we maximise
158our chances of one day making use of this information automatically.</p>
159
160<p>The simple form, which will be the most common form, looks like this:</p>
161
162<pre class="prettyprint">
163name: python-django
164...
165provides:
166 website:
167 interface: http
168 sets: [host, post]
169</pre>
170
171<p>...and this:</p>
172
173<pre class="prettyprint">
174name: haproxy
175...
176requires:
177 reverseproxy:
178 interface: http
179 gets: [host, port]
180</pre>
181
182<p>...indicating that a relation can surely be made between python-django and haproxy,
183because the <code>website</code> relation unconditionally sets the keys that the
184<code>reverseproxy</code> relation requires in order to function.</p>
185
186<p>The more complex form, which is only required for complex protocols, is defined
187as follows:</p>
188<ul>
189 <li><code>gets</code> holds a list of settings keys that must all be set by
190 each unit on the remote end of a relation in order for the local unit to
191 function.</li>
192 <li><code>sets</code> holds a list of settings that will be set by each unit
193 of the local charm. These settings can either be a plain string, indicating that
194 no remote settings need exist for this key to be written; or a single-element
195 map, with the setting to be written mapped to the remote settings that must
196 exist for this to be done.</li>
197</ul>
198<p>For example, consider charms <code>a</code> and <code>b</code>, which do the
199following handshake dance before they can complete their configuration:</p>
200<ul>
201 <li><code>b/0</code> starts running -joined, which takes a while.</li>
202 <li><code>a/0</code> runs -joined and -changed before <code>b/0</code> has
203 finished -joined. In the -changed hook, it fails to find the remote settings
204 it expected, and exits without error.</li>
205 <li><code>b/0</code> finishes -joined, setting <code>X</code> and <code>Y</code>,
206 thus triggering -changed on <code>a/0</code>.</li>
207 <li><code>a/0</code> sets <code>P</code> and <code>Q</code> in response, causing
208 a -changed on <code>b/0</code>.</li>
209 <li><code>b/0</code> completes local configuration using <code>P</code> and
210 <code>Q</code>, and sets <code>Z</code>, triggering a final -changed on
211 <code>a/0</code>.</li>
212 <li><code>a/0</code> completes local configuration using <code>X</code>,
213 <code>Y</code>, and <code>Z</code>, and sets nothing.</li>
214</ul>
215<p>For example, in the hypothetical complex protocol described in the previous
216section, the metadata for charm <code>a</code> above would contain:</p>
217
218<pre class="prettyprint">
219requires:
220 ab:
221 interface: ab
222 sets:
223 - P: [X, Y]
224 - Q: [X, Y]
225 gets: [X, Y, Z]
226</pre>
227
228<p>...indicating that <code>P</code> and <code>Q</code> will only be written when
229<code>X</code> and <code>Y</code> have; and that configuration will not complete
230without <code>X</code>, <code>Y</code> and <code>Z</code>. Meanwhile charm
231<code>b</code> would contain:</p>
232
233<pre class="prettyprint">
234provides:
235 ab:
236 interface: ab
237 sets:
238 - X
239 - Y
240 - Z: [P, Q]
241 gets: [P, Q]
242</pre>
243
244<p>...indicating that it will always write <code>X</code> and <code>Y</code>, and
245that <code>Z</code> will be written when <code>P</code> and <code>Q</code> have; and
246that configuration will not be complete without <code>P</code> and <code>Q</code>.</p>
247
248<p>Peer relations are a different matter, in that peer relations are the mechanism
249by which service units share information internally. It's not unusual for peer
250service units to maintain convenient caches of distributed information in their
251own peer settings, and this inevitably involves generating settings keys at
252runtime.</p>
253</section>
254</article>
255<!--Postamble-->
256 </div>
257 </div>
258 </section>
259 </div>
260</div>
261<!--End-Postamble-->
262<!--Footer-->
263 <footer class="global clearfix" role="contentinfo">
264 <nav role="navigation">
265 <div class="footer-a">
266 <div class="clearfix">
267 <ul>
268 <li>
269 <h2><a href="/">Juju</a></h2>
270 <ul>
271 <li><a href="/charms">Charms</a></li>
272 <li><a href="/features">Features</a></li>
273 <li><a href="/deployment">Deployment</a></li>
274 </ul>
275 </li>
276 <li>
277 <h2><a href="/resources">Resources</a></h2>
278 <ul>
279 <li><a href="/resources/juju-overview/">Overview</a></li>
280 <li><a href="/docs/">Documentation</a></li>
281 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
282 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
283 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
284 <li><a href="/resources/videos/">Videos</a></li>
285 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
286 </ul>
287 </li>
288 <li>
289 <h2><a href="/community">Community</a></h2>
290 <ul>
291 <li><a href="/community/blog/">Juju Blog</a></li>
292 <li><a href="/events/">Events</a></li>
293 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
294 <li><a href="/community/charmers/">Charmers</a></li>
295 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
296 <li><a href="/docs/contributing.html">Help with documentation</a></li>
297 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
298 </ul>
299 </li>
300 <li>
301 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
302 <ul>
303 <li><a href="https://jujucharms.com/">Charm store</a></li>
304 <li><a href="/download/">Download Juju</a></li>
305 </ul>
306 </li>
307 </ul>
308 </div>
309 </div>
310 </nav>
311 <div class="legal clearfix">
312 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
313 </div>
314 </footer>
315
316<!--End-Footer-->
317<!--Scripts-->
318 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
319 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
320 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
321 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
322 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
323 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
324 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
325 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
326 <!-- google analytics -->
327 <script>
328 var _gaq = _gaq || [];
329 _gaq.push(['_setAccount', 'UA-1018242-41']);
330 _gaq.push(['_trackPageview']);
331
332 (function() {
333 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
334 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
335 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
336 })();
337 </script>
338<!--End-Scripts-->
339
340</body></html>
0341
=== added file 'htmldocs/authors-charm-metadata.html'
--- htmldocs/authors-charm-metadata.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-charm-metadata.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,376 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25 <body class="resources">
26<!--Header-->
27
28 <header class="banner global" role="banner">
29 <nav role="navigation" class="nav-primary nav-right">
30 <div class="logo">
31 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
32 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
33 <span>Juju</span>
34 </a>
35 </div>
36 <ul>
37 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
38 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
39 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
40 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
41 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
42 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
43 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
44 </ul>
45 <div id="box-search">
46 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
47 <label class="off-left" for="s">Search:</label>
48 <input class="form-text" type="text" value="" name="s" id="s" />
49 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
50 </form>
51 </div>
52 </nav>
53 </header>
54<!--End-Header-->
55<!--Preamble-->
56<div class="wrapper">
57 <div id="main-content" class="inner-wrapper" role="main">
58 <div class="row no-border">
59 <div class="header-navigation-secondary"></div>
60 <h2 class="pagetitle">Juju documentation</h2>
61 </div>
62 <section id="content" class="container-12">
63 <div class="grid-12 doc-container">
64 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
65 <div class="grid-9 doc-content">
66<!--End-Preamble-->
67<article>
68
69<section id="charm-metadata">
70<h1>Charm metadata</h1>
71
72<p>The only file that must be present in a charm is <code>metadata.yaml</code>, in
73the root directory. A metadata file must be a valid yaml dictionary, containing at
74least the following fields:</p>
75<ul>
76 <li><code>name</code> is the charm name, which is used to form the charm URL.
77 It must contain only <code>a-z</code>, <code>0-9</code>, and <code>-</code>;
78 must start with <code>a-z</code>; must not end with a <code>-</code>; and may
79 only end with digits if the digits are <em>not</em> directly preceded by a
80 space. Stick with names like <code>foo</code> and <code>foo-bar-baz</code>
81 and you needn't pay further attention to the restrictions.</li>
82 <li><code>summary</code> is a one-line description of the charm.</li>
83 <li><code>description</code> is a long-form description of the charm and its
84 features. It will also appear in the juju GUI.</li>
85</ul>
86
87<p>Here's a valid metadata file:</p>
88<pre class="prettyprint lang-yaml">
89name: minecraft
90summary: Minecraft Server
91description: |
92 Will deploy OpenJDK 6 JRE and the latest Minecraft server
93</pre>
94
95<p>With only those fields, a metadata file is valid, but not very useful. Charms
96for use in the Charm Store should always set the following fields as well,
97for categorization and display in the GUI:</p>
98<ul>
99 <li><code>maintainer</code> is the name and email address for the main point
100 of contact for the development and maintenance of the charm. Or, at least, it
101 should be: in frequent practice, it's just a name. Please update your charms
102 as you get the opportunity.</li>
103 <li><code>categories</code> is a list containing one or more of the following:
104 <ul>
105 <li>applications</li>
106 <li>app-servers</li>
107 <li>cache-proxy</li>
108 <li>databases</li>
109 <li>file-servers</li>
110 <li>mis</li>
111 </ul>
112 <p>In almost all cases, only one category will be appropriate. The categories help keep the Charm Store organised.</p></li>
113</ul>
114
115<p>Finally, a metadata file defines the charm's relations, and whether it's
116designed for deployment as a <a href="./authors-subordinate-services.html">subordinate service</a>.</p>
117<ul>
118 <li><code>subordinate</code> should be set to true if the charm is a
119 subordinate. If omitted, the charm will be presumed not to be subordinate.</li>
120 <li><code>provides</code>, <code>requires</code>, and <code>peers</code> define
121 the various relations the charm will participate in.</li>
122 <li>if the charm is subordinate, it must contain at least one <code>requires</code>
123 relation with container scope.</li>
124</ul>
125
126<p>Other field names should be considered to be reserved; please don't use any
127not listed above to avoid issues with future versions of Juju.</p>
128</section>
129
130<section id="simple-relations">
131<h2>Simple relations</h2>
132
133<p>The <code>provides</code> and <code>requires</code> keys are used to define
134pairings of charms that are likely to be fruitful. Consider a simple mongodb
135charm's metadata:</p>
136
137<pre class="prettyprint lang-yaml">
138name: my-mongodb
139...
140provides:
141 server: mongodb
142</pre>
143
144<p>...and that of a simple node.js application charm:</p>
145
146<pre class="prettyprint lang-yaml">
147name: my-node-app
148...
149requires:
150 database: mongodb
151provides:
152 website: http
153</pre>
154
155<p>Put together, these files indicate that a relation can be made between services
156running the respective charms. The my-mongodb charm <code>provides</code> a relation named
157<code>server</code> with the <code>mongodb</code> interface, and the my-node-app charm
158<code>requires</code> a relation named <code>database</code> with the <code>mongodb</code>
159interface.</p>
160
161<p>The my-node-app charm also <code>provides</code> a relation named <code>website</code>
162with the <code>http</code> interface, but that's irrelevant to the mongodb charm. (But an
163haproxy charm might well define, say, <code>reverseproxy</code>, that <code>requires</code>
164the <code>http</code> interface provided by my-node-app.)</p>
165</section>
166
167<section id="relation-interfaces">
168<h2>Relation interfaces</h2>
169
170<p>An interface is a string that must only contain <code>a-z</code> and <code>-</code>,
171and neither start nor end with <code>-</code>. It's the single determiner of
172compatibility between charms; and it carries with it nothing more than a mutual
173promise that the provider and requirer somehow know the communication protocol
174implied by the name.</p>
175
176<p>So, the relation namespace is essentially unrestricted (with one enforced
177exception: you may not <em>provide</em> a relation named <code>juju</code>, or
178starting with <code>juju-</code>). This allows for rapid development in some
179situations; but, in the example above, there is a potential problem: we've picked
180<em>two</em> interface names that already have meanings in the charm ecosystem,
181and that means we have to be <a href="./authors-charm-interfaces.html">compatible</a>;
182but that's a concern for a bit later, when we're actually writing the relation hooks.</p>
183</section>
184
185<section id="peer-relations">
186<h2>Peer relations</h2>
187
188<p>Alongside <code>provides</code> and <code>requires</code>, charms can declare
189relations under <code>peers</code>. Where <code>provides</code> relations integrate
190with <code>requires</code> ones, such that providers respond to requirers and vice
191versa, the <code>peers</code> relation causes each unit of a single service to
192respond to the other units in the same service. A peer relation is otherwise defined
193in exactly the same way as any other relation.</p>
194</section>
195
196<section id="relation-config">
197<h2>Configuring relations</h2>
198
199<p>There's an alternative syntax for specifying relations, which allows you to
200set 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>
201<ul>
202 <li><code>scope</code> defaults to <code>global</code>, but may be set to
203 <code>container</code>. The scope controls the set of remote units that are
204 reported to the unit as members of the relation: container-scoped relations
205 are restricted to reporting details of a single principal unit to a single
206 subordinate, and vice versa, while global relations consider all possible
207 remote units.<br />
208 <a href="authors-charm-subordinates.html">Subordinate</a> charms are only
209 valid if they have at least one <code>requires</code> relation with
210 <code>container</code> scope.</li>
211 <li><code>limit</code> is ignored by juju, but if present should be a positive
212 integer N indicating that the charm is not designed to use this interface in more
213 than N relations at once.<br />
214 For example, if you're writing a really simple exploratory charm for your
215 particular data store, you could just create a single shared store and
216 write the same access credentials for every relation. A limit of 1 is
217 thus useful in that it does <em>document</em> the restriction, even though
218 it's not automatically enforced today.</li>
219 <li><code>optional</code> is ignored by juju, but if present should only be
220 set to true, on <code>requires</code> relations, to indicate that the charm
221 can still function effectively without having those relations added.<br />
222 For example, the my-node-app charm might also define:<br />
223<pre class="prettyprint lang-yaml">
224requires:
225 database: mongodb
226 memcache:
227 interface: memcached
228 optional: true
229</code></pre><br />
230 ...to indicate that it can integrate with memcached if it's available, but
231 that it can't be expected to do anything useful without a mongodb service
232 available.</li>
233 <li><code>gets</code> and <code>sets</code> are ignored by juju at present,
234 but are valuable <a href="./authors-charm-interfaces.html">documentation</a>.</li>
235</ul>
236
237</section>
238
239<section id="examples">
240<h2>Sample metadata.yaml files</h2>
241<p> The MySQL charm metadata: </p>
242<pre class="prettyprint">
243 name: mysql
244 summary: MySQL is a fast, stable and true multi-user, multi-threaded SQL database
245 maintainer: Marco Ceppi
246 description: |
247 MySQL is a fast, stable and true multi-user, multi-threaded SQL database
248 server. SQL (Structured Query Language) is the most popular database query
249 language in the world. The main goals of MySQL are speed, robustness and
250 ease of use.
251 categories:
252 - databases
253 provides:
254 db:
255 interface: mysql
256 db-admin:
257 interface: mysql-root
258 shared-db:
259 interface: mysql-shared
260 master:
261 interface: mysql-oneway-replication
262 munin:
263 interface: munin-node
264 monitors:
265 interface: monitors
266 local-monitors:
267 interface: local-monitors
268 scope: container
269
270peers:
271 cluster:
272 interface: mysql-ha
273
274requires:
275 slave:
276 interface: mysql-oneway-replication
277 ceph:
278 interface: ceph-client
279 ha:
280 interface: hacluster
281 scope: container
282</pre>
283
284
285</section>
286
287
288</article>
289<!--Postamble-->
290 </div>
291 </div>
292 </section>
293 </div>
294</div>
295<!--End-Postamble-->
296<!--Footer-->
297 <footer class="global clearfix" role="contentinfo">
298 <nav role="navigation">
299 <div class="footer-a">
300 <div class="clearfix">
301 <ul>
302 <li>
303 <h2><a href="/">Juju</a></h2>
304 <ul>
305 <li><a href="/charms">Charms</a></li>
306 <li><a href="/features">Features</a></li>
307 <li><a href="/deployment">Deployment</a></li>
308 </ul>
309 </li>
310 <li>
311 <h2><a href="/resources">Resources</a></h2>
312 <ul>
313 <li><a href="/resources/juju-overview/">Overview</a></li>
314 <li><a href="/docs/">Documentation</a></li>
315 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
316 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
317 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
318 <li><a href="/resources/videos/">Videos</a></li>
319 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
320 </ul>
321 </li>
322 <li>
323 <h2><a href="/community">Community</a></h2>
324 <ul>
325 <li><a href="/community/blog/">Juju Blog</a></li>
326 <li><a href="/events/">Events</a></li>
327 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
328 <li><a href="/community/charmers/">Charmers</a></li>
329 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
330 <li><a href="/docs/contributing.html">Help with documentation</a></li>
331 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
332 </ul>
333 </li>
334 <li>
335 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
336 <ul>
337 <li><a href="https://jujucharms.com/">Charm store</a></li>
338 <li><a href="/download/">Download Juju</a></li>
339 </ul>
340 </li>
341 </ul>
342 </div>
343 </div>
344 </nav>
345 <div class="legal clearfix">
346 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
347 </div>
348 </footer>
349
350<!--End-Footer-->
351<!--Scripts-->
352 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
353 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
354 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
355 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
356 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
357 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
358 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
359 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
360 <!-- google analytics -->
361 <script>
362 var _gaq = _gaq || [];
363 _gaq.push(['_setAccount', 'UA-1018242-41']);
364 _gaq.push(['_trackPageview']);
365
366 (function() {
367 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
368 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
369 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
370 })();
371 </script>
372<!--End-Scripts-->
373
374
375</body></html>
376
0377
=== modified file 'htmldocs/authors-charm-policy.html'
--- htmldocs/authors-charm-policy.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-charm-policy.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -94,7 +96,7 @@
94 96
95 <h2>metadata.yaml</h2>97 <h2>metadata.yaml</h2>
96 98
97 <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>99 <p>This file is an <a href="authors-charm-contents.html">important component</a> of a charm.</p>
98 <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>100 <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>
99101
100102
@@ -212,4 +214,6 @@
212<!--End-Scripts-->214<!--End-Scripts-->
213215
214216
217
218
215</body></html>219</body></html>
216220
=== modified file 'htmldocs/authors-charm-quality.html'
--- htmldocs/authors-charm-quality.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-charm-quality.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -295,4 +297,6 @@
295<!--End-Scripts-->297<!--End-Scripts-->
296298
297299
300
301
298</body></html>302</body></html>
299303
=== modified file 'htmldocs/authors-charm-store.html'
--- htmldocs/authors-charm-store.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-charm-store.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -297,4 +299,6 @@
297<!--End-Scripts-->299<!--End-Scripts-->
298300
299301
302
303
300</body></html>304</body></html>
301305
=== added file 'htmldocs/authors-charm-upgrades.html'
--- htmldocs/authors-charm-upgrades.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-charm-upgrades.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,212 @@
1<!DOCTYPE html>
2<html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>Juju Documentation - Charm Upgrades</title>
6 <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' />
7 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" />
8 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" />
9 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" />
10 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" />
11 <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' />
12 <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/>
13
14 <!--[if lt IE 9]>
15 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
16 <![endif]-->
17</head>
18 <body class="resources">
19 <header class="global clearfix" role="banner">
20 <div class="header-navigation">
21 <div>
22 <nav role="navigation">
23 <ul>
24 <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li>
25 <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li>
26 <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
27 <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li>
28 <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li>
29 <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li>
30 <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li>
31 <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li>
32 <li>
33 <form id="form-search" method="get" action="https://juju.ubuntu.com/">
34 <fieldset>
35 <input id="input-search" type="text" name="s" value="Search" />
36 </fieldset>
37 </form>
38 </li>
39 </ul>
40 </nav>
41 </div>
42 </div>
43 <div class="header-content">
44 <div class="clearfix">
45 <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">
46 <div class="header-navigation-secondary"></div>
47 <div class="header-image"></div>
48 <h1>Resources</h1>
49 <h2>A collection of some of the most important online references for Juju users and developers.</h2>
50 </div>
51 </div>
52</header>
53
54 <section id="content" class="container-12">
55 <div class="grid-12 doc-container">
56 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
57 <div class="grid-9 doc-content">
58 <article>
59
60
61<!--Actual docs start here-->
62
63<section id="charm-upgrades">
64<h1>Charm upgrades</h1>
65
66<p>A service's charm can be changed at runtime with the <code>upgrade-charm</code>
67command. By default, it changes to the latest available version of the same charm; if
68<code>--revision</code> is specified, it changes to that revision of the same charm; and
69if <code>--switch</code> is specified it changes to any arbitrary charm, inferred from the
70argument in the same way as in <code>juju deploy</code>.</p>
71
72<p>For a charm to replace another, though, there is a minimum standard of
73compatibility, which applies regardless of the particular change. That is:</p>
74<ul>
75 <li>a subordinate charm must be replaced by a subordinate charm, and a
76 principal charm must be replaced by a principal charm.</li>
77 <li>every runtime relation used by the service must exist in both charms.</li>
78 <li class=" sub">charm relations that are defined, but not in use at runtime,
79 may be removed freely.</li>
80 <li class=" sub">in particular, it's not possible to remove a peer relation by
81 upgrading, because peer relations are always in use.</li>
82</ul>
83<p>No other factor is used in determining compatibility: configuration settings
84in particular are converted completely naively, such that any settings from
85the original charm that share a name and type are preserved; any incompatible
86settings are removed; and any new settings take defaults as though freshly
87deployed.</p>
88
89<p>When a service has been upgraded but a particular unit has not, the unit will
90continue to see the configuration settings from before conversion; these settings
91will not be affected by subsequent changes to the service's settings.</p>
92</section>
93
94<section id="forced-upgrades">
95<h2>Forced charm upgrades</h2>
96
97<p>Juju defines the upgrade-charm <a href="./authors-hook-kinds.html">hook</a> for
98resolving differences between versions of the same charm. No notice is given of
99charm upgrades; a charm upgrade may run at any time the unit is started, and the
100only opportunity for resolution that exists occurs *after* the change has taken
101place.</p>
102
103<p>This is quite a tight restriction, but nonetheless valuable, so long as you can
104guarantee it'll run. However, it's important to understand that the upgrade-charm
105accepts a <code>--force</code> flag: a forced charm upgrade will upgrade even units
106that are currently in an <a href="./authors-hook-errors.html">error</a> state, at
107the cost of skipping the <code>upgrade-charm</code> hook for those units.</p>
108
109<p>This is useful for charm authors who want to push a new version of a failed hook
110(they can <code>upgrade-charm --force</code> and then <code>resolved --retry</code>
111to run it immediately without otherwise disturbing the system); but it's potentially
112dangerous if abused. We recommend that use of the feature be restricted to charm
113authors while developing their own charms, and that it's not sensible to devote
114serious effort to recovering from inappropriately forced upgrades.</p>
115</section>
116
117<section id="upgrade-errors">
118<h2>Charm upgrade errors</h2>
119
120<p>These will only occur as a result of conflicts between the contents of the
121charm directory written at runtime, and should never be seen by a user; users
122certainly cannot be expected to understand the structure of your charm well
123enough to solve the conflicts sanely.</p>
124
125<p>When you're writing a new version of a charm, you should always test upgrading
126it from (at least) the previous version, to ensure these errors don't slip out
127into the wild.</p>
128
129<p>You can completely avoid these errors by <em>never</em> writing to the charm
130directory; and you can also avoid them by rigorously delineating the parts of
131your charm directory that you write to at runtime, and ensuring you never add a
132file to the raw charm that could conflict with the runtime state.</p>
133
134<p>If you're writing your hooks in python, you should be doubly aware of this: if
135you don't configure python to suppress bytecode caching, it will write <code>.pyc</code>
136files next to your python files at runtime, and effectively prevent you from
137rearranging those directories in future. This is not an unreasonable burden to
138bear, but it's important to know you're taking it on.</p>
139
140<p>If you encounter a charm upgrade error, you can run <code>git status</code> in
141the charm directory to see what the problem is, and use the knowledge thus gleaned to
142fix the charm and try to upgrade again.</p>
143</section>
144
145
146 </article>
147 </div>
148 </div>
149 </section>
150 <div class="shadow"></div>
151 <footer class="global clearfix" role="contentinfo">
152 <div class="row">
153 <div class="inner-wrapper">
154 <nav role="navigation" class="clearfix">
155 <ul class="footer-a">
156 <li class="grid-3 first-col">
157 <h4><a href="/get-started">Get started</a></h4>
158 <ul>
159 <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li>
160 <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li>
161 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li>
162 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li>
163 <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li>
164 <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li>
165 </ul>
166 </li>
167 <li class="grid-3">
168 <h4><a href="/resources">Resources</a></h4>
169 <ul>
170 <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li>
171 <li><a href="/resources/videos/">Videos</a></li>
172 <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li>
173 </ul>
174 </li>
175 <li class="grid-3">
176 <h4><a href="/community">Community</a></h4>
177 <ul>
178 <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li>
179 <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li>
180 <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li>
181 <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li>
182 <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li>
183 <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li>
184 </ul>
185 </li>
186 <li class="grid-3 last-col">
187 <h4><a href="https://launchpad.net/juju">Code</a></h4>
188 <ul>
189 <li><a href="https://launchpad.net/juju-core">Juju Core</a></li>
190 <li><a href="https://launchpad.net/charms">Charms</a></li>
191 </ul>
192 </li>
193 </ul>
194 </nav>
195 </div>
196 </div>
197 <div class="row no-border">
198 <div class="legal inner-wrapper">
199 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p>
200 <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p>
201 </div>
202 </div>
203</footer>
204
205 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
206 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
207 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
208 <script type="text/javascript" src="js/main.js"></script>
209 <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
210 </body>
211</html>
212
0213
=== modified file 'htmldocs/authors-charm-writing.html'
--- htmldocs/authors-charm-writing.html 2013-10-03 07:29:32 +0000
+++ htmldocs/authors-charm-writing.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -166,7 +168,7 @@
166<span class="number" > 4 </span>168<span class="number" > 4 </span>
167 <div class="step" id="step04">169 <div class="step" id="step04">
168 <h2>Writing hooks</h2>170 <h2>Writing hooks</h2>
169 <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>171 <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>
170 <p>For our charm, the hooks we will need to create are:</p>172 <p>For our charm, the hooks we will need to create are:</p>
171 <ul>173 <ul>
172 <li>start - for when the service needs to be started.</li>174 <li>start - for when the service needs to be started.</li>
@@ -416,4 +418,6 @@
416<!--End-Scripts-->418<!--End-Scripts-->
417419
418420
421
422
419</body></html>423</body></html>
420424
=== removed file 'htmldocs/authors-charms-in-action.html'
--- htmldocs/authors-charms-in-action.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-charms-in-action.html 1970-01-01 00:00:00 +0000
@@ -1,296 +0,0 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25
26 <body class="resources">
27
28<!--Header-->
29
30 <header class="banner global" role="banner">
31 <nav role="navigation" class="nav-primary nav-right">
32 <div class="logo">
33 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
34 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
35 <span>Juju</span>
36 </a>
37 </div>
38 <ul>
39 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
40 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
41 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
42 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
43 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
44 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
45 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
46 </ul>
47 <div id="box-search">
48 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
49 <label class="off-left" for="s">Search:</label>
50 <input class="form-text" type="text" value="" name="s" id="s" />
51 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
52 </form>
53 </div>
54 </nav>
55 </header>
56<!--End-Header-->
57<!--Preamble-->
58<div class="wrapper">
59 <div id="main-content" class="inner-wrapper" role="main">
60 <div class="row no-border">
61 <div class="header-navigation-secondary"></div>
62 <h2 class="pagetitle">Juju documentation</h2>
63 </div>
64 <section id="content" class="container-12">
65 <div class="grid-12 doc-container">
66 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
67 <div class="grid-9 doc-content">
68<!--End-Preamble-->
69 <article>
70 <section id="charm-in-action">
71 <h1 id="charms-in-action">Charms in action</h1>
72 <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>
73
74 <h2 id="hooks">Hooks</h2>
75 <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>
76 <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>
77 <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>
78
79 <h2 id="errors-in-hooks">Errors in hooks</h2>
80 <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>
81 <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>
82 <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>
83 <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>
84 <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>
85
86 <h2 id="charm-deployment">Charm deployment</h2>
87 <ul>
88 <li>A charm is deployed into a directory that is entirely owned and controlled by juju.</li>
89 <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>
90 <li>At these times, and only at these times, should the charm directory be used by anything other than juju itself.</li>
91 </ul>
92
93 <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>
94 <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>
95 <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>
96
97 <h2 id="execution-environment">Execution environment</h2>
98 <p>Every hook is run in the deployed charm directory, in an environment with the following characteristics:</p>
99 <ul>
100 <li>$PATH is prefixed by a directory containing command line tools through which the hooks can interact with juju.</li>
101 <li>$CHARM_DIR holds the path to the charm directory.</li>
102 <li>$JUJU_UNIT_NAME holds the name of the local unit.</li>
103 <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>
104 <li>$JUJU_API_ADDRESSES holds a space separated list of juju API addresses.</li>
105 </ul>
106 <h2 id="hook-tools">Hook tools</h2>
107 <p>All hooks can directly use the following tools:</p>
108 <ul>
109 <li>juju-log (write arguments direct to juju's log (potentially redundant, hook output is all logged anyway, but --debug may remain useful))</li>
110 <li>unit-get (returns the local unit's private-address or public-address)</li>
111 <li>open-port (marks the supplied port/protocol as ready to open when the service is exposed)</li>
112 <li>close-port (reverses the effect of open-port)</li>
113 <li>config-get (get current service configuration values)</li>
114 <li>relation-get (get the settings of some related unit)</li>
115 <li>relation-set (write the local unit's relation settings)</li>
116 <li>relation-ids (list all relations using a given charm relation)</li>
117 <li>relation-list (list all units of a related service)</li>
118 </ul>
119 <p>Within the context of a single hook execution, the above tools present a sandboxed view of the system with the following properties:</p>
120 <ul>
121 <li>Any data retrieved corresponds to the real value of the underlying state at some point in time.</li>
122 <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>
123 <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>
124 <li>Not actually sandboxed: open-port and close-port operate directly on state. [TODO: lp:1089304 - might be a little tricky.]</li>
125 </ul>
126
127 <h2 id="hook-kinds">Hook kinds</h2>
128 <p>There are 5 <code>unit hooks</code> with predefined names that can be implemented by any charm:</p>
129 <ul>
130 <li>install</li>
131 <li>config-changed</li>
132 <li>start</li>
133 <li>upgrade-charm</li>
134 <li>stop</li>
135 </ul>
136 <p>For every relation defined by a charm, an additional 4 <code>relation hooks</code> can be implemented, named after the charm relation:</p>
137 <ul>
138 <li><name>-relation-joined</li>
139 <li><name>-relation-changed</li>
140 <li><name>-relation-departed</li>
141 <li><name>-relation-broken</li>
142 </ul>
143
144 <h2 id="unit-hooks">Unit hooks</h2>
145 <p>The <code>install</code> hook always runs once, and only once, before any other hook.</p>
146 <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>
147 <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>
148 <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>
149 <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>
150 <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>
151 <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>
152
153 <h2 id="relation-hooks">Relation hooks</h2>
154 <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>
155 <ul>
156 <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>
157 <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>
158 <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>
159 </ul>
160 <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>
161 <ul>
162 <li>JUJU_REMOTE_UNIT is set to the name of the current related unit.</li>
163 <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>
164 </ul>
165 <p>For every relation in which a unit partcipates, hooks for the appropriate charm relation are run according to the following rules.</p>
166 <p>The &quot;relation-joined&quot; hook always runs once when a related unit is first seen.</p>
167 <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>
168 <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>
169 <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>
170 <h2 id="relations-in-depth">Relations in depth</h2>
171 <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>
172 <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>
173 <ul>
174 <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>
175 <li>Signal its existence, and role in the relation, to the rest of the system.</li>
176 </ul>
177 <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>
178 <ul>
179 <li>Each provider unit observes every requirer unit</li>
180 <li>Each requirer unit observes every provider unit</li>
181 <li>Each peer unit observes every other peer unit</li>
182 </ul>
183 <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>
184 <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>
185 <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>
186 <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>
187 <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>
188 <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>
189 <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>
190 <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>
191 <h2 id="departing-relations">Departing relations</h2>
192 <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>
193 <ul>
194 <li>For every known related unit -- those which have joined and not yet departed -- run the relation-departed hook.</li>
195 <li>Run the relation-broken hook.</li>
196 <li><code>depart</code> from its scope in the relation.</li>
197 </ul>
198 <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>
199 <h2 id="debugging-charms">Debugging charms</h2>
200 <p>Facilities are currently not good.</p>
201 <ul>
202 <li>juju ssh</li>
203 <li>juju debug-hooks</li>
204 <li>juju debug-log</li>
205 </ul>
206 <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>
207</article>
208 </section>
209<!--Postamble-->
210 </div>
211 </div>
212 </section>
213 </div>
214</div>
215<!--End-Postamble-->
216<!--Footer-->
217 <footer class="global clearfix" role="contentinfo">
218 <nav role="navigation">
219 <div class="footer-a">
220 <div class="clearfix">
221 <ul>
222 <li>
223 <h2><a href="/">Juju</a></h2>
224 <ul>
225 <li><a href="/charms">Charms</a></li>
226 <li><a href="/features">Features</a></li>
227 <li><a href="/deployment">Deployment</a></li>
228 </ul>
229 </li>
230 <li>
231 <h2><a href="/resources">Resources</a></h2>
232 <ul>
233 <li><a href="/resources/juju-overview/">Overview</a></li>
234 <li><a href="/docs/">Documentation</a></li>
235 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
236 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
237 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
238 <li><a href="/resources/videos/">Videos</a></li>
239 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
240 </ul>
241 </li>
242 <li>
243 <h2><a href="/community">Community</a></h2>
244 <ul>
245 <li><a href="/community/blog/">Juju Blog</a></li>
246 <li><a href="/events/">Events</a></li>
247 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
248 <li><a href="/community/charmers/">Charmers</a></li>
249 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
250 <li><a href="/docs/contributing.html">Help with documentation</a></li>
251 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
252 </ul>
253 </li>
254 <li>
255 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
256 <ul>
257 <li><a href="https://jujucharms.com/">Charm store</a></li>
258 <li><a href="/download/">Download Juju</a></li>
259 </ul>
260 </li>
261 </ul>
262 </div>
263 </div>
264 </nav>
265 <div class="legal clearfix">
266 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
267 </div>
268 </footer>
269
270<!--End-Footer-->
271
272<!--Scripts-->
273 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
274 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
275 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
276 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
277 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
278 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
279 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
280 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
281 <!-- google analytics -->
282 <script>
283 var _gaq = _gaq || [];
284 _gaq.push(['_setAccount', 'UA-1018242-41']);
285 _gaq.push(['_trackPageview']);
286
287 (function() {
288 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
289 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
290 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
291 })();
292 </script>
293<!--End-Scripts-->
294
295
296</body></html>
297\ No newline at end of file0\ No newline at end of file
2981
=== added file 'htmldocs/authors-hook-debug.html'
--- htmldocs/authors-hook-debug.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-hook-debug.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,169 @@
1<!DOCTYPE html>
2<html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>Juju Documentation - Hook Debugging</title>
6 <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' />
7 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" />
8 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" />
9 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" />
10 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" />
11 <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' />
12 <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/>
13
14 <!--[if lt IE 9]>
15 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
16 <![endif]-->
17</head>
18 <body class="resources">
19 <header class="global clearfix" role="banner">
20 <div class="header-navigation">
21 <div>
22 <nav role="navigation">
23 <ul>
24 <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li>
25 <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li>
26 <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
27 <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li>
28 <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li>
29 <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li>
30 <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li>
31 <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li>
32 <li>
33 <form id="form-search" method="get" action="https://juju.ubuntu.com/">
34 <fieldset>
35 <input id="input-search" type="text" name="s" value="Search" />
36 </fieldset>
37 </form>
38 </li>
39 </ul>
40 </nav>
41 </div>
42 </div>
43 <div class="header-content">
44 <div class="clearfix">
45 <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">
46 <div class="header-navigation-secondary"></div>
47 <div class="header-image"></div>
48 <h1>Resources</h1>
49 <h2>A collection of some of the most important online references for Juju users and developers.</h2>
50 </div>
51 </div>
52</header>
53
54 <section id="content" class="container-12">
55 <div class="grid-12 doc-container">
56 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
57 <div class="grid-9 doc-content">
58 <article>
59
60
61<section id="debugging-hooks">
62<h1>Debugging hooks</h1>
63
64<p>The <code>juju debug-hooks</code> command accepts a unit and an optional list
65of hooks to debug, which must each be named individually -- or all omitted, causing all
66hooks to be debugged.</p>
67
68<p>When you start a debug-hooks session, juju creates a tmux session on the
69machine running the requested unit; while that session persists, all hook
70executions will be replaced with new windows in that session, which run an
71<a href="./authors-hook-environment.html">environment</a> matching that of the
72appropriate hook (with one addition: <code>$JUJU_HOOK_NAME</code>) and which are
73marked as succeeded or failed depending on the exit code of the window.</p>
74
75<p>You can stop debugging by closing all windows in the tmux session.</p>
76</section>
77
78<section id="intercept-install">
79<h2>Debugging early hooks</h2>
80
81<p>The <code>install</code>, <code>config-changed</code>, and <code>start</code>
82hooks often execute quite soon after the unit comes up, making it difficult to start
83a debug-hooks session in time to intercept them. If you're having difficulties, you
84can temporarily return an error code from your <code>install</code> hook, and start
85your session only when the unit reports an <a href="./authors-hook-errors.html">error
86status</a>; then run <code>juju resolved --retry</code> for the affected unit, and go
87back to the debug-hooks session to interact.</p>
88</section>
89
90<section id="notes">
91<h2>Special considerations</h2>
92
93<p>While you're debugging hooks for one unit on a machine, you're blocking
94execution of all hooks on that machine. This is generally helpful, because
95you don't want to have to contend with concurrent changes to the machine's
96software, but you should be aware that multiple debug-hooks sessions for
97units assigned to the same machine will block one another, and that you
98can't control relative execution order directly (other than by erroring out
99of hooks you don't want to run yet, and retrying them later).</p>
100</section>
101
102
103 </article>
104 </div>
105 </div>
106 </section>
107 <div class="shadow"></div>
108 <footer class="global clearfix" role="contentinfo">
109 <div class="row">
110 <div class="inner-wrapper">
111 <nav role="navigation" class="clearfix">
112 <ul class="footer-a">
113 <li class="grid-3 first-col">
114 <h4><a href="/get-started">Get started</a></h4>
115 <ul>
116 <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li>
117 <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li>
118 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li>
119 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li>
120 <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li>
121 <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li>
122 </ul>
123 </li>
124 <li class="grid-3">
125 <h4><a href="/resources">Resources</a></h4>
126 <ul>
127 <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li>
128 <li><a href="/resources/videos/">Videos</a></li>
129 <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li>
130 </ul>
131 </li>
132 <li class="grid-3">
133 <h4><a href="/community">Community</a></h4>
134 <ul>
135 <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li>
136 <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li>
137 <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li>
138 <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li>
139 <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li>
140 <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li>
141 </ul>
142 </li>
143 <li class="grid-3 last-col">
144 <h4><a href="https://launchpad.net/juju">Code</a></h4>
145 <ul>
146 <li><a href="https://launchpad.net/juju-core">Juju Core</a></li>
147 <li><a href="https://launchpad.net/charms">Charms</a></li>
148 </ul>
149 </li>
150 </ul>
151 </nav>
152 </div>
153 </div>
154 <div class="row no-border">
155 <div class="legal inner-wrapper">
156 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p>
157 <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p>
158 </div>
159 </div>
160</footer>
161
162 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
163 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
164 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
165 <script type="text/javascript" src="js/main.js"></script>
166 <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
167 </body>
168</html>
169
0170
=== added file 'htmldocs/authors-hook-environment.html'
--- htmldocs/authors-hook-environment.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-hook-environment.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,561 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24 <body class="resources">
25<!--Header-->
26
27 <header class="banner global" role="banner">
28 <nav role="navigation" class="nav-primary nav-right">
29 <div class="logo">
30 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
31 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
32 <span>Juju</span>
33 </a>
34 </div>
35 <ul>
36 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
37 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
38 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
39 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
40 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
41 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
42 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
43 </ul>
44 <div id="box-search">
45 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
46 <label class="off-left" for="s">Search:</label>
47 <input class="form-text" type="text" value="" name="s" id="s" />
48 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
49 </form>
50 </div>
51 </nav>
52 </header>
53<!--End-Header-->
54<!--Preamble-->
55<div class="wrapper">
56 <div id="main-content" class="inner-wrapper" role="main">
57 <div class="row no-border">
58 <div class="header-navigation-secondary"></div>
59 <h2 class="pagetitle">Juju documentation</h2>
60 </div>
61 <section id="content" class="container-12">
62 <div class="grid-12 doc-container">
63 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
64 <div class="grid-9 doc-content">
65<!--End-Preamble-->
66<article>
67<section id="hook-execution-environment">
68<h1>Hook execution environment</h1>
69
70<p>When a charm is deployed onto a unit, the raw charm is extracted into a
71directory; this directory is known as the charm directory. It's owned and
72operated by juju, and juju sometimes temporarily cedes control of it to
73user code, by running a hook inside it.</p>
74
75<p>When a hook's running, it should be considered to have sole access to the
76charm directory; at all other times, you should consider that juju may be
77making arbitrarily scary changes to the directory, and that it is not safe
78to read or write to anything in there at all.</p>
79
80<p>This is to say that the software you install must, once it's running, be
81entirely independent of the charm that created it. It's fine (and encouraged,
82with some caveats) to store <em>charm</em> state in the charm directory, but the
83state of your <em>software</em> must remain unperturbed by direct changes to the
84charm.</p>
85
86<p>So, every hook runs with easy access to the charm files. Every hook also runs
87as root, with a number of useful variables set, and has access to hook-specific
88tools that let you interrogate and affect the juju environment.</p>
89
90<p>No more than one hook will execute on a given system at a given time. A unit in
91a container is considered to be on a different system to any unit on the
92container's host machine.</p>
93</section>
94
95<section id="environment-variables">
96<h2>Environment variables</h2>
97
98<p>The following variables are always available.</p>
99<ul>
100 <li>The <code>$CHARM_DIR</code> variable is the path to the charm directory.</li>
101 <li>The <code>$PATH</code> variable is prefixed with the path to the hook tools
102 directory.</li>
103 <li>The <code>$JUJU_UNIT_NAME</code> variable holds the name of the unit.</li>
104 <li>The <code>$JUJU_API_ADDRESSES</code> variable holds a space-separated list of API
105 server addresses.</li>
106</ul>
107<p>In addition, every relation hook makes available relation-specific variables.</p>
108<ul>
109 <li>The <code>$JUJU_RELATION</code> variable holds the relation name. This
110 information is of limited value, because it's always the same as the part of
111 the hook name just before &quot;-relation-&quot;.</li>
112 <li>The <code>$JUJU_RELATION_ID</code> variable holds an opaque relation
113 identifier, used to distinguish between multiple relations with the same name.
114 It is vitally important, because it's the only reasonable way of telling the
115 difference between (say) a database service's many independent clients.</li>
116</ul>
117<p>...and, if that relation hook is not a -broken hook:</p>
118<ul>
119 <li>The <code>$JUJU_REMOTE_UNIT</code> variable holds the name of the unit which
120 is being reported to have -joined, -changed, or -departed.</li>
121</ul>
122<p>Juju does <em>not</em> pay any attention to the values of the above variables when
123running hook tools: they're a one-way communication channel from juju to
124the charm only. Finally, in all cases:</p>
125<ul>
126 <li>The <code>$JUJU_AGENT_SOCKET</code> and <code>$JUJU_CONTEXT_ID</code> variables
127 allow the hook tools to work: juju <em>does</em> pay attention to them, but you
128 should treat them as opaque and avoid messing with them.</li>
129</ul>
130<p>Finally, if you're <a href="./authors-hook-debug.html">debugging</a>, you'll also
131have access to:</p>
132<ul>
133 <li>The <code>$JUJU_HOOK_NAME</code> variable, which will be set to the current
134 hook name.</li>
135</ul>
136</section>
137
138<section id="hook-tools">
139<h2>Hook tools</h2>
140
141<p>All hook tools are available in all hooks. Many of the tools produce output,
142and those that do accept a <code>--format</code> flag whose value can be set to
143<code>json</code> or <code>yaml</code> as desired. If it's not specified, the format
144defaults to <code>smart</code>, which transforms the basic output as follows:</p>
145<ul>
146 <li>strings are left untouched</li>
147 <li>boolean values are converted to the strings <code>True</code> and
148 <code>False</code></li>
149 <li>ints and floats are converted directly to strings</li>
150 <li>lists of strings are converted to a single newline-separated string</li>
151 <li>all other types (in general, dictionaries) are formatted as YAML</li>
152</ul>
153<p>Tools which do not produce output also accept the <code>--format</code> flag,
154but ignore it, for compatibility reasons.</p>
155
156<p>The various &quot;relation-&quot; tools infer context from the hook where
157possible. If they're running in a relation hook, the current relation id is set
158as the default; and if they're running in a -joined, -changed, or -broken hook,
159the current remote unit is set as the default.</p>
160
161<p>Best use of relation hooks will be made by those who understand the
162<a href="./authors-relations-in-depth">relation model</a>.</p>
163</section>
164
165<section id="juju-log">
166<h3>juju-log</h3>
167
168<p><code>juju-log</code> writes its arguments directly to the unit's log file.
169All hook output is currently logged anyway, so it's theoretically redundant with
170<code>echo</code>, but this is an implementation detail and should not be depended
171upon. If it's important, please <code>juju-log</code> it.</p>
172
173<pre class="prettyprint lang-bash">
174juju-log "some important text"
175</pre>
176
177<p>It accepts a <code>--debug</code> flag which causes the message to be logged
178at <code>DEBUG</code> level; in all other cases it's logged at <code>INFO</code>
179level. The <code>-l</code>/<code>--level</code> argument is ignored, and is present
180only to prevent legacy charms from entirely failing to run; the inability to specify
181logging levels and targets in more detail is a known
182<a href="https://bugs.launchpad.net/juju-core/+bug/1223325">bug</a>.</p>
183</section>
184
185<section id="unit-get">
186<h3>unit-get</h3>
187
188<p><code>unit-get</code> returns information about the local unit. It accepts a
189single argument, which must be <code>private-address</code> or
190<code>public-address</code>. It is not affected by context.</p>
191
192<pre class="prettyprint">
193unit-get private-address
19410.0.1.101
195</pre>
196
197<pre class="prettyprint">
198unit-get public-address
199foo.example.com
200</pre>
201
202</section>
203
204<section id="config-get">
205<h3>config-get</h3>
206
207<p><code>config-get</code> returns information about the service configuration (as
208defined by the charm). If called without arguments, it returns a dictionary
209containing all config settings that are either explicitly set, or which
210have a non-nil default value. If the <code>--all</code> flag is passed, it returns
211a dictionary containing all definied config settings including nil values
212(for those without defaults). If called with a single argument, it returns
213the value of that config key. Missing config keys are reported as having a
214value of nil, and do not return an error.</p>
215
216<p>Get the interesting bits of the config:</p>
217<pre class="prettyprint">
218config-get
219
220key: some-value
221another-key: default-value
222</pre>
223<p>Get the whole config including nulls:</p>
224<pre class="prettyprint">
225config-get --all
226
227key: some-value
228another-key: default-value
229no-default: null
230</pre>
231<p>Retrieve a specific value:</p>
232<pre class="prettyprint">
233config-get _key_
234
235default-value
236</pre>
237<p>Get a config setting with no value:</p>
238<pre class="prettyprint lang-bash">
239config-get no-default
240</pre>
241<p>Get a config setting that doesn't exist:</p>
242<pre class="prettyprint lang-bash">
243config-get missing-key
244</pre>
245<p class = "note"><strong>Note: </strong> The above two examples are not misprints
246 - asking for a value which doesn't exist or has not been set returns nothing and
247raises no errors.</p>
248</section>
249
250<section id="open-port">
251<h3>open-port</h3>
252
253<p><code>open-port</code> marks a port on the local system as appropriate to
254open, if and when the service is exposed to the outside world. It accepts a single
255port with an optional protocol, which may be <code>udp</code> or <code>tcp</code>,
256where <code>tcp</code> is the default.</p>
257<p>Examples:</p>
258<p>Open 80/tcp if and when the service is exposed:</p>
259<pre class="prettyprint lang-bash">
260open-port 80
261</pre>
262<p>Open 1234/udp if and when the service is exposed:</p>
263<pre class="prettyprint lang-bash">
264open-port 1234/udp
265</code></pre>
266
267<p><code>open-port</code> will not have any effect if the service is not exposed,
268and may have a somewhat delayed effect even if it is. It accepts and ignores
269<code>--format</code>, because it doesn't produce any output.</p>
270
271</section>
272
273<section id="close-port">
274<h3>close-port</h3>
275<p><code>close-port</code> unmarks a local system port. If the service is not
276exposed, it has no effect; otherwise the port is marked for imminent closure. It
277accepts the same flags and arguments as <code>open-port</code>.</p>
278<p>Examples:</p>
279<p>Close 1234/udp if it was open:</p>
280<pre class="prettyprint lang-bash">
281close-port 1234/udp
282</pre>
283<p>Close port 80 if it was open:</p>
284<pre class="prettyprint lang-bash">
285close-port 80
286</pre>
287</section>
288
289<section id="relation-set">
290<h3>relation-set</h3>
291
292<p><code>relation-set</code> writes the local unit's settings for some relation. It
293accepts any number of <code>key=value</code> strings, and an optional <code>-r</code>
294argument, which defaults to the current relation id. If it's not running in a relation
295hook, <code>-r</code> needs to be specified. The <code>value</code> part of an argument
296is not inspected, and is stored directly as a string. Setting an empty string causes
297the setting to be removed.</p>
298<p>Examples:</p>
299<p>Set a pair of values for the local unit in the default relation:</p>
300<pre class="prettyprint lang-bash">
301echo $JUJU_RELATION_ID
302
303 server:3
304
305relation-set username=bob password=2db673e81ffa264c
306</pre>
307
308<p>Set a pair of values for the local unit in a specific relation:</p>
309<pre class="prettyprint lang-bash">
310relation-set -r server:3 username=jim password=12345
311</pre>
312<p>Clear a value for the local unit in the default relation:</p>
313<pre class="prettyprint lang-bash">
314echo $JUJU_RELATION_ID
315server:3
316relation-set deprecated-or-unused=
317</pre>
318
319<p><code>relation-set</code> is the single tool at your disposal for communicating
320your own configuration to units of related services. At least by convention, the
321charm that <code>provides</code> an interface is likely to set values, and a charm
322that <code>requires</code> that interface will read them; but there's nothing
323forcing this. Whatever information you need to propagate for the remote charm to
324work must be propagated via relation-set, with the single exception of the
325<code>private-address</code> key, which is always set before the unit joins.</p>
326
327<p>You may wish to overwrite the <code>private-address</code> setting, for example
328if you're writing a charm that serves as a proxy for some external service; but
329you should in general avoid <em>removing</em> that key, because most charms expect
330that value to exist unconditionally.</p>
331
332<p>All values set are stored locally until the hook completes; at that point,
333if the hook exit code is 0, all changed values will be communicated to the
334rest of the system, causing -changed hooks to run in all related units.</p>
335
336<p>There is no way to write settings for any unit other than the local unit; but
337any hook on the local unit can write settings for any relation the local unit is
338participating in.</p>
339
340</section>
341
342<section id="relation-get">
343<h3>relation-get</h3>
344
345<p><code>relation-get</code> reads the settings of the local unit, or of any
346remote unit, in a given relation (set with <code>-r</code>, defaulting to the
347current relation, as in <code>relation-set</code>). The first argument specifies
348the settings key, and the second the remote unit, which may be omitted if a
349default is available (that is, when running a relation hook other than -broken).</p>
350
351<p>If the first argument is omitted, a dictionary of all current keys and values
352will be printed; all values are always plain strings without any interpretation.
353If you need to specify a remote unit but want to see all settings, use <code>-</code>
354for the first argument.</p>
355
356<p>Get all settings from the default remote unit in the default relation:</p>
357<pre class="prettyprint lang-bash">
358$ echo $JUJU_RELATION_ID
359db:1
360$ echo $JUJU_REMOTE_UNIT
361mongodb/2
362$ relation-get
363username: jim
364password: "12345"
365</pre>
366<p>Get one setting from the default remote unit in the default relation:</p>
367<pre class="prettyprint lang-bash">
368echo $JUJU_RELATION_ID
369db:1
370
371echo $JUJU_REMOTE_UNIT
372mongodb/2
373
374relation-get username
375jim
376</pre>
377<p>Get all settings from a particular remote unit in a particular relation:</p>
378<pre class="prettyprint lang-bash">
379echo $JUJU_RELATION_ID
380
381relation-get -r database:7 - mongodb/5
382
383 username: bob
384 password: 2db673e81ffa264c
385</pre>
386
387<p>Note that <code>relation-get</code> produces results that are <em>consistent</em>
388but not necessarily <em>accurate</em>, in that you will always see settings that:</p>
389<ul>
390 <li>were accurate at some point in the reasonably recent past
391 <li>are always the same within a single hook run...
392 <li class=" sub"><em>except</em> when inspecting the unit's own relation settings,
393 in which case local changes from <code>relation-set</code> will be seen correctly.</li>
394</ul>
395<p>You should never depend upon the presence of any given key in <code>relation-get</code>
396output. Processing that depends on specific values (other than
397<code>private-addres</code>) should be restricted to -changed hooks for the relevant
398unit, and the absence of a remote unit's value should never be treated as an
399<a href="./authors-hook-errors.html">error</a> in the local unit.</p>
400
401<p>In practice, it is common and encouraged for -relation-changed hooks to exit
402early, without error, after inspecting <code>relation-get</code> output and
403determining it to be inadequate; and for <a href="./authors-hook-kinds.html">all
404other hooks</a> to be resilient in the face of missing keys, such that
405-relation-changed hooks will be sufficient to complete all configuration that
406depends on remote unit settings.</p>
407
408<p>Settings for remote units already known to have departed remain accessible
409for the lifetime of the relation.</p>
410
411<p><code>relation-get</code> currently has a
412<a href="https://bugs.launchpad.net/juju-core/+bug/1223339">bug</a> that allows units
413of the same service to see each other's settings outside of a peer relation. Depending
414on this behaviour is foolish in the extreme: if you need to share settings between
415units of the same service, always use a peer relation to do so, or you may be
416seriously inconvenienced when the hole is closed without notice.</p>
417
418</section>
419
420<section id="relation-list">
421<h3>relation-list</h3>
422
423<p><code>relation-list</code> accepts the <code>-r</code> flag as above, and
424outputs the names of every remote unit currently known to be in the relation.</p>
425<p>Examples:</p>
426<p>Show all remote units in the current relation</p>
427<pre class="prettyprint lang-bash">
428$ echo $JUJU_RELATION_ID
429db:1
430
431$ relation-list
432mongodb/0
433mongodb/2
434mongodb/3
435</pre>
436
437<p>Show all remote units in a specific relation:</p>
438<pre class="prettyprint lang-bash">
439echo $JUJU_RELATION_ID
440relation-list -r website:2
441
442haproxy/0
443</pre>
444
445</section>
446
447<section id="relation-ids">
448<h3>relation-ids</h3>
449
450<p><code>relation-ids</code> accepts a single argument which, in a relation
451hook, defaults to the name of the current relation.</p>
452<p>Examples:</p>
453<p>Show all relations like the current one:</p>
454<pre class="prettyprint lang-bash">
455$ echo $JUJU_RELATION
456server
457$ relation-ids
458server:1
459server:7
460server:9
461</pre>
462<p>Show all relations with the given name:</p>
463<pre class="prettyprint lang-bash">
464$ echo $JUJU_RELATION_ID
465
466$ relation-ids reverseproxy
467reverseproxy:3
468</pre>
469
470<p>Note again that all commands that produce output accept <code>--format json</code>
471and <code>--format yaml</code>, and you may consider it smarter to use those for
472clarity's sake than to depend on the default <code>smart</code> format.
473</section>
474</article>
475<!--Postamble-->
476 </div>
477 </div>
478 </section>
479 </div>
480</div>
481<!--End-Postamble-->
482<!--Footer-->
483 <footer class="global clearfix" role="contentinfo">
484 <nav role="navigation">
485 <div class="footer-a">
486 <div class="clearfix">
487 <ul>
488 <li>
489 <h2><a href="/">Juju</a></h2>
490 <ul>
491 <li><a href="/charms">Charms</a></li>
492 <li><a href="/features">Features</a></li>
493 <li><a href="/deployment">Deployment</a></li>
494 </ul>
495 </li>
496 <li>
497 <h2><a href="/resources">Resources</a></h2>
498 <ul>
499 <li><a href="/resources/juju-overview/">Overview</a></li>
500 <li><a href="/docs/">Documentation</a></li>
501 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
502 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
503 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
504 <li><a href="/resources/videos/">Videos</a></li>
505 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
506 </ul>
507 </li>
508 <li>
509 <h2><a href="/community">Community</a></h2>
510 <ul>
511 <li><a href="/community/blog/">Juju Blog</a></li>
512 <li><a href="/events/">Events</a></li>
513 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
514 <li><a href="/community/charmers/">Charmers</a></li>
515 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
516 <li><a href="/docs/contributing.html">Help with documentation</a></li>
517 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
518 </ul>
519 </li>
520 <li>
521 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
522 <ul>
523 <li><a href="https://jujucharms.com/">Charm store</a></li>
524 <li><a href="/download/">Download Juju</a></li>
525 </ul>
526 </li>
527 </ul>
528 </div>
529 </div>
530 </nav>
531 <div class="legal clearfix">
532 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
533 </div>
534 </footer>
535
536<!--End-Footer-->
537<!--Scripts-->
538 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
539 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
540 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
541 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
542 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
543 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
544 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
545 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
546 <!-- google analytics -->
547 <script>
548 var _gaq = _gaq || [];
549 _gaq.push(['_setAccount', 'UA-1018242-41']);
550 _gaq.push(['_trackPageview']);
551
552 (function() {
553 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
554 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
555 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
556 })();
557 </script>
558<!--End-Scripts-->
559
560</body></html>
561
0562
=== added file 'htmldocs/authors-hook-errors.html'
--- htmldocs/authors-hook-errors.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-hook-errors.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,194 @@
1<!DOCTYPE html>
2<html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>Juju Documentation - Hook Errors</title>
6 <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' />
7 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" />
8 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" />
9 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" />
10 <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" />
11 <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' />
12 <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/>
13
14 <!--[if lt IE 9]>
15 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
16 <![endif]-->
17</head>
18 <body class="resources">
19 <header class="global clearfix" role="banner">
20 <div class="header-navigation">
21 <div>
22 <nav role="navigation">
23 <ul>
24 <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li>
25 <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li>
26 <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
27 <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li>
28 <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li>
29 <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li>
30 <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li>
31 <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li>
32 <li>
33 <form id="form-search" method="get" action="https://juju.ubuntu.com/">
34 <fieldset>
35 <input id="input-search" type="text" name="s" value="Search" />
36 </fieldset>
37 </form>
38 </li>
39 </ul>
40 </nav>
41 </div>
42 </div>
43 <div class="header-content">
44 <div class="clearfix">
45 <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">
46 <div class="header-navigation-secondary"></div>
47 <div class="header-image"></div>
48 <h1>Resources</h1>
49 <h2>A collection of some of the most important online references for Juju users and developers.</h2>
50 </div>
51 </div>
52</header>
53
54 <section id="content" class="container-12">
55 <div class="grid-12 doc-container">
56 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
57 <div class="grid-9 doc-content">
58 <article>
59
60
61<section id="hook-errors">
62<h1>Hook errors</h1>
63
64<p>If any of your hooks returns a non-zero exit code, juju will stop managing the
65unit directly and will wait for user intervention. This is a Bad Thing, and you
66should make every effort to avoid it, because the average user may not be in a
67position to diagnose the fault with any great degree of sophistication.</p>
68
69<p>So, in general, you should write your hooks as robustly as possible: if an
70operation suffers a possibly-transient failure, it's wise to wait a moment and
71retry a couple of times, to avoid needlessly bothering the user with a decision
72or call to action that they're not necessarily equipped to make.</p>
73
74<p>However, you will no doubt encounter errors on occasion -- in particular, if
75the unit agent is aborted while it's running a hook, it'll set an error status
76for that hook when it comes back up. You will in that case have to deal with
77users' potentially underinformed responses to those errors.</p>
78</section>
79
80<section id="error-status">
81<h2>Error status</h2>
82
83<p>When a unit agent sets an error status, it stops running hooks and relinquishes
84control over the charm directory. This means that it's generally safe to
85<code>juju ssh</code> into the unit and use it as though you were the sole
86administrator; juju will only take back control of the directory when explicitly
87requested, in response to either <code>juju resolved</code> or
88<code>juju upgrade-charm --force</code>.
89<ul>
90 <li><code>juju resolved</code> causes the unit to unblock itself and continue
91 as though the hook had completed successfuly. The ideal charm will be aware of
92 this possibility and will therefore trust information from its
93 <a href="./authors-hook-environment.html">environment</a> to be more recent and
94 correct than anything it may have previously have recorded in the local
95 <a href="./authors-charm-contents.html">charm directory</a>.</li>
96
97 <li><code>juju resolved --retry</code> reverts the charm directory's contents
98 to whatever they were at the start of the failed hook, and runs the hook again
99 exactly as before. This, in combination with the
100 <a href="./authors-hook-debug.html">debug-hooks</a> command, is your main entry
101 point for investigating an error in detail. If the hook fails again when retried,
102 it will set an error as before and wait again for user resolution.</li>
103
104 <li><code>juju upgrade-charm --force</code> merges into the charm directory the
105 contents of the newer charm version, and continues blocking in the original hook
106 error state. Each time a new upgrade is forced, the charm directory is rolled
107 back to the state from which it was originally upgraded before proceeding; this
108 means that a forced upgrade back to the original charm will always be a no-op,
109 regardless of what other upgrade attempts have been made in the interim.</li>
110</ul>
111<p>Once you have issued one of the above commands, the charm directory should
112once again be treated as inaccessible.</p>
113</section>
114
115<section id="upgrade-errors">
116<h2>Charm upgrade errors</h2>
117
118<p>Finally, there's another reason a unit might set an error status: a
119<a href="./authors-charm-upgrades.html">charm upgrade</a> conflict, which
120should never happen except during development.</p>
121
122<p>They can be resolved either by forcing an upgrade to a different charm version,
123or by manually resolving the git conflicts in the charm directory and running
124<code>juju resolved</code> to cause the unit agent to continue.</p>
125</section>
126
127
128 </article>
129 </div>
130 </div>
131 </section>
132 <div class="shadow"></div>
133 <footer class="global clearfix" role="contentinfo">
134 <div class="row">
135 <div class="inner-wrapper">
136 <nav role="navigation" class="clearfix">
137 <ul class="footer-a">
138 <li class="grid-3 first-col">
139 <h4><a href="/get-started">Get started</a></h4>
140 <ul>
141 <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li>
142 <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li>
143 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li>
144 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li>
145 <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li>
146 <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li>
147 </ul>
148 </li>
149 <li class="grid-3">
150 <h4><a href="/resources">Resources</a></h4>
151 <ul>
152 <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li>
153 <li><a href="/resources/videos/">Videos</a></li>
154 <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li>
155 </ul>
156 </li>
157 <li class="grid-3">
158 <h4><a href="/community">Community</a></h4>
159 <ul>
160 <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li>
161 <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li>
162 <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li>
163 <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li>
164 <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li>
165 <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li>
166 </ul>
167 </li>
168 <li class="grid-3 last-col">
169 <h4><a href="https://launchpad.net/juju">Code</a></h4>
170 <ul>
171 <li><a href="https://launchpad.net/juju-core">Juju Core</a></li>
172 <li><a href="https://launchpad.net/charms">Charms</a></li>
173 </ul>
174 </li>
175 </ul>
176 </nav>
177 </div>
178 </div>
179 <div class="row no-border">
180 <div class="legal inner-wrapper">
181 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p>
182 <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p>
183 </div>
184 </div>
185</footer>
186
187 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
188 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
189 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
190 <script type="text/javascript" src="js/main.js"></script>
191 <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
192 </body>
193</html>
194
0195
=== added file 'htmldocs/authors-hook-kinds.html'
--- htmldocs/authors-hook-kinds.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-hook-kinds.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,402 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25 <body class="resources">
26<!--Header-->
27
28 <header class="banner global" role="banner">
29 <nav role="navigation" class="nav-primary nav-right">
30 <div class="logo">
31 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
32 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
33 <span>Juju</span>
34 </a>
35 </div>
36 <ul>
37 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
38 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
39 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
40 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
41 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
42 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
43 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
44 </ul>
45 <div id="box-search">
46 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
47 <label class="off-left" for="s">Search:</label>
48 <input class="form-text" type="text" value="" name="s" id="s" />
49 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
50 </form>
51 </div>
52 </nav>
53 </header>
54<!--End-Header-->
55<!--Preamble-->
56<div class="wrapper">
57 <div id="main-content" class="inner-wrapper" role="main">
58 <div class="row no-border">
59 <div class="header-navigation-secondary"></div>
60 <h2 class="pagetitle">Juju documentation</h2>
61 </div>
62 <section id="content" class="container-12">
63 <div class="grid-12 doc-container">
64 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
65 <div class="grid-9 doc-content">
66<!--End-Preamble-->
67<article>
68<section id="charm-hooks">
69<h1>Charm hooks</h1>
70
71<p>A service unit's direct action is entirely defined by its charm's hooks. Hooks
72are executable files in a charm's <code>hooks</code> directory; hooks with particular
73names (see below) will be invoked by the juju unit agent at particular times, and thereby cause
74changes to the world.</p>
75
76<p>Whenever a hook-worthy event takes place, the unit agent first checks whether
77that hook is being <a href="./authors-hook-debug.html">debugged</a>, and if so
78hands over control to the user. Otherwise, it tries to find a hook with precisely
79the right name. If the hook doesn't exist, the agent continues without complaint;
80if it does, it is invoked without arguments in a specific
81<a href="./authors-hook-environment.html">environment</a>, and its output is written
82to the unit agent's log. If it returns a non-zero exit code, the agent enters an
83<a href="./authors-hook-errors.html">error state</a> and awaits user intervention.</p>
84
85<p>The agent will also enter an error state if the unit agent process is aborted
86during hook execution.</p>
87
88<p>There are two types of hooks, described in more detail in the following sections.</p>
89
90<p class = "note"><strong>Note: </strong>None of the unit or relation hooks are required; if you don't implement a hook,
91it 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>
92</section>
93
94<section id="unit-hooks">
95<h2>Unit hooks</h2>
96
97<p>There are 5 &quot;unit hooks&quot; with predefined names that can be implemented
98by any charm:</p>
99<ul>
100 <li>install</li>
101 <li>config-changed</li>
102 <li>start</li>
103 <li>upgrade-charm</li>
104 <li>stop</li>
105</ul>
106
107<p>For every relation defined by a charm, an additional 4 &quot;relation hooks&quot;
108can be implemented, named after the charm relation:</p>
109<ul>
110 <li>&lt;name&gt;-relation-joined</li>
111 <li>&lt;name&gt;-relation-changed</li>
112 <li>&lt;name&gt;-relation-departed</li>
113 <li>&lt;name&gt;-relation-broken</li>
114</ul>
115<p>None of the unit or relation hooks are required; if you don't implement a hook,
116it 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>
117</section>
118
119<p>The unit hooks are run under the following circumstances.</p>
120</section>
121
122<section id="hook-install">
123<h3>install</h3>
124
125<p><code>install</code> runs just once, before any other hook. It should be used to
126perform one-time setup operations only.</p>
127</section>
128
129<section id="hook-config-changed">
130<h3>config-changed</h3>
131
132<p><code>config-changed</code> runs in several different situations.</p>
133<ul>
134 <li>immediately after "install"</li>
135 <li>immediately after "upgrade-charm"</li>
136 <li>at least once when the unit agent is restarted (but, if the unit is in
137 an <a href="./authors-hook-errors.html">error state</a>, it won't be run
138 until after the error state is cleared).</li>
139</ul>
140<p>It cannot assume that the software has already been started; it should not
141start stopped software, but should (if appropriate) restart running software
142to take configuration changes into account.</p>
143</section>
144
145<section id="hook-start">
146<h3>start</h3>
147<p><code>start</code> runs immediately after the first <code>config-changed</code>
148hook. It should be used to ensure the charm's software is running. Note that the
149charm's software should be configured so as to persist through reboots without further
150intervention on juju's part.
151</section>
152
153<section id="hook-upgrade-charm">
154<h3>upgrade-charm</h3>
155
156<p><code>upgrade-charm</code> runs immediately after any
157<a href="./authors-charm-upgrades.html">upgrade</a> operation that does <em>not</em>
158itself interrupt an existing <a href="./authors-hook-errors.html">error state.</a>. It
159should be used to reconcile local state written by some other version of the charm into
160whatever form it needs to take to be manipulated by the current version.</p>
161
162<p>While the forced upgrade functionality is intended as a developer tool, and is
163not generally suitable for end users, it's somewhat optimistic to depend on the
164functionality never being abused. In light of this, if you need to run an
165<code>upgrade-charm</code> hook before your other hooks will work correctly,
166it may be wise to preface all your other hooks with a quick call to your
167(idempotent)<code>upgrade-charm</code>.</p>
168</section>
169
170<section id="hook-stop">
171<h3>stop</h3>
172
173<p><code>stop</code> runs immediately before the end of the unit's destruction
174sequence. It should be used to ensure that the charm's software is not running, and
175will not start again on reboot.</p>
176</section>
177
178<section id="relation-hooks">
179<h2>Relation hooks</h2>
180
181<p>Units will only participate in relations after they're been started, and before
182they've been stopped. Within that time window, the unit may participate in several
183different relations at a time, <em>including</em> multiple relations with the
184same name.</p>
185
186<p>To illustrate, consider a database service that will be used by multiple client
187services. Units of a single client service will surely want to connect to, and
188use, the same database; but if units of another client service were to use that
189same database, the consequences could be catastrophic for all concerned.</p>
190
191<p>If juju respected the <code>limit</code> field in relation
192<a href="./authors-charm-metadata.html">metadata</a>, it would be possible
193to work around this, but it's not a high-priority
194<a href="https://bugs.launchpad.net/bugs/1089297">bug</a>: most provider services
195<em>should</em> be able to handle multiple requirers anyway; and most requirers will
196only be connected to one provider anyway.</p>
197
198<p>When a unit running a given charm participates in a given relation, it runs at
199least three hooks for every remote unit it becomes aware of in that relation.</p>
200</section>
201
202<section id="hook-relation-joined">
203<h3>&lt;name&gt;-relation-joined</h3>
204
205<p><code>&lt;name&gt;-relation-joined</code> is run once only, when that remote
206unit is first observed by the unit. It should be used to <code>relation-set</code> any
207local unit settings that can be determined using no more than the name of the joining
208unit and the remote <code>private-address</code> setting, which is always available
209when the relation is created and is by convention not deleted.</p>
210
211<p>You should not depend upon any other relation settings in the -joined hook
212because they're not guaranteed to be present; if you need more information
213you should wait for a -changed hook that presents the right information.</p>
214</section>
215
216<section id="hook-relation-changed">
217<h3>&lt;name&gt;-relation-changed</h3>
218
219<p><code>&lt;name&gt;-relation-changed</code> is always run once, after -joined, and
220will subsequently be run whenever that remote unit changes its settings for the
221relation. It should be the <em>only</em> hook that <em>relies</em> upon remote relation
222settings from <code>relation-get</code>, and it should <em>not</em> error if the
223settings are incomplete: you can guarantee that when the remote unit changes its
224settings, the hook will be run again.</p>
225
226<p>The settings that you can get, and that you should set, are determined by
227the relation's <a href="./authors-charm-interfaces.html">interface</a>.</p>
228</section>
229
230<section id="hook-relation-departed">
231<h3>&lt;name&gt;-relation-departed</h3>
232
233<p><code>&lt;name&gt;-relation-departed</code> is run once only, when the remote unit
234is known to be leaving the relation; it will only run once at least one -changed has
235been run, and after -departed has run, no further -changeds will be run. This should
236be used to remove all references to the remote unit, because there's no guarantee that
237it's still part of the system; it's perfectly probable (although not guaranteed) that
238the system running that unit has already shut down.</p>
239
240<p>When a unit's own participation in a relation is known to be ending, the unit
241agent continues to uphold the ordering guarantees above; but within those
242constraints, it will run the fewest possible hooks to notify the charm of the
243departure of each individual remote unit.</p>
244
245<p>Once all necessary -departed hooks have been run for such a relation, the unit
246agent will run the final relation hook:</p>
247</section>
248
249<section id="hook-relation-broken">
250<h3>&lt;name&gt;-relation-broken</h3>
251
252<p><code>&lt;name&gt;-relation-broken</code> indicates that the current relation is
253no longer valid, and that the charm's software must be configured as though the
254relation had never existed. It will only be called after every necessary -departed
255hook has been run; if it's being executed, you can be sure that no remote units are
256currently known locally.</p>
257
258<p>It is important to note that the -broken hook might run even if no other units
259have ever joined the relation. This is not a bug: even if no remote units have ever
260joined, the fact of the unit's participation can be detected in other hooks via the
261<code>relation-ids</code> tool, and the -broken hook needs to execute to give the
262charm an opportunity to clean up any optimistically-generated configuration.</p>
263
264<p>And, again, it's important to internalise the fact that there may be multiple
265runtime relations in play with the same name, and that they're independent:
266one -broken hook does not mean that <em>every</em> such relation is broken.</p>
267</section>
268
269<section id="writing-hooks">
270<h2>Writing hooks</h2>
271
272<p>If you follow the <a href="./authors-charm-writing.html">tutorial</a>, you'll
273get a good sense of the basics. To fill out your knowledge, you'll want to study
274the hook <a href="./authors-hook-environment.html">environment and tools</a>, and
275to experiment with <a href="./authors-hook-debug.html">debug-hooks</a>.</p>
276
277<p>Independent of the nuts and bolts, though, good hooks display a number of
278useful high-level properties:</p>
279<ul>
280 <li>They are <em>idempotent</em>: that is to say that there should be no
281 observable difference between running a hook once, and running it N times
282 in a row. If this property does not hold, you are likely to be making your
283 own life unnecesarily difficult: apart from anything else, the average user's
284 most likely first response to a failed hook will be to try to run it again
285 (if they don't just skip it).</li>
286
287 <li>They are <em>easy to read</em> and understand. It's tempting to write a
288 single file that does everything, and which just calls different functions
289 internally depending on the value of <code>argv[0]</code>, and to symlink that
290 one file for every hook; but such structures quickly become unwieldy.<br />
291 The time taken to write a library, separate from the hooks, is very likely
292 to be well spent: it lets you write single hooks that are clear and focused,
293 and insulates the maintainer from irrelevant details.</li>
294
295 <li>Where possible, they reuse
296 <a href="https://launchpad.net/charm-tools">common code</a> already written to
297 ease or solve common use cases.</li>
298
299 <li>They do not return <a href="./authors-hook-errors.html">errors</a> unless
300 there is a good reason to believe that they cannot be resolved without user
301 intervention. Doing so is an admission of defeat: a user who sees your charm
302 returning an error state is unlikely to have the specific expertise necessary
303 to resolve it. If you have to return an error, please be sure to at least write
304 any context you can to the log before you do so.</li>
305
306 <li>They write only <em>very</em> sparingly to the
307 <a href="./authors-charm-contents.html">charm directory</a>.</li>
308</ul>
309
310<p>We recommend you also familiarize yourself with the
311<a href="./authors-charm-best-practice.html">best practices</a> and, if you
312plan to distribute your charm, the
313<a href="./authors-charm-policy.html">charm store policy</a>.</p>
314</section>
315 </article>
316<!--Postamble-->
317 </div>
318 </div>
319 </section>
320 </div>
321</div>
322<!--End-Postamble-->
323<!--Footer-->
324 <footer class="global clearfix" role="contentinfo">
325 <nav role="navigation">
326 <div class="footer-a">
327 <div class="clearfix">
328 <ul>
329 <li>
330 <h2><a href="/">Juju</a></h2>
331 <ul>
332 <li><a href="/charms">Charms</a></li>
333 <li><a href="/features">Features</a></li>
334 <li><a href="/deployment">Deployment</a></li>
335 </ul>
336 </li>
337 <li>
338 <h2><a href="/resources">Resources</a></h2>
339 <ul>
340 <li><a href="/resources/juju-overview/">Overview</a></li>
341 <li><a href="/docs/">Documentation</a></li>
342 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
343 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
344 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
345 <li><a href="/resources/videos/">Videos</a></li>
346 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
347 </ul>
348 </li>
349 <li>
350 <h2><a href="/community">Community</a></h2>
351 <ul>
352 <li><a href="/community/blog/">Juju Blog</a></li>
353 <li><a href="/events/">Events</a></li>
354 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
355 <li><a href="/community/charmers/">Charmers</a></li>
356 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
357 <li><a href="/docs/contributing.html">Help with documentation</a></li>
358 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
359 </ul>
360 </li>
361 <li>
362 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
363 <ul>
364 <li><a href="https://jujucharms.com/">Charm store</a></li>
365 <li><a href="/download/">Download Juju</a></li>
366 </ul>
367 </li>
368 </ul>
369 </div>
370 </div>
371 </nav>
372 <div class="legal clearfix">
373 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
374 </div>
375 </footer>
376
377<!--End-Footer-->
378<!--Scripts-->
379 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
380 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
381 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
382 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
383 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
384 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
385 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
386 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
387 <!-- google analytics -->
388 <script>
389 var _gaq = _gaq || [];
390 _gaq.push(['_setAccount', 'UA-1018242-41']);
391 _gaq.push(['_trackPageview']);
392
393 (function() {
394 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
395 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
396 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
397 })();
398 </script>
399<!--End-Scripts-->
400
401
402</body></html>
0403
=== removed file 'htmldocs/authors-hooks.html'
--- htmldocs/authors-hooks.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-hooks.html 1970-01-01 00:00:00 +0000
@@ -1,185 +0,0 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25
26 <body class="resources">
27
28<!--Header-->
29
30 <header class="banner global" role="banner">
31 <nav role="navigation" class="nav-primary nav-right">
32 <div class="logo">
33 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
34 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
35 <span>Juju</span>
36 </a>
37 </div>
38 <ul>
39 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
40 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
41 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
42 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
43 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
44 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
45 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
46 </ul>
47 <div id="box-search">
48 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
49 <label class="off-left" for="s">Search:</label>
50 <input class="form-text" type="text" value="" name="s" id="s" />
51 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
52 </form>
53 </div>
54 </nav>
55 </header>
56<!--End-Header-->
57<!--Preamble-->
58<div class="wrapper">
59 <div id="main-content" class="inner-wrapper" role="main">
60 <div class="row no-border">
61 <div class="header-navigation-secondary"></div>
62 <h2 class="pagetitle">Juju documentation</h2>
63 </div>
64 <section id="content" class="container-12">
65 <div class="grid-12 doc-container">
66 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
67 <div class="grid-9 doc-content">
68<!--End-Preamble-->
69 <article>
70 <section id ="hook-debugging">
71 <h1>Hook debugging</h1>
72
73 <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>
74 <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>
75
76 <h2>How it works</h2>
77 <p>When the juju user utilizes the hook debug command like so:</p>
78 <pre>juju debug-hooks unit_name [hook_name]</pre>
79
80 <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>
81 <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>
82 <p>The native capabilities of tmux can be exploited to construct a full debug/development environment on the remote machine.</p>
83 <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>
84 <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>
85 <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>
86 <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>
87 <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>
88
89 <h2>Internals</h2>
90 <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>
91 <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>
92 <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>
93 </section>
94 </article>
95 </div>
96 </div>
97 </section>
98<!--Postamble-->
99 </div>
100 </div>
101 </section>
102 </div>
103</div>
104<!--End-Postamble-->
105<!--Footer-->
106 <footer class="global clearfix" role="contentinfo">
107 <nav role="navigation">
108 <div class="footer-a">
109 <div class="clearfix">
110 <ul>
111 <li>
112 <h2><a href="/">Juju</a></h2>
113 <ul>
114 <li><a href="/charms">Charms</a></li>
115 <li><a href="/features">Features</a></li>
116 <li><a href="/deployment">Deployment</a></li>
117 </ul>
118 </li>
119 <li>
120 <h2><a href="/resources">Resources</a></h2>
121 <ul>
122 <li><a href="/resources/juju-overview/">Overview</a></li>
123 <li><a href="/docs/">Documentation</a></li>
124 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
125 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
126 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
127 <li><a href="/resources/videos/">Videos</a></li>
128 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
129 </ul>
130 </li>
131 <li>
132 <h2><a href="/community">Community</a></h2>
133 <ul>
134 <li><a href="/community/blog/">Juju Blog</a></li>
135 <li><a href="/events/">Events</a></li>
136 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
137 <li><a href="/community/charmers/">Charmers</a></li>
138 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
139 <li><a href="/docs/contributing.html">Help with documentation</a></li>
140 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
141 </ul>
142 </li>
143 <li>
144 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
145 <ul>
146 <li><a href="https://jujucharms.com/">Charm store</a></li>
147 <li><a href="/download/">Download Juju</a></li>
148 </ul>
149 </li>
150 </ul>
151 </div>
152 </div>
153 </nav>
154 <div class="legal clearfix">
155 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
156 </div>
157 </footer>
158
159<!--End-Footer-->
160
161<!--Scripts-->
162 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
163 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
164 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
165 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
166 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
167 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
168 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
169 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
170 <!-- google analytics -->
171 <script>
172 var _gaq = _gaq || [];
173 _gaq.push(['_setAccount', 'UA-1018242-41']);
174 _gaq.push(['_trackPageview']);
175
176 (function() {
177 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
178 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
179 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
180 })();
181 </script>
182<!--End-Scripts-->
183
184
185</body></html>
1860
=== modified file 'htmldocs/authors-implicit-relations.html'
--- htmldocs/authors-implicit-relations.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-implicit-relations.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -186,4 +188,6 @@
186<!--End-Scripts-->188<!--End-Scripts-->
187189
188190
191
192
189</body></html>193</body></html>
190194
=== modified file 'htmldocs/authors-interfaces.html'
--- htmldocs/authors-interfaces.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-interfaces.html 2013-10-09 20:07:46 +0000
@@ -23,6 +23,8 @@
2323
2424
2525
26
27
26 <body class="resources">28 <body class="resources">
27 29
28<!--Header-->30<!--Header-->
@@ -362,4 +364,6 @@
362<!--End-Scripts-->364<!--End-Scripts-->
363365
364366
367
368
365</body></html>369</body></html>
366370
=== modified file 'htmldocs/authors-intro.html'
--- htmldocs/authors-intro.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-intro.html 2013-10-09 20:07:46 +0000
@@ -21,6 +21,8 @@
21 </head>21 </head>
22<!--End-Head-->22<!--End-Head-->
2323
24
25
24 <body class="resources"> 26 <body class="resources">
25<!--Header-->27<!--Header-->
2628
@@ -67,7 +69,7 @@
67 <section id='author-intro'>69 <section id='author-intro'>
68 <h1>Becoming a charm author</h1>70 <h1>Becoming a charm author</h1>
69 <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>71 <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>
70 <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> 72 <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>
71</article>73</article>
72<!--Postamble-->74<!--Postamble-->
73 </div>75 </div>
@@ -154,4 +156,6 @@
154 </script>156 </script>
155<!--End-Scripts-->157<!--End-Scripts-->
156158
159
160
157</body></html>161</body></html>
158162
=== added file 'htmldocs/authors-relations-in-depth.html'
--- htmldocs/authors-relations-in-depth.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-relations-in-depth.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,187 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24 <body class="resources">
25<!--Header-->
26
27 <header class="banner global" role="banner">
28 <nav role="navigation" class="nav-primary nav-right">
29 <div class="logo">
30 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
31 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
32 <span>Juju</span>
33 </a>
34 </div>
35 <ul>
36 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
37 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
38 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
39 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
40 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
41 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
42 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
43 </ul>
44 <div id="box-search">
45 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
46 <label class="off-left" for="s">Search:</label>
47 <input class="form-text" type="text" value="" name="s" id="s" />
48 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
49 </form>
50 </div>
51 </nav>
52 </header>
53<!--End-Header-->
54<!--Preamble-->
55<div class="wrapper">
56 <div id="main-content" class="inner-wrapper" role="main">
57 <div class="row no-border">
58 <div class="header-navigation-secondary"></div>
59 <h2 class="pagetitle">Juju documentation</h2>
60 </div>
61 <section id="content" class="container-12">
62 <div class="grid-12 doc-container">
63 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
64 <div class="grid-9 doc-content">
65<!--End-Preamble-->
66<article>
67 <section id="relations-in-depth">
68 <h1>Relations in depth</h1>
69
70 <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>
71 <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>
72 <ul>
73 <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>
74 <li>Signal its existence, and role in the relation, to the rest of the system.</li>
75 </ul>
76 <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>
77 <ul>
78 <li>Each provider unit observes every requirer unit</li>
79 <li>Each requirer unit observes every provider unit</li>
80 <li>Each peer unit observes every other peer unit</li>
81 </ul>
82 <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>
83 <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>
84 <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>
85 <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>
86 <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>
87 <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>
88 <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>
89 </section>
90
91 <section id="relations-in-depth">
92 <h2 id="departing-relations">Departing relations</h2>
93 <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>
94 <ul>
95 <li>For every known related unit -- those which have joined and not yet departed -- run the relation-departed hook.</li>
96 <li>Run the relation-broken hook.</li>
97 <li><code>depart</code> from its scope in the relation.</li>
98 </ul>
99 <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>
100 </section>
101</article>
102<!--Postamble-->
103 </div>
104 </div>
105 </section>
106 </div>
107</div>
108<!--End-Postamble-->
109<!--Footer-->
110 <footer class="global clearfix" role="contentinfo">
111 <nav role="navigation">
112 <div class="footer-a">
113 <div class="clearfix">
114 <ul>
115 <li>
116 <h2><a href="/">Juju</a></h2>
117 <ul>
118 <li><a href="/charms">Charms</a></li>
119 <li><a href="/features">Features</a></li>
120 <li><a href="/deployment">Deployment</a></li>
121 </ul>
122 </li>
123 <li>
124 <h2><a href="/resources">Resources</a></h2>
125 <ul>
126 <li><a href="/resources/juju-overview/">Overview</a></li>
127 <li><a href="/docs/">Documentation</a></li>
128 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
129 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
130 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
131 <li><a href="/resources/videos/">Videos</a></li>
132 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
133 </ul>
134 </li>
135 <li>
136 <h2><a href="/community">Community</a></h2>
137 <ul>
138 <li><a href="/community/blog/">Juju Blog</a></li>
139 <li><a href="/events/">Events</a></li>
140 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
141 <li><a href="/community/charmers/">Charmers</a></li>
142 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
143 <li><a href="/docs/contributing.html">Help with documentation</a></li>
144 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
145 </ul>
146 </li>
147 <li>
148 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
149 <ul>
150 <li><a href="https://jujucharms.com/">Charm store</a></li>
151 <li><a href="/download/">Download Juju</a></li>
152 </ul>
153 </li>
154 </ul>
155 </div>
156 </div>
157 </nav>
158 <div class="legal clearfix">
159 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
160 </div>
161 </footer>
162
163<!--End-Footer-->
164<!--Scripts-->
165 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
166 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
167 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
168 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
169 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
170 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
171 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
172 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
173 <!-- google analytics -->
174 <script>
175 var _gaq = _gaq || [];
176 _gaq.push(['_setAccount', 'UA-1018242-41']);
177 _gaq.push(['_trackPageview']);
178
179 (function() {
180 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
181 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
182 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
183 })();
184 </script>
185<!--End-Scripts-->
186
187</body></html>
0188
=== added file 'htmldocs/authors-service-config.html'
--- htmldocs/authors-service-config.html 1970-01-01 00:00:00 +0000
+++ htmldocs/authors-service-config.html 2013-10-09 20:07:46 +0000
@@ -0,0 +1,210 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25
26
27 <body class="resources">
28
29<!--Header-->
30
31 <header class="banner global" role="banner">
32 <nav role="navigation" class="nav-primary nav-right">
33 <div class="logo">
34 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
35 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
36 <span>Juju</span>
37 </a>
38 </div>
39 <ul>
40 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
41 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
42 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
43 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
44 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
45 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
46 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
47 </ul>
48 <div id="box-search">
49 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
50 <label class="off-left" for="s">Search:</label>
51 <input class="form-text" type="text" value="" name="s" id="s" />
52 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
53 </form>
54 </div>
55 </nav>
56 </header>
57<!--End-Header-->
58<!--Preamble-->
59<div class="wrapper">
60 <div id="main-content" class="inner-wrapper" role="main">
61 <div class="row no-border">
62 <div class="header-navigation-secondary"></div>
63 <h2 class="pagetitle">Juju documentation</h2>
64 </div>
65 <section id="content" class="container-12">
66 <div class="grid-12 doc-container">
67 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
68 <div class="grid-9 doc-content">
69<!--End-Preamble-->
70<article>
71<h1>Service configuration</h1>
72<h2>Introduction</h2>
73<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>
74<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>
75<h2>Using configuration options</h2>
76<p>Configuration options are manipulated using a command line interface. juju provide a set command to aid the administrator in changing values.</p>
77<pre><code>juju set &lt;service name&gt; option=value [option=value]</code></pre>
78<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>
79<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>
80<p>A configuration file may be provided at deployment time using the --config option, as follows:</p>
81<pre><code>juju deploy [--config local.yaml] wordpress myblog
82juju deploy [--config local.yaml] postgres</code></pre>
83<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>
84<p>Below is an example local.yaml containing options which would be used during deployment of a service named myblog.</p>
85<pre><code>myblog:
86 blog-roll: [&#39;http://foobar.com&#39;, &#39;http://testing.com&#39;]
87 blog-title: Awesome Sauce
88 password: n0nsense
89postgres:
90 port: 5432
91 cluster-name: main</code></pre>
92<h2>Creating charms</h2>
93<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>
94<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>
95<p>The following config.yaml would be included in the top level directory of a charm and includes a list of option definitions:</p>
96<pre><code>options:
97 port:
98 default: 80
99 type: int
100 description: Port to listen on
101 admin-email:
102 # type: str is implied
103 default: null
104 description: Email address for the site administrator.</code></pre>
105<p>To access these configuration options from a hook we provide the following:</p>
106<pre><code>config-get [option name]</code></pre>
107<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>
108<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>
109<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>
110<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>
111<h2>Internals</h2>
112<blockquote>
113<p><strong>note</strong></p>
114<dl>
115<dt>This section explains details useful to the implementation but not of</dt>
116<dd><p>interest to the casual reader.</p>
117</dd>
118</dl>
119</blockquote>
120<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>
121</article>
122<!--Postamble-->
123 </div>
124 </div>
125 </section>
126 </div>
127</div>
128<!--End-Postamble-->
129<!--Footer-->
130 <footer class="global clearfix" role="contentinfo">
131 <nav role="navigation">
132 <div class="footer-a">
133 <div class="clearfix">
134 <ul>
135 <li>
136 <h2><a href="/">Juju</a></h2>
137 <ul>
138 <li><a href="/charms">Charms</a></li>
139 <li><a href="/features">Features</a></li>
140 <li><a href="/deployment">Deployment</a></li>
141 </ul>
142 </li>
143 <li>
144 <h2><a href="/resources">Resources</a></h2>
145 <ul>
146 <li><a href="/resources/juju-overview/">Overview</a></li>
147 <li><a href="/docs/">Documentation</a></li>
148 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
149 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
150 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
151 <li><a href="/resources/videos/">Videos</a></li>
152 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
153 </ul>
154 </li>
155 <li>
156 <h2><a href="/community">Community</a></h2>
157 <ul>
158 <li><a href="/community/blog/">Juju Blog</a></li>
159 <li><a href="/events/">Events</a></li>
160 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
161 <li><a href="/community/charmers/">Charmers</a></li>
162 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
163 <li><a href="/docs/contributing.html">Help with documentation</a></li>
164 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
165 </ul>
166 </li>
167 <li>
168 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
169 <ul>
170 <li><a href="https://jujucharms.com/">Charm store</a></li>
171 <li><a href="/download/">Download Juju</a></li>
172 </ul>
173 </li>
174 </ul>
175 </div>
176 </div>
177 </nav>
178 <div class="legal clearfix">
179 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
180 </div>
181 </footer>
182
183<!--End-Footer-->
184
185<!--Scripts-->
186 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
187 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
188 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
189 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
190 <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script>
191 <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script>
192 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script>
193 <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script>
194 <!-- google analytics -->
195 <script>
196 var _gaq = _gaq || [];
197 _gaq.push(['_setAccount', 'UA-1018242-41']);
198 _gaq.push(['_trackPageview']);
199
200 (function() {
201 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
202 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
203 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
204 })();
205 </script>
206<!--End-Scripts-->
207
208
209
210</body></html>
0211
=== removed file 'htmldocs/authors-service-config.html'
--- htmldocs/authors-service-config.html 2013-09-27 14:53:30 +0000
+++ htmldocs/authors-service-config.html 1970-01-01 00:00:00 +0000
@@ -1,208 +0,0 @@
1<!DOCTYPE html>
2<html>
3<!--Head-->
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6 <title>Juju Documentation</title>
7 <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script>
8 <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css">
9 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css">
10 <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" />
11 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" />
12 <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" />
13 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css">
14 <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css">
15 <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">
16 <link href="./css/main.css" rel="stylesheet" type="text/css">
17
18 <!--[if lt IE 9]>
19 <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
20 <![endif]-->
21 </head>
22<!--End-Head-->
23
24
25
26 <body class="resources">
27
28<!--Header-->
29
30 <header class="banner global" role="banner">
31 <nav role="navigation" class="nav-primary nav-right">
32 <div class="logo">
33 <a class="logo-ubuntu" href="https://juju.ubuntu.com/">
34 <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" />
35 <span>Juju</span>
36 </a>
37 </div>
38 <ul>
39 <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li>
40 <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li>
41 <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li>
42 <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li>
43 <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li>
44 <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li>
45 <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li>
46 </ul>
47 <div id="box-search">
48 <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/">
49 <label class="off-left" for="s">Search:</label>
50 <input class="form-text" type="text" value="" name="s" id="s" />
51 <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button>
52 </form>
53 </div>
54 </nav>
55 </header>
56<!--End-Header-->
57<!--Preamble-->
58<div class="wrapper">
59 <div id="main-content" class="inner-wrapper" role="main">
60 <div class="row no-border">
61 <div class="header-navigation-secondary"></div>
62 <h2 class="pagetitle">Juju documentation</h2>
63 </div>
64 <section id="content" class="container-12">
65 <div class="grid-12 doc-container">
66 <div id="navlinks" class="grid-3 doc-navigation">LINKS</div>
67 <div class="grid-9 doc-content">
68<!--End-Preamble-->
69<article>
70<h1>Service configuration</h1>
71<h2>Introduction</h2>
72<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>
73<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>
74<h2>Using configuration options</h2>
75<p>Configuration options are manipulated using a command line interface. juju provide a set command to aid the administrator in changing values.</p>
76<pre><code>juju set &lt;service name&gt; option=value [option=value]</code></pre>
77<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>
78<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>
79<p>A configuration file may be provided at deployment time using the --config option, as follows:</p>
80<pre><code>juju deploy [--config local.yaml] wordpress myblog
81juju deploy [--config local.yaml] postgres</code></pre>
82<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>
83<p>Below is an example local.yaml containing options which would be used during deployment of a service named myblog.</p>
84<pre><code>myblog:
85 blog-roll: [&#39;http://foobar.com&#39;, &#39;http://testing.com&#39;]
86 blog-title: Awesome Sauce
87 password: n0nsense
88postgres:
89 port: 5432
90 cluster-name: main</code></pre>
91<h2>Creating charms</h2>
92<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>
93<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>
94<p>The following config.yaml would be included in the top level directory of a charm and includes a list of option definitions:</p>
95<pre><code>options:
96 port:
97 default: 80
98 type: int
99 description: Port to listen on
100 admin-email:
101 # type: str is implied
102 default: null
103 description: Email address for the site administrator.</code></pre>
104<p>To access these configuration options from a hook we provide the following:</p>
105<pre><code>config-get [option name]</code></pre>
106<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>
107<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>
108<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>
109<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>
110<h2>Internals</h2>
111<blockquote>
112<p><strong>note</strong></p>
113<dl>
114<dt>This section explains details useful to the implementation but not of</dt>
115<dd><p>interest to the casual reader.</p>
116</dd>
117</dl>
118</blockquote>
119<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>
120</article>
121<!--Postamble-->
122 </div>
123 </div>
124 </section>
125 </div>
126</div>
127<!--End-Postamble-->
128<!--Footer-->
129 <footer class="global clearfix" role="contentinfo">
130 <nav role="navigation">
131 <div class="footer-a">
132 <div class="clearfix">
133 <ul>
134 <li>
135 <h2><a href="/">Juju</a></h2>
136 <ul>
137 <li><a href="/charms">Charms</a></li>
138 <li><a href="/features">Features</a></li>
139 <li><a href="/deployment">Deployment</a></li>
140 </ul>
141 </li>
142 <li>
143 <h2><a href="/resources">Resources</a></h2>
144 <ul>
145 <li><a href="/resources/juju-overview/">Overview</a></li>
146 <li><a href="/docs/">Documentation</a></li>
147 <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li>
148 <li><a href="/docs/authors-charm-store.html">The charm store</a></li>
149 <li><a href="/docs/getting-started.html#test">Tutorial</a></li>
150 <li><a href="/resources/videos/">Videos</a></li>
151 <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li>
152 </ul>
153 </li>
154 <li>
155 <h2><a href="/community">Community</a></h2>
156 <ul>
157 <li><a href="/community/blog/">Juju Blog</a></li>
158 <li><a href="/events/">Events</a></li>
159 <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li>
160 <li><a href="/community/charmers/">Charmers</a></li>
161 <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li>
162 <li><a href="/docs/contributing.html">Help with documentation</a></li>
163 <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li>
164 </ul>
165 </li>
166 <li>
167 <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2>
168 <ul>
169 <li><a href="https://jujucharms.com/">Charm store</a></li>
170 <li><a href="/download/">Download Juju</a></li>
171 </ul>
172 </li>
173 </ul>
174 </div>
175 </div>
176 </nav>
177 <div class="legal clearfix">
178 <p>&copy; 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p>
179 </div>
180 </footer>
181
182<!--End-Footer-->
183
184<!--Scripts-->
185 <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script>
186 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
187 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
188 <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script>
189 <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