Merge lp:~jujudocs/juju-core/docs-reorg into lp:juju-core/docs
- docs-reorg
- Merge into 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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nick Veitch (community) | Approve | ||
Review via email: mp+190236@code.launchpad.net |
Commit message
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 : | # |
Revision history for this message
Nick Veitch (evilnick) wrote : | # |
Not that I expect a medal or anything
Revision history for this message
Nick Veitch (evilnick) wrote : | # |
Hurrah! Good work there... Approve
review:
Approve
Revision history for this message
Antonio Rosales (arosales) wrote : | # |
Looks good Nick, thanks for the work on this branch.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed file 'htmldocs/authors-charm-anatomy.html' | |||
2 | --- htmldocs/authors-charm-anatomy.html 2013-09-27 14:53:30 +0000 | |||
3 | +++ htmldocs/authors-charm-anatomy.html 1970-01-01 00:00:00 +0000 | |||
4 | @@ -1,525 +0,0 @@ | |||
5 | 1 | <!DOCTYPE html> | ||
6 | 2 | <html> | ||
7 | 3 | <!--Head--> | ||
8 | 4 | <head> | ||
9 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
10 | 6 | <title>Juju Documentation</title> | ||
11 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
12 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
13 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
14 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
15 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
16 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
17 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
18 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
19 | 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"> | ||
20 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
21 | 17 | |||
22 | 18 | <!--[if lt IE 9]> | ||
23 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
24 | 20 | <![endif]--> | ||
25 | 21 | </head> | ||
26 | 22 | <!--End-Head--> | ||
27 | 23 | |||
28 | 24 | |||
29 | 25 | |||
30 | 26 | <body class="resources"> | ||
31 | 27 | <!--Header--> | ||
32 | 28 | |||
33 | 29 | <header class="banner global" role="banner"> | ||
34 | 30 | <nav role="navigation" class="nav-primary nav-right"> | ||
35 | 31 | <div class="logo"> | ||
36 | 32 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
37 | 33 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
38 | 34 | <span>Juju</span> | ||
39 | 35 | </a> | ||
40 | 36 | </div> | ||
41 | 37 | <ul> | ||
42 | 38 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
43 | 39 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
44 | 40 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
45 | 41 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
46 | 42 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
47 | 43 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
48 | 44 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
49 | 45 | </ul> | ||
50 | 46 | <div id="box-search"> | ||
51 | 47 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
52 | 48 | <label class="off-left" for="s">Search:</label> | ||
53 | 49 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
54 | 50 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
55 | 51 | </form> | ||
56 | 52 | </div> | ||
57 | 53 | </nav> | ||
58 | 54 | </header> | ||
59 | 55 | <!--End-Header--> | ||
60 | 56 | <!--Preamble--> | ||
61 | 57 | <div class="wrapper"> | ||
62 | 58 | <div id="main-content" class="inner-wrapper" role="main"> | ||
63 | 59 | <div class="row no-border"> | ||
64 | 60 | <div class="header-navigation-secondary"></div> | ||
65 | 61 | <h2 class="pagetitle">Juju documentation</h2> | ||
66 | 62 | </div> | ||
67 | 63 | <section id="content" class="container-12"> | ||
68 | 64 | <div class="grid-12 doc-container"> | ||
69 | 65 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
70 | 66 | <div class="grid-9 doc-content"> | ||
71 | 67 | <!--End-Preamble--> | ||
72 | 68 | <article> | ||
73 | 69 | <section id="charm-anatomy"> | ||
74 | 70 | <h1>Anatomy of a charm</h1> | ||
75 | 71 | <p>Charms define how services integrate and how their service units | ||
76 | 72 | react to events in the distributed environment, as orchestrated by | ||
77 | 73 | juju.</p> | ||
78 | 74 | <p>This specification describes how charms are defined, including their | ||
79 | 75 | metadata and hooks. It also describes the resources available to hooks | ||
80 | 76 | in working with the juju environment.</p> | ||
81 | 77 | |||
82 | 78 | <h2>The metadata file</h2> | ||
83 | 79 | <p>The <cite>metadata.yaml</cite> file, at the root of the charm directory, | ||
84 | 80 | describes the charm. The following fields are supported:</p> | ||
85 | 81 | <blockquote> | ||
86 | 82 | <ul> | ||
87 | 83 | <li><strong>name:</strong> - The charm name itself. Charm names are formed by | ||
88 | 84 | lowercase letters, digits, and dashes, and must necessarily | ||
89 | 85 | begin with a letter and have no digits alone in a dashed | ||
90 | 86 | section.</li> | ||
91 | 87 | <li><strong>summary:</strong> - A one-line description of the charm.</li> | ||
92 | 88 | <li><strong>maintainer:</strong> - An RFC2822 compliant email address that should | ||
93 | 89 | be the main point of contact for development of this charm.</li> | ||
94 | 90 | <li><strong>description:</strong> - Long explanation of the charm and its | ||
95 | 91 | features.</li> | ||
96 | 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> | ||
97 | 93 | <li><strong>provides:</strong> - The deployed service unit must have the given | ||
98 | 94 | relations established with another service unit whose charm | ||
99 | 95 | requires them for the service to work properly. See below for how | ||
100 | 96 | to define a relation.</li> | ||
101 | 97 | <li><strong>requires:</strong> - The deployed service unit must have the given | ||
102 | 98 | relations established with another service unit whose charm | ||
103 | 99 | provides them for the service to work properly. See below for how | ||
104 | 100 | to define a relation.</li> | ||
105 | 101 | <li><strong>peers:</strong> - Relations that are established with P2P semantics | ||
106 | 102 | instead of a provides/requires (or client/server) style. When the | ||
107 | 103 | charm is deployed as a service unit, all the units from the | ||
108 | 104 | given service will automatically be made part of the relation. | ||
109 | 105 | See below for how to define a relation.</li> | ||
110 | 106 | </ul> | ||
111 | 107 | </blockquote> | ||
112 | 108 | |||
113 | 109 | <p>Relations available in <cite>provides</cite>, <cite>requires</cite>, and <cite>peers</cite> are defined | ||
114 | 110 | as follows:</p> | ||
115 | 111 | <blockquote> | ||
116 | 112 | <ul> | ||
117 | 113 | <li><p class="first"><strong>provides|requires|peers:</strong></p> | ||
118 | 114 | <ul> | ||
119 | 115 | <li><p class="first"><strong><relation name>:</strong> - This name is a user-provided value which | ||
120 | 116 | identifies the relation uniquely within the given charm. | ||
121 | 117 | Examples include "database", "cache", "proxy", and "appserver".</p> | ||
122 | 118 | <p>Each relation may have the following fields defined:</p> | ||
123 | 119 | <ul> | ||
124 | 120 | <li><strong>interface:</strong> - This field defines the type of the | ||
125 | 121 | relation. The relation will only be established with service | ||
126 | 122 | units that define a compatible relation with the same | ||
127 | 123 | interface. Examples include "http", "mysql", and | ||
128 | 124 | "backup-schedule".</li> | ||
129 | 125 | <li><strong>limit:</strong> - The maximum number of relations of this kind | ||
130 | 126 | which may be established to other service units. Defaults to | ||
131 | 127 | 1 for <cite>requires</cite> relations, and to "none" (no limit) for | ||
132 | 128 | <cite>provides</cite> and <cite>peers</cite> relations. While you may define it, | ||
133 | 129 | this field is not yet enforced by juju.</li> | ||
134 | 130 | <li><strong>optional:</strong> - Whether this relation is required for the | ||
135 | 131 | service unit to function or not. Defaults to <cite>false</cite>, which | ||
136 | 132 | means the relation is required. While you may define it, this | ||
137 | 133 | field is not yet enforced by juju.</li> | ||
138 | 134 | <li><strong>scope:</strong> - Controls which units of related-to services can | ||
139 | 135 | be communicated with through this relationship. Juju supports | ||
140 | 136 | the following scopes:<ul> | ||
141 | 137 | <li><strong>global:</strong> <cite>default</cite> When a traditional relation is added | ||
142 | 138 | between two services, all the service units for the first service will | ||
143 | 139 | receive relation events about all service units for the second | ||
144 | 140 | service.</li> | ||
145 | 141 | <li><strong>container</strong>: Communication is restricted to units deployed | ||
146 | 142 | in the same container. It is not possible to establish a | ||
147 | 143 | container scoped relation between principal services. See | ||
148 | 144 | <a href="authors-subordinate-services.html"><em>Subordinate services</em></a>.</li> | ||
149 | 145 | </ul> | ||
150 | 146 | </li> | ||
151 | 147 | </ul> | ||
152 | 148 | <p>As a shortcut, if these properties are not defined, and instead | ||
153 | 149 | a single string value is provided next to the relation name, the | ||
154 | 150 | string is taken as the interface value, as seen in this | ||
155 | 151 | example:</p> | ||
156 | 152 | <pre><code>requires: | ||
157 | 153 | db: mysql</code></pre> | ||
158 | 154 | |||
159 | 155 | </li> | ||
160 | 156 | </ul> | ||
161 | 157 | </li> | ||
162 | 158 | </ul> | ||
163 | 159 | </blockquote> | ||
164 | 160 | <p>Some sample charm definitions are provided at the end of this | ||
165 | 161 | specification.</p> | ||
166 | 162 | </section> | ||
167 | 163 | |||
168 | 164 | <section id="hooks"> | ||
169 | 165 | <h2>Hooks</h2> | ||
170 | 166 | <p>Juju uses hooks to notify a service unit about changes happening | ||
171 | 167 | in its lifecycle or the larger distributed environment. A hook running | ||
172 | 168 | for a service unit can query this environment, make any desired local | ||
173 | 169 | changes on its underlying machine, and change the relation | ||
174 | 170 | settings.</p> | ||
175 | 171 | <p>Each hook for a charm is implemented by placing an executable with | ||
176 | 172 | the desired hook name under the <span class="pre">hooks/</span> directory of the charm | ||
177 | 173 | directory. juju will execute the hook based on its file name when | ||
178 | 174 | the corresponding event occurs.</p> | ||
179 | 175 | <p>All hooks are optional. Not including a corresponding executable in | ||
180 | 176 | the charm is treated by juju as if the hook executed and then | ||
181 | 177 | exited with an exit code of 0.</p> | ||
182 | 178 | <p>All hooks are executed in the charm directory on the service unit.</p> | ||
183 | 179 | <p>The following hooks are with respect to the lifecycle of a service unit:</p> | ||
184 | 180 | <blockquote> | ||
185 | 181 | <ul> | ||
186 | 182 | <li><strong>install</strong> - Runs just once during the life time of a service | ||
187 | 183 | unit. Currently this hook is the right place to ensure any package | ||
188 | 184 | dependencies are met. However, in the future juju will use the | ||
189 | 185 | charm metadata to perform this role instead.</li> | ||
190 | 186 | <li><strong>config-changed</strong> - runs once after installation, and in response | ||
191 | 187 | to configuration changes (e.g. <span class="pre">juju</span> <span class="pre">set</span>). Service configuration | ||
192 | 188 | actions such as config file generation or runtime tuning should | ||
193 | 189 | happen here.</li> | ||
194 | 190 | <li><strong>start</strong> - Runs when the service unit is started. This happens | ||
195 | 191 | before any relation hooks are called. The purpose of this hook is | ||
196 | 192 | to get the service unit ready for relations to be established.</li> | ||
197 | 193 | <li><strong>stop</strong> - Runs when the service unit is stopped. If relations | ||
198 | 194 | exist, they will be broken and the respective hooks called before | ||
199 | 195 | this hook is called.</li> | ||
200 | 196 | </ul> | ||
201 | 197 | </blockquote> | ||
202 | 198 | <p>The following hooks are called on each service unit as the membership | ||
203 | 199 | of an established relation changes:</p> | ||
204 | 200 | <blockquote> | ||
205 | 201 | <ul> | ||
206 | 202 | <li><p class="first"><strong><relation name>-relation-joined</strong> - Runs upon each time a remote | ||
207 | 203 | service unit joins the relation.</p> | ||
208 | 204 | </li> | ||
209 | 205 | <li><p class="first"><strong><relation name>-relation-changed</strong> - Runs upon each time the | ||
210 | 206 | following events occur:</p> | ||
211 | 207 | <ol class="arabic simple"> | ||
212 | 208 | <li>A remote service unit joins the relation, right after the | ||
213 | 209 | <strong><relation name>-relation-joined</strong> hook was called.</li> | ||
214 | 210 | <li>A remote service unit changes its relation settings.</li> | ||
215 | 211 | </ol> | ||
216 | 212 | <p>This hook enables the charm to modify the service unit state | ||
217 | 213 | (configuration, running processes, or anything else) to adapt to | ||
218 | 214 | the relation settings of remote units.</p> | ||
219 | 215 | <p>An example usage is that HAProxy needs to be aware of web servers | ||
220 | 216 | as they become available, including details like its IP | ||
221 | 217 | address. Web server service units can publish their availability | ||
222 | 218 | by making the appropriate relation settings in the hook that makes | ||
223 | 219 | the most sense. Assume the HAProxy uses the relation name of | ||
224 | 220 | <span class="pre">server</span>. Then upon that happening, the HAProxy in its | ||
225 | 221 | <span class="pre">server-relation-changed</span> <span class="pre">hook</span> can then change its own | ||
226 | 222 | configuration as to what is available to be proxied.</p> | ||
227 | 223 | </li> | ||
228 | 224 | <li><p class="first"><strong><relation name>-relation-departed</strong> - Runs upon each time a | ||
229 | 225 | remote service unit leaves a relation. This could happen because | ||
230 | 226 | the service unit has been removed, its service has been destroyed, | ||
231 | 227 | or the relation between this service and the remote service has | ||
232 | 228 | been removed.</p> | ||
233 | 229 | <p>An example usage is that HAProxy needs to be aware of web servers | ||
234 | 230 | when they are no longer available. It can remove each web server | ||
235 | 231 | its configuration as the corresponding service unit departs the | ||
236 | 232 | relation.</p> | ||
237 | 233 | </li> | ||
238 | 234 | </ul> | ||
239 | 235 | </blockquote> | ||
240 | 236 | <p>This relation hook is with respect to the relation itself:</p> | ||
241 | 237 | <blockquote> | ||
242 | 238 | <ul> | ||
243 | 239 | <li><p class="first"><strong><relation name>-relation-broken</strong> - Runs when a relation which | ||
244 | 240 | had at least one other relation hook run for it (successfully or | ||
245 | 241 | not) is now unavailable. The service unit can then clean up any | ||
246 | 242 | established state.</p> | ||
247 | 243 | <p>An example might be cleaning up the configuration changes which | ||
248 | 244 | were performed when HAProxy was asked to load-balance for another | ||
249 | 245 | service unit.</p> | ||
250 | 246 | </li> | ||
251 | 247 | </ul> | ||
252 | 248 | </blockquote> | ||
253 | 249 | <p>Note that the coupling between charms is defined by which settings | ||
254 | 250 | are required and made available to them through the relation hooks and | ||
255 | 251 | how these settings are used. Those conventions then define what the | ||
256 | 252 | relation interface really is, and the <strong>interface</strong> name in the | ||
257 | 253 | <cite>metadata.yaml</cite> file is simply a way to refer to them and avoid the | ||
258 | 254 | attempting of incompatible conversations. Keep that in mind when | ||
259 | 255 | designing your charms and relations, since it is a good idea to | ||
260 | 256 | allow the implementation of the charm to change and be replaced with | ||
261 | 257 | alternative versions without changing the relation conventions in a | ||
262 | 258 | backwards incompatible way.</p> | ||
263 | 259 | |||
264 | 260 | <h2>Hook environment</h2> | ||
265 | 261 | <p>Hooks can expect to be invoked with a standard environment and | ||
266 | 262 | context. The following environment variables are set:</p> | ||
267 | 263 | <blockquote> | ||
268 | 264 | <ul> | ||
269 | 265 | <li><strong>$JUJU_UNIT_NAME</strong> - The name of the local unit executing, | ||
270 | 266 | in the form <span class="pre"><service</span> <span class="pre">name>/<unit</span> <span class="pre">sequence></span>. E.g. <span class="pre">myblog/3</span>.</li> | ||
271 | 267 | </ul> | ||
272 | 268 | </blockquote> | ||
273 | 269 | <p>Hooks called for relation changes will have the follow additional | ||
274 | 270 | environment variables set:</p> | ||
275 | 271 | <blockquote> | ||
276 | 272 | <ul> | ||
277 | 273 | <li><strong>$JUJU_RELATION</strong> - The relation name this hook is running | ||
278 | 274 | for. It's redundant with the hook name, but is necessary for | ||
279 | 275 | the command line tools to know the current context.</li> | ||
280 | 276 | <li><strong>$JUJU_REMOTE_UNIT</strong> - The unit name of the remote unit | ||
281 | 277 | which has triggered the hook execution.</li> | ||
282 | 278 | </ul> | ||
283 | 279 | </blockquote> | ||
284 | 280 | |||
285 | 281 | <h2>Hook commands for working with relations</h2> | ||
286 | 282 | <p>In implementing their functionality, hooks can leverage a set of | ||
287 | 283 | command tools provided by juju for working with relations. These | ||
288 | 284 | utilities enable the hook to collaborate on their relation settings, | ||
289 | 285 | and to inquire about the peers the service unit has relations with.</p> | ||
290 | 286 | <p>The following command line tools are made available:</p> | ||
291 | 287 | <blockquote> | ||
292 | 288 | <ul> | ||
293 | 289 | <li><p class="first"><strong>relation-ids</strong> - List ids for established relations.</p> | ||
294 | 290 | <p>Example:</p> | ||
295 | 291 | <pre><span class="n">relation</span><span class="o">-</span><span class="n">ids</span> | ||
296 | 292 | </pre> | ||
297 | 293 | |||
298 | 294 | </li> | ||
299 | 295 | <li><p class="first"><strong>relation-list</strong> - List all service units participating in the | ||
300 | 296 | established relation. This list excludes the local service unit | ||
301 | 297 | which is executing the command. For <cite>provides</cite> and <cite>requires</cite> | ||
302 | 298 | relations, this command will always return a single service unit.</p> | ||
303 | 299 | <p>Example:</p> | ||
304 | 300 | <pre>MEMBERS=$(relation-list)</pre> | ||
305 | 301 | |||
306 | 302 | </li> | ||
307 | 303 | <li><p class="first"><strong>relation-get</strong> - Queries a setting from an established relation | ||
308 | 304 | with one or more service units. This command will read some | ||
309 | 305 | context information from environment variables (e.g. | ||
310 | 306 | $JUJU_RELATION_NAME).</p> | ||
311 | 307 | <p>Examples:</p> | ||
312 | 308 | <p>Get the IP address from the remote unit which triggered the hook | ||
313 | 309 | execution:</p> | ||
314 | 310 | <pre>relation-get ip</pre> | ||
315 | 311 | |||
316 | 312 | <p>Get all the settings from the remote unit which triggered the hook | ||
317 | 313 | execution:</p> | ||
318 | 314 | <span class="n">relation</span><span class="o">-</span><span class="n">get</span> | ||
319 | 315 | |||
320 | 316 | |||
321 | 317 | <p>Get the port information from the <cite>wordpress/3</cite> unit:</p> | ||
322 | 318 | <pre>relation-get port wordpress/3</pre> | ||
323 | 319 | |||
324 | 320 | <p>Get all the settings from the <cite>wordpress/3</cite> unit, in JSON format:</p> | ||
325 | 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> | ||
326 | 322 | </pre> | ||
327 | 323 | |||
328 | 324 | </li> | ||
329 | 325 | <li><p class="first"><strong>relation-set</strong> - Changes a setting in an established relation.</p> | ||
330 | 326 | <p>Examples:</p> | ||
331 | 327 | <p>Set this unit's port number for other peers to use:</p> | ||
332 | 328 | <pre>relation-set port=8080</pre> | ||
333 | 329 | |||
334 | 330 | <p>Change two settings at once:</p> | ||
335 | 331 | <pre>relation-set dbname=wordpress dbpass="super secur3"</pre> | ||
336 | 332 | |||
337 | 333 | <p>Change several settings at once, with a JSON file:</p> | ||
338 | 334 | <pre>cat settings.json | relation-set</pre> | ||
339 | 335 | |||
340 | 336 | <p>Delete a setting:</p> | ||
341 | 337 | <pre>relation-set name=</pre> | ||
342 | 338 | |||
343 | 339 | </li> | ||
344 | 340 | </ul> | ||
345 | 341 | </blockquote> | ||
346 | 342 | <p>Changes to relation settings are only committed if the hook exited | ||
347 | 343 | with an exit code of 0. Such changes will then trigger further hook | ||
348 | 344 | execution in the remote unit(s), through the <strong><relation | ||
349 | 345 | name>-relation-changed</strong> hook. This mechanism enables a general | ||
350 | 346 | communication mechanism for service units to coordinate.</p> | ||
351 | 347 | |||
352 | 348 | |||
353 | 349 | <h2>Hook commands for opening and closing ports></h2> | ||
354 | 350 | <p>Service exposing determines which ports to expose by using the | ||
355 | 351 | <span class="pre">open-port</span> and <span class="pre">close-port</span> commands in hooks. They may be | ||
356 | 352 | executed within any charm hook. The commands take the same | ||
357 | 353 | arguments:</p> | ||
358 | 354 | <pre>open-port port[/protocol] | ||
359 | 355 | |||
360 | 356 | close-port port[/protocol]</pre> | ||
361 | 357 | |||
362 | 358 | <p>These commands are executed immediately; they do not depend on the | ||
363 | 359 | exit status of the hook.</p> | ||
364 | 360 | <p>As an example, consider the WordPress charm, which has been deployed | ||
365 | 361 | as <span class="pre">my-wordpress</span>. After completing the setup and restart of Apache, | ||
366 | 362 | the <span class="pre">wordpress</span> charm can then publish the available port in its | ||
367 | 363 | <span class="pre">start</span> hook for a given service unit:</p> | ||
368 | 364 | <pre>open-port 80</pre> | ||
369 | 365 | |||
370 | 366 | <p>External access to the service unit is only allowed when both | ||
371 | 367 | <span class="pre">open-port</span> is executed within any hook and the administrator has | ||
372 | 368 | exposed its service. The order in which these happen is not | ||
373 | 369 | important, however.</p> | ||
374 | 370 | |||
375 | 371 | <p class="note"><strong>Note: </strong>Being able to use any hook may be important for your charm. | ||
376 | 372 | Ideally, the service does not have ports that are vulnerable if | ||
377 | 373 | exposed prior to the service being fully ready. But if that's the | ||
378 | 374 | case, you can solve this problem by only opening the port in the | ||
379 | 375 | appropriate hook and when the desired conditions are met.</p> | ||
380 | 376 | |||
381 | 377 | <p>Alternatively, you may need to expose more than one port, or expose | ||
382 | 378 | ports that don't use the TCP protocol. To expose ports for | ||
383 | 379 | HTTP and HTTPS, your charm could instead make these settings:</p> | ||
384 | 380 | <pre>open-port 80 | ||
385 | 381 | open-port 443</pre> | ||
386 | 382 | |||
387 | 383 | <p>Or if you are writing a charm for a DNS server that you would like | ||
388 | 384 | to expose, then specify the protocol to be UDP:</p> | ||
389 | 385 | <pre>open-port 53/udp</pre> | ||
390 | 386 | |||
391 | 387 | <p>When the service unit is removed or stopped for any reason, the | ||
392 | 388 | firewall will again be changed to block traffic which was previously | ||
393 | 389 | allowed to reach the exposed service. Your charm can also do this to | ||
394 | 390 | close the port:</p> | ||
395 | 391 | <pre>close-port 80</pre> | ||
396 | 392 | |||
397 | 393 | <p>To be precise, the firewall is only open for the exposed ports during | ||
398 | 394 | the time both these conditions hold:</p> | ||
399 | 395 | <blockquote> | ||
400 | 396 | <ul> | ||
401 | 397 | <li>A service has been exposed.</li> | ||
402 | 398 | <li>A corresponding <span class="pre">open-port</span> command has been run (without a | ||
403 | 399 | subsequent <span class="pre">close-port</span>).</li> | ||
404 | 400 | </ul> | ||
405 | 401 | </blockquote> | ||
406 | 402 | |||
407 | 403 | <h2>Sample metadata.yaml files</h2> | ||
408 | 404 | <p>Below are presented some sample metadata files.</p> | ||
409 | 405 | <p>MySQL:</p> | ||
410 | 406 | <pre>name: mysql | ||
411 | 407 | summary: "A pretty popular database" | ||
412 | 408 | maintainer: "Juju Charmers <juju@lists.ubuntu.com>" | ||
413 | 409 | |||
414 | 410 | provides: | ||
415 | 411 | db: mysql</pre> | ||
416 | 412 | |||
417 | 413 | <p>Wordpress:</p> | ||
418 | 414 | <pre>name: wordpress | ||
419 | 415 | summary: "A pretty popular blog engine" | ||
420 | 416 | maintainer: "Juju Charmers <juju@lists.ubuntu.com>" | ||
421 | 417 | provides: | ||
422 | 418 | url: | ||
423 | 419 | interface: http | ||
424 | 420 | |||
425 | 421 | requires: | ||
426 | 422 | db: | ||
427 | 423 | interface: mysql</pre> | ||
428 | 424 | |||
429 | 425 | <p>Riak:</p> | ||
430 | 426 | <pre>name: riak | ||
431 | 427 | summary: "Scalable K/V Store in Erlang with Clocks :-)" | ||
432 | 428 | maintainer: "Juju Charmers <juju@lists.ubuntu.com>" | ||
433 | 429 | provides: | ||
434 | 430 | endpoint: | ||
435 | 431 | interface: http | ||
436 | 432 | |||
437 | 433 | peers: | ||
438 | 434 | ring: | ||
439 | 435 | interface: riak</pre> | ||
440 | 436 | |||
441 | 437 | </section> | ||
442 | 438 | </article> | ||
443 | 439 | <!--Postamble--> | ||
444 | 440 | </div> | ||
445 | 441 | </div> | ||
446 | 442 | </section> | ||
447 | 443 | </div> | ||
448 | 444 | </div> | ||
449 | 445 | <!--End-Postamble--> | ||
450 | 446 | <!--Footer--> | ||
451 | 447 | <footer class="global clearfix" role="contentinfo"> | ||
452 | 448 | <nav role="navigation"> | ||
453 | 449 | <div class="footer-a"> | ||
454 | 450 | <div class="clearfix"> | ||
455 | 451 | <ul> | ||
456 | 452 | <li> | ||
457 | 453 | <h2><a href="/">Juju</a></h2> | ||
458 | 454 | <ul> | ||
459 | 455 | <li><a href="/charms">Charms</a></li> | ||
460 | 456 | <li><a href="/features">Features</a></li> | ||
461 | 457 | <li><a href="/deployment">Deployment</a></li> | ||
462 | 458 | </ul> | ||
463 | 459 | </li> | ||
464 | 460 | <li> | ||
465 | 461 | <h2><a href="/resources">Resources</a></h2> | ||
466 | 462 | <ul> | ||
467 | 463 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
468 | 464 | <li><a href="/docs/">Documentation</a></li> | ||
469 | 465 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
470 | 466 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
471 | 467 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
472 | 468 | <li><a href="/resources/videos/">Videos</a></li> | ||
473 | 469 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
474 | 470 | </ul> | ||
475 | 471 | </li> | ||
476 | 472 | <li> | ||
477 | 473 | <h2><a href="/community">Community</a></h2> | ||
478 | 474 | <ul> | ||
479 | 475 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
480 | 476 | <li><a href="/events/">Events</a></li> | ||
481 | 477 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
482 | 478 | <li><a href="/community/charmers/">Charmers</a></li> | ||
483 | 479 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
484 | 480 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
485 | 481 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
486 | 482 | </ul> | ||
487 | 483 | </li> | ||
488 | 484 | <li> | ||
489 | 485 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
490 | 486 | <ul> | ||
491 | 487 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
492 | 488 | <li><a href="/download/">Download Juju</a></li> | ||
493 | 489 | </ul> | ||
494 | 490 | </li> | ||
495 | 491 | </ul> | ||
496 | 492 | </div> | ||
497 | 493 | </div> | ||
498 | 494 | </nav> | ||
499 | 495 | <div class="legal clearfix"> | ||
500 | 496 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
501 | 497 | </div> | ||
502 | 498 | </footer> | ||
503 | 499 | |||
504 | 500 | <!--End-Footer--> | ||
505 | 501 | <!--Scripts--> | ||
506 | 502 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
507 | 503 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
508 | 504 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
509 | 505 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
510 | 506 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
511 | 507 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
512 | 508 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
513 | 509 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
514 | 510 | <!-- google analytics --> | ||
515 | 511 | <script> | ||
516 | 512 | var _gaq = _gaq || []; | ||
517 | 513 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
518 | 514 | _gaq.push(['_trackPageview']); | ||
519 | 515 | |||
520 | 516 | (function() { | ||
521 | 517 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
522 | 518 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
523 | 519 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
524 | 520 | })(); | ||
525 | 521 | </script> | ||
526 | 522 | <!--End-Scripts--> | ||
527 | 523 | |||
528 | 524 | |||
529 | 525 | </body></html> | ||
530 | 526 | \ No newline at end of file | 0 | \ No newline at end of file |
531 | 527 | 1 | ||
532 | === modified file 'htmldocs/authors-charm-best-practice.html' | |||
533 | --- htmldocs/authors-charm-best-practice.html 2013-09-27 14:53:30 +0000 | |||
534 | +++ htmldocs/authors-charm-best-practice.html 2013-10-09 20:07:46 +0000 | |||
535 | @@ -23,6 +23,8 @@ | |||
536 | 23 | 23 | ||
537 | 24 | 24 | ||
538 | 25 | 25 | ||
539 | 26 | |||
540 | 27 | |||
541 | 26 | <body class="resources"> | 28 | <body class="resources"> |
542 | 27 | 29 | ||
543 | 28 | <!--Header--> | 30 | <!--Header--> |
544 | @@ -220,4 +222,6 @@ | |||
545 | 220 | <!--End-Scripts--> | 222 | <!--End-Scripts--> |
546 | 221 | 223 | ||
547 | 222 | 224 | ||
548 | 225 | |||
549 | 226 | |||
550 | 223 | </body></html> | 227 | </body></html> |
551 | 224 | 228 | ||
552 | === added file 'htmldocs/authors-charm-components.html' | |||
553 | --- htmldocs/authors-charm-components.html 1970-01-01 00:00:00 +0000 | |||
554 | +++ htmldocs/authors-charm-components.html 2013-10-09 20:07:46 +0000 | |||
555 | @@ -0,0 +1,235 @@ | |||
556 | 1 | <!DOCTYPE html> | ||
557 | 2 | <html> | ||
558 | 3 | <!--Head--> | ||
559 | 4 | <head> | ||
560 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
561 | 6 | <title>Juju Documentation</title> | ||
562 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
563 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
564 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
565 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
566 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
567 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
568 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
569 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
570 | 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"> | ||
571 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
572 | 17 | |||
573 | 18 | <!--[if lt IE 9]> | ||
574 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
575 | 20 | <![endif]--> | ||
576 | 21 | </head> | ||
577 | 22 | <!--End-Head--> | ||
578 | 23 | |||
579 | 24 | |||
580 | 25 | <body class="resources"> | ||
581 | 26 | <!--Header--> | ||
582 | 27 | |||
583 | 28 | <header class="banner global" role="banner"> | ||
584 | 29 | <nav role="navigation" class="nav-primary nav-right"> | ||
585 | 30 | <div class="logo"> | ||
586 | 31 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
587 | 32 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
588 | 33 | <span>Juju</span> | ||
589 | 34 | </a> | ||
590 | 35 | </div> | ||
591 | 36 | <ul> | ||
592 | 37 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
593 | 38 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
594 | 39 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
595 | 40 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
596 | 41 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
597 | 42 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
598 | 43 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
599 | 44 | </ul> | ||
600 | 45 | <div id="box-search"> | ||
601 | 46 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
602 | 47 | <label class="off-left" for="s">Search:</label> | ||
603 | 48 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
604 | 49 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
605 | 50 | </form> | ||
606 | 51 | </div> | ||
607 | 52 | </nav> | ||
608 | 53 | </header> | ||
609 | 54 | <!--End-Header--> | ||
610 | 55 | <!--Preamble--> | ||
611 | 56 | <div class="wrapper"> | ||
612 | 57 | <div id="main-content" class="inner-wrapper" role="main"> | ||
613 | 58 | <div class="row no-border"> | ||
614 | 59 | <div class="header-navigation-secondary"></div> | ||
615 | 60 | <h2 class="pagetitle">Juju documentation</h2> | ||
616 | 61 | </div> | ||
617 | 62 | <section id="content" class="container-12"> | ||
618 | 63 | <div class="grid-12 doc-container"> | ||
619 | 64 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
620 | 65 | <div class="grid-9 doc-content"> | ||
621 | 66 | <!--End-Preamble--> | ||
622 | 67 | <article> | ||
623 | 68 | <section id="charm-contents"> | ||
624 | 69 | <h1>What makes a Charm?</h1> | ||
625 | 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> | ||
626 | 71 | </section> | ||
627 | 72 | |||
628 | 73 | <section id="required-files"> | ||
629 | 74 | <h2>Required files</h2> | ||
630 | 75 | <p>A charm requires only a single file in order to be considered valid by juju: | ||
631 | 76 | <ul> | ||
632 | 77 | <li><code>metadata.yaml</code> <a href="./authors-charm-metadata.html">describes the | ||
633 | 78 | charm</a> and the relations it can participate in.</li> | ||
634 | 79 | </ul> | ||
635 | 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> | ||
636 | 81 | </section> | ||
637 | 82 | |||
638 | 83 | <section id="special-files"> | ||
639 | 84 | <h2>Special files</h2> | ||
640 | 85 | <p>The following files will be treated specially, if present:</p> | ||
641 | 86 | <ul> | ||
642 | 87 | <li><code>/hooks</code> must be a directory holding | ||
643 | 88 | executables with specific names, that will be invoked by juju at the relevant times. | ||
644 | 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> | ||
645 | 90 | <li><code>config.yaml</code> defines service configuration options.<a href="./authors-charm-config.html"> | ||
646 | 91 | The config.yaml file is descibed more fully here</a>.</li> | ||
647 | 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> | ||
648 | 93 | <li><code>README</code> is made available in the charm store. It should be | ||
649 | 94 | comprehensible to a reasonably ignorant user.</li> | ||
650 | 95 | <li><code>revision</code> is now deprecated.</li> | ||
651 | 96 | <li> files matching <code>.juju*</code> should <strong>not</strong> be used.</li> | ||
652 | 97 | </ul> | ||
653 | 98 | </section> | ||
654 | 99 | |||
655 | 100 | <section id="other-files"> | ||
656 | 101 | <h2>Other files</h2> | ||
657 | 102 | |||
658 | 103 | <p>Any other files you know you'll need can be placed in the charm for convenience. | ||
659 | 104 | It is recommended to leave the hooks directory for the executable hooks alone - library | ||
660 | 105 | code may be included elsewhere in the charm.</p> | ||
661 | 106 | |||
662 | 107 | <p>When hooks are actually running, they can read and write to the charm directory | ||
663 | 108 | freely, but should carefully observe the caveats in the next section...</p> | ||
664 | 109 | </section> | ||
665 | 110 | |||
666 | 111 | <section id="runtime-files"> | ||
667 | 112 | <h2>Charm files at runtime</h2> | ||
668 | 113 | |||
669 | 114 | <p>The files you store with your charm should <em>not</em> be used directly by the | ||
670 | 115 | software installed by your charm. If the files are really needed by the software | ||
671 | 116 | at runtime, copy them on the system alongside the software and reference those | ||
672 | 117 | instead.</p> | ||
673 | 118 | |||
674 | 119 | <p>This is because the software does <em>not</em> have control over the charm directory; | ||
675 | 120 | <em>juju</em> has control over the charm directory, which it temporarily cedes to the | ||
676 | 121 | charm only when running a hook. Juju will occasionally do things to the contents | ||
677 | 122 | of that directory that assume it is neither read nor written outside a hook, and | ||
678 | 123 | the results of such interactions can only be undefined.</p> | ||
679 | 124 | |||
680 | 125 | <p>The only files you should be writing into the charm directory should be written | ||
681 | 126 | by hooks and accessed only by hooks. If everything in your charm directory | ||
682 | 127 | went away, that should be considered a <em>management</em> failure only; the software | ||
683 | 128 | installed should continue to run, using its last known good configuration, and | ||
684 | 129 | should do this by virtue of never having had the opportunity to observe the | ||
685 | 130 | change.</p> | ||
686 | 131 | |||
687 | 132 | <p>Finally, any file written at runtime constrains all future implementations of | ||
688 | 133 | the charm. When <a href="./authors-charm-upgrades.html">upgrading a charm</a>, any | ||
689 | 134 | change that would cause runtime state to be overwritten will cause juju to abort | ||
690 | 135 | the operation and hand over to the user for resolution. This is inconvenient for | ||
691 | 136 | the users and undermines confidence in the charm.</p> | ||
692 | 137 | |||
693 | 138 | <p class="note"> <strong>Note: </strong> You need to be especially aware of the following | ||
694 | 139 | when writing python code: | ||
695 | 140 | Python packages run without bytecode suppression will write <code>.pyc</code> files into | ||
696 | 141 | the package, and subsequent attempts to move or remove the package will fail: | ||
697 | 142 | the .pyc files are treated as important hook-relevant runtime state information, to be | ||
698 | 143 | recorded and tracked, and the loss of their directory will put the unit into | ||
699 | 144 | an upgrade error state as referenced above.</p> | ||
700 | 145 | </section> | ||
701 | 146 | |||
702 | 147 | </article> | ||
703 | 148 | <!--Postamble--> | ||
704 | 149 | </div> | ||
705 | 150 | </div> | ||
706 | 151 | </section> | ||
707 | 152 | </div> | ||
708 | 153 | </div> | ||
709 | 154 | <!--End-Postamble--> | ||
710 | 155 | <!--Footer--> | ||
711 | 156 | <footer class="global clearfix" role="contentinfo"> | ||
712 | 157 | <nav role="navigation"> | ||
713 | 158 | <div class="footer-a"> | ||
714 | 159 | <div class="clearfix"> | ||
715 | 160 | <ul> | ||
716 | 161 | <li> | ||
717 | 162 | <h2><a href="/">Juju</a></h2> | ||
718 | 163 | <ul> | ||
719 | 164 | <li><a href="/charms">Charms</a></li> | ||
720 | 165 | <li><a href="/features">Features</a></li> | ||
721 | 166 | <li><a href="/deployment">Deployment</a></li> | ||
722 | 167 | </ul> | ||
723 | 168 | </li> | ||
724 | 169 | <li> | ||
725 | 170 | <h2><a href="/resources">Resources</a></h2> | ||
726 | 171 | <ul> | ||
727 | 172 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
728 | 173 | <li><a href="/docs/">Documentation</a></li> | ||
729 | 174 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
730 | 175 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
731 | 176 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
732 | 177 | <li><a href="/resources/videos/">Videos</a></li> | ||
733 | 178 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
734 | 179 | </ul> | ||
735 | 180 | </li> | ||
736 | 181 | <li> | ||
737 | 182 | <h2><a href="/community">Community</a></h2> | ||
738 | 183 | <ul> | ||
739 | 184 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
740 | 185 | <li><a href="/events/">Events</a></li> | ||
741 | 186 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
742 | 187 | <li><a href="/community/charmers/">Charmers</a></li> | ||
743 | 188 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
744 | 189 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
745 | 190 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
746 | 191 | </ul> | ||
747 | 192 | </li> | ||
748 | 193 | <li> | ||
749 | 194 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
750 | 195 | <ul> | ||
751 | 196 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
752 | 197 | <li><a href="/download/">Download Juju</a></li> | ||
753 | 198 | </ul> | ||
754 | 199 | </li> | ||
755 | 200 | </ul> | ||
756 | 201 | </div> | ||
757 | 202 | </div> | ||
758 | 203 | </nav> | ||
759 | 204 | <div class="legal clearfix"> | ||
760 | 205 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
761 | 206 | </div> | ||
762 | 207 | </footer> | ||
763 | 208 | |||
764 | 209 | <!--End-Footer--> | ||
765 | 210 | <!--Scripts--> | ||
766 | 211 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
767 | 212 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
768 | 213 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
769 | 214 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
770 | 215 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
771 | 216 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
772 | 217 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
773 | 218 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
774 | 219 | <!-- google analytics --> | ||
775 | 220 | <script> | ||
776 | 221 | var _gaq = _gaq || []; | ||
777 | 222 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
778 | 223 | _gaq.push(['_trackPageview']); | ||
779 | 224 | |||
780 | 225 | (function() { | ||
781 | 226 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
782 | 227 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
783 | 228 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
784 | 229 | })(); | ||
785 | 230 | </script> | ||
786 | 231 | <!--End-Scripts--> | ||
787 | 232 | |||
788 | 233 | |||
789 | 234 | </body></html> | ||
790 | 235 | |||
791 | 0 | 236 | ||
792 | === added file 'htmldocs/authors-charm-config.html' | |||
793 | --- htmldocs/authors-charm-config.html 1970-01-01 00:00:00 +0000 | |||
794 | +++ htmldocs/authors-charm-config.html 2013-10-09 20:07:46 +0000 | |||
795 | @@ -0,0 +1,244 @@ | |||
796 | 1 | <!DOCTYPE html> | ||
797 | 2 | <html> | ||
798 | 3 | <!--Head--> | ||
799 | 4 | <head> | ||
800 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
801 | 6 | <title>Juju Documentation</title> | ||
802 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
803 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
804 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
805 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
806 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
807 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
808 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
809 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
810 | 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"> | ||
811 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
812 | 17 | |||
813 | 18 | <!--[if lt IE 9]> | ||
814 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
815 | 20 | <![endif]--> | ||
816 | 21 | </head> | ||
817 | 22 | <!--End-Head--> | ||
818 | 23 | |||
819 | 24 | |||
820 | 25 | <body class="resources"> | ||
821 | 26 | <!--Header--> | ||
822 | 27 | |||
823 | 28 | <header class="banner global" role="banner"> | ||
824 | 29 | <nav role="navigation" class="nav-primary nav-right"> | ||
825 | 30 | <div class="logo"> | ||
826 | 31 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
827 | 32 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
828 | 33 | <span>Juju</span> | ||
829 | 34 | </a> | ||
830 | 35 | </div> | ||
831 | 36 | <ul> | ||
832 | 37 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
833 | 38 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
834 | 39 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
835 | 40 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
836 | 41 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
837 | 42 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
838 | 43 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
839 | 44 | </ul> | ||
840 | 45 | <div id="box-search"> | ||
841 | 46 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
842 | 47 | <label class="off-left" for="s">Search:</label> | ||
843 | 48 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
844 | 49 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
845 | 50 | </form> | ||
846 | 51 | </div> | ||
847 | 52 | </nav> | ||
848 | 53 | </header> | ||
849 | 54 | <!--End-Header--> | ||
850 | 55 | <!--Preamble--> | ||
851 | 56 | <div class="wrapper"> | ||
852 | 57 | <div id="main-content" class="inner-wrapper" role="main"> | ||
853 | 58 | <div class="row no-border"> | ||
854 | 59 | <div class="header-navigation-secondary"></div> | ||
855 | 60 | <h2 class="pagetitle">Juju documentation</h2> | ||
856 | 61 | </div> | ||
857 | 62 | <section id="content" class="container-12"> | ||
858 | 63 | <div class="grid-12 doc-container"> | ||
859 | 64 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
860 | 65 | <div class="grid-9 doc-content"> | ||
861 | 66 | <!--End-Preamble--> | ||
862 | 67 | <article> | ||
863 | 68 | |||
864 | 69 | <section id="charm-configuration"> | ||
865 | 70 | <h1>Charm configuration</h1> | ||
866 | 71 | |||
867 | 72 | <p>The optional <code>config.yaml</code> file defines how a service running the | ||
868 | 73 | charm can be configured by its user.</p> | ||
869 | 74 | |||
870 | 75 | <p>If it exists, it must contain a dictionary of <code>options</code>, in which | ||
871 | 76 | each possible setting is named by the key and defined by the value. An option | ||
872 | 77 | definition may contain any number of the following fields:</p> | ||
873 | 78 | <ul> | ||
874 | 79 | <li><code>type</code> can be <code>string</code>, <code>int</code>, <code>float</code>, | ||
875 | 80 | or <code>boolean</code>. If not present, it defaults to <code>string</code>.</li> | ||
876 | 81 | <li><code>description</code> should contain an explanation of what the user might | ||
877 | 82 | achieve by altering the setting.</li> | ||
878 | 83 | <li><code>default</code> should, if present, contain a value of the appropriate | ||
879 | 84 | type. If not present it is treated as null (which is always a valid value in this | ||
880 | 85 | context); an option with no default will not normally be reported by the | ||
881 | 86 | config-get <a href="./authors-hook-environment.html">hook tool</a> unless it | ||
882 | 87 | has been explicitly set.</li> | ||
883 | 88 | </ul> | ||
884 | 89 | </section> | ||
885 | 90 | |||
886 | 91 | <section id="picking-options"> | ||
887 | 92 | <h2>What to expose to users</h2> | ||
888 | 93 | |||
889 | 94 | <p>The charm configuration is deliberately somewhat restrictive, in the hope of | ||
890 | 95 | encouraging charmers to expose only features that are clear and comprehensible. | ||
891 | 96 | The user doesn't want to configure the software - they want to configure the | ||
892 | 97 | <em>service</em>, which exists at a higher level of abstraction. A charm with | ||
893 | 98 | a single opinionated <code>tuning</code> option is, from this perspective, | ||
894 | 99 | infinitely superior to one that exposes 6 arcane options that correspond | ||
895 | 100 | directly to flags or config settings for the software.</p> | ||
896 | 101 | |||
897 | 102 | <p>In short, the config is part of the user interface for the charm - it needs to be concise and | ||
898 | 103 | as easy to understand and use as possible. If you're considering using base64 | ||
899 | 104 | encoding to slip structured data through the deliberately restrictive configuration | ||
900 | 105 | language, you're probably "Doing It Wrong".</p> | ||
901 | 106 | </section> | ||
902 | 107 | |||
903 | 108 | <section id="default-options"> | ||
904 | 109 | <h2>Default configuration</h2> | ||
905 | 110 | |||
906 | 111 | <p>Your charm should operate correctly with no explicit configuration settings. | ||
907 | 112 | The first time someone uses your charm, they're likely to run <code>juju deploy yourcharm</code> | ||
908 | 113 | and see what happens; if it doesn't work out of the box ont the first go, | ||
909 | 114 | many potential users won't give it a second try.</p> | ||
910 | 115 | </section> | ||
911 | 116 | |||
912 | 117 | |||
913 | 118 | <h2>Warning</h2> | ||
914 | 119 | |||
915 | 120 | <p class="Warning"><strong>Warning: </strong> There's a <a href="https://bugs.launchpad.net/juju-core/+bug/1194945">bug</a> | ||
916 | 121 | in the service configuration CLI at the moment; if a string-typed option has an | ||
917 | 122 | explicit default that is <em>not</em> the empty string, it will become | ||
918 | 123 | impossible to set the value to the empty string at runtime. If your option | ||
919 | 124 | needs to accept an empty string value, it should make the empty string the | ||
920 | 125 | explicit default value.</p> | ||
921 | 126 | </section> | ||
922 | 127 | |||
923 | 128 | <section id="examples"> | ||
924 | 129 | <h2>Sample config.yaml files</h2> | ||
925 | 130 | |||
926 | 131 | <p> The MediaWiki has some simple but useful configuration options:</p> | ||
927 | 132 | <pre class="prettyprint"> | ||
928 | 133 | options: | ||
929 | 134 | name: | ||
930 | 135 | default: Please set name of wiki | ||
931 | 136 | description: The name, or Title of the Wiki | ||
932 | 137 | type: string | ||
933 | 138 | skin: | ||
934 | 139 | default: vector | ||
935 | 140 | description: skin for the Wiki | ||
936 | 141 | type: string | ||
937 | 142 | logo: | ||
938 | 143 | description: URL to fetch logo from | ||
939 | 144 | type: string | ||
940 | 145 | admins: | ||
941 | 146 | description: Admin users to create, user:pass | ||
942 | 147 | type: string | ||
943 | 148 | debug: | ||
944 | 149 | default: false | ||
945 | 150 | type: boolean | ||
946 | 151 | description: turn on debugging features of mediawiki | ||
947 | 152 | </pre> | ||
948 | 153 | |||
949 | 154 | </section> | ||
950 | 155 | |||
951 | 156 | </article> | ||
952 | 157 | </article> | ||
953 | 158 | <!--Postamble--> | ||
954 | 159 | </div> | ||
955 | 160 | </div> | ||
956 | 161 | </section> | ||
957 | 162 | </div> | ||
958 | 163 | </div> | ||
959 | 164 | <!--End-Postamble--> | ||
960 | 165 | <!--Footer--> | ||
961 | 166 | <footer class="global clearfix" role="contentinfo"> | ||
962 | 167 | <nav role="navigation"> | ||
963 | 168 | <div class="footer-a"> | ||
964 | 169 | <div class="clearfix"> | ||
965 | 170 | <ul> | ||
966 | 171 | <li> | ||
967 | 172 | <h2><a href="/">Juju</a></h2> | ||
968 | 173 | <ul> | ||
969 | 174 | <li><a href="/charms">Charms</a></li> | ||
970 | 175 | <li><a href="/features">Features</a></li> | ||
971 | 176 | <li><a href="/deployment">Deployment</a></li> | ||
972 | 177 | </ul> | ||
973 | 178 | </li> | ||
974 | 179 | <li> | ||
975 | 180 | <h2><a href="/resources">Resources</a></h2> | ||
976 | 181 | <ul> | ||
977 | 182 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
978 | 183 | <li><a href="/docs/">Documentation</a></li> | ||
979 | 184 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
980 | 185 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
981 | 186 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
982 | 187 | <li><a href="/resources/videos/">Videos</a></li> | ||
983 | 188 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
984 | 189 | </ul> | ||
985 | 190 | </li> | ||
986 | 191 | <li> | ||
987 | 192 | <h2><a href="/community">Community</a></h2> | ||
988 | 193 | <ul> | ||
989 | 194 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
990 | 195 | <li><a href="/events/">Events</a></li> | ||
991 | 196 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
992 | 197 | <li><a href="/community/charmers/">Charmers</a></li> | ||
993 | 198 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
994 | 199 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
995 | 200 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
996 | 201 | </ul> | ||
997 | 202 | </li> | ||
998 | 203 | <li> | ||
999 | 204 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
1000 | 205 | <ul> | ||
1001 | 206 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
1002 | 207 | <li><a href="/download/">Download Juju</a></li> | ||
1003 | 208 | </ul> | ||
1004 | 209 | </li> | ||
1005 | 210 | </ul> | ||
1006 | 211 | </div> | ||
1007 | 212 | </div> | ||
1008 | 213 | </nav> | ||
1009 | 214 | <div class="legal clearfix"> | ||
1010 | 215 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
1011 | 216 | </div> | ||
1012 | 217 | </footer> | ||
1013 | 218 | |||
1014 | 219 | <!--End-Footer--> | ||
1015 | 220 | <!--Scripts--> | ||
1016 | 221 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
1017 | 222 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
1018 | 223 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
1019 | 224 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
1020 | 225 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
1021 | 226 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
1022 | 227 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
1023 | 228 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
1024 | 229 | <!-- google analytics --> | ||
1025 | 230 | <script> | ||
1026 | 231 | var _gaq = _gaq || []; | ||
1027 | 232 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
1028 | 233 | _gaq.push(['_trackPageview']); | ||
1029 | 234 | |||
1030 | 235 | (function() { | ||
1031 | 236 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
1032 | 237 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
1033 | 238 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
1034 | 239 | })(); | ||
1035 | 240 | </script> | ||
1036 | 241 | <!--End-Scripts--> | ||
1037 | 242 | |||
1038 | 243 | |||
1039 | 244 | </body></html> | ||
1040 | 0 | 245 | ||
1041 | === added file 'htmldocs/authors-charm-hooks.html' | |||
1042 | --- htmldocs/authors-charm-hooks.html 1970-01-01 00:00:00 +0000 | |||
1043 | +++ htmldocs/authors-charm-hooks.html 2013-10-09 20:07:46 +0000 | |||
1044 | @@ -0,0 +1,387 @@ | |||
1045 | 1 | <!DOCTYPE html> | ||
1046 | 2 | <html> | ||
1047 | 3 | <!--Head--> | ||
1048 | 4 | <head> | ||
1049 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
1050 | 6 | <title>Juju Documentation</title> | ||
1051 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
1052 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
1053 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
1054 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
1055 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
1056 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
1057 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
1058 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
1059 | 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"> | ||
1060 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
1061 | 17 | |||
1062 | 18 | <!--[if lt IE 9]> | ||
1063 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
1064 | 20 | <![endif]--> | ||
1065 | 21 | </head> | ||
1066 | 22 | <!--End-Head--> | ||
1067 | 23 | |||
1068 | 24 | |||
1069 | 25 | <body class="resources"> | ||
1070 | 26 | <!--Header--> | ||
1071 | 27 | |||
1072 | 28 | <header class="banner global" role="banner"> | ||
1073 | 29 | <nav role="navigation" class="nav-primary nav-right"> | ||
1074 | 30 | <div class="logo"> | ||
1075 | 31 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
1076 | 32 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
1077 | 33 | <span>Juju</span> | ||
1078 | 34 | </a> | ||
1079 | 35 | </div> | ||
1080 | 36 | <ul> | ||
1081 | 37 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
1082 | 38 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
1083 | 39 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
1084 | 40 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
1085 | 41 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
1086 | 42 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
1087 | 43 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
1088 | 44 | </ul> | ||
1089 | 45 | <div id="box-search"> | ||
1090 | 46 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
1091 | 47 | <label class="off-left" for="s">Search:</label> | ||
1092 | 48 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
1093 | 49 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
1094 | 50 | </form> | ||
1095 | 51 | </div> | ||
1096 | 52 | </nav> | ||
1097 | 53 | </header> | ||
1098 | 54 | <!--End-Header--> | ||
1099 | 55 | <!--Preamble--> | ||
1100 | 56 | <div class="wrapper"> | ||
1101 | 57 | <div id="main-content" class="inner-wrapper" role="main"> | ||
1102 | 58 | <div class="row no-border"> | ||
1103 | 59 | <div class="header-navigation-secondary"></div> | ||
1104 | 60 | <h2 class="pagetitle">Juju documentation</h2> | ||
1105 | 61 | </div> | ||
1106 | 62 | <section id="content" class="container-12"> | ||
1107 | 63 | <div class="grid-12 doc-container"> | ||
1108 | 64 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
1109 | 65 | <div class="grid-9 doc-content"> | ||
1110 | 66 | <!--End-Preamble--> | ||
1111 | 67 | <article> | ||
1112 | 68 | <section id="charm-hooks"> | ||
1113 | 69 | <h1>Charm hooks</h1> | ||
1114 | 70 | |||
1115 | 71 | <p>A service unit's direct action is entirely defined by its charm's hooks. Hooks | ||
1116 | 72 | are executable files in a charm's <code>hooks</code> directory; hooks with particular | ||
1117 | 73 | names (see below) will be invoked by the juju unit agent at particular times, and thereby cause | ||
1118 | 74 | changes to the world.</p> | ||
1119 | 75 | |||
1120 | 76 | <p>Whenever a hook-worthy event takes place, the unit agent first checks whether | ||
1121 | 77 | that hook is being <a href="./authors-hook-debug.html">debugged</a>, and if so | ||
1122 | 78 | hands over control to the user. Otherwise, it tries to find a hook with precisely | ||
1123 | 79 | the right name. If the hook doesn't exist, the agent continues without complaint; | ||
1124 | 80 | if it does, it is invoked without arguments in a specific | ||
1125 | 81 | <a href="./authors-hook-environment.html">environment</a>, and its output is written | ||
1126 | 82 | to the unit agent's log. If it returns a non-zero exit code, the agent enters an | ||
1127 | 83 | <a href="./authors-hook-errors.html">error state</a> and awaits user intervention.</p> | ||
1128 | 84 | |||
1129 | 85 | <p>The agent will also enter an error state if the unit agent process is aborted | ||
1130 | 86 | during hook execution.</p> | ||
1131 | 87 | |||
1132 | 88 | <p>There are two types of hooks, described in more detail in the following sections.</p> | ||
1133 | 89 | |||
1134 | 90 | <p class = "note"><strong>Note: </strong>None of the unit or relation hooks are required; if you don't implement a hook, | ||
1135 | 91 | it just doesn't get run. When a hook event occurs, Juju will look for the corresponding hook file to execute, but if it finds none, will continue running without generating an error.</p> | ||
1136 | 92 | </section> | ||
1137 | 93 | |||
1138 | 94 | <section id="unit-hooks"> | ||
1139 | 95 | <h2>Unit hooks</h2> | ||
1140 | 96 | |||
1141 | 97 | <p>There are 5 "unit hooks" with predefined names that can be implemented | ||
1142 | 98 | by any charm:</p> | ||
1143 | 99 | <ul> | ||
1144 | 100 | <li>install</li> | ||
1145 | 101 | <li>config-changed</li> | ||
1146 | 102 | <li>start</li> | ||
1147 | 103 | <li>upgrade-charm</li> | ||
1148 | 104 | <li>stop</li> | ||
1149 | 105 | </ul> | ||
1150 | 106 | |||
1151 | 107 | <p>For every relation defined by a charm, an additional 4 "relation hooks" | ||
1152 | 108 | can be implemented, named after the charm relation:</p> | ||
1153 | 109 | <ul> | ||
1154 | 110 | <li><name>-relation-joined</li> | ||
1155 | 111 | <li><name>-relation-changed</li> | ||
1156 | 112 | <li><name>-relation-departed</li> | ||
1157 | 113 | <li><name>-relation-broken</li> | ||
1158 | 114 | </ul> | ||
1159 | 115 | |||
1160 | 116 | <h3 id="hook-install">install</h3> | ||
1161 | 117 | |||
1162 | 118 | <p><code>install</code> runs just once, before any other hook. It should be used to | ||
1163 | 119 | perform one-time setup operations only.</p> | ||
1164 | 120 | |||
1165 | 121 | <h3 id="hook-config-changed">config-changed</h3> | ||
1166 | 122 | |||
1167 | 123 | <p><code>config-changed</code> runs in several different situations.</p> | ||
1168 | 124 | <ul> | ||
1169 | 125 | <li>immediately after "install"</li> | ||
1170 | 126 | <li>immediately after "upgrade-charm"</li> | ||
1171 | 127 | <li>at least once when the unit agent is restarted (but, if the unit is in | ||
1172 | 128 | an <a href="./authors-hook-errors.html">error state</a>, it won't be run | ||
1173 | 129 | until after the error state is cleared).</li> | ||
1174 | 130 | </ul> | ||
1175 | 131 | <p>It cannot assume that the software has already been started; it should not | ||
1176 | 132 | start stopped software, but should (if appropriate) restart running software | ||
1177 | 133 | to take configuration changes into account.</p> | ||
1178 | 134 | |||
1179 | 135 | <h3 id="hook-start">start</h3> | ||
1180 | 136 | <p><code>start</code> runs immediately after the first <code>config-changed</code> | ||
1181 | 137 | hook. It should be used to ensure the charm's software is running. Note that the | ||
1182 | 138 | charm's software should be configured so as to persist through reboots without further | ||
1183 | 139 | intervention on juju's part. | ||
1184 | 140 | |||
1185 | 141 | <h3 id="hook-upgrade-charm">upgrade-charm</h3> | ||
1186 | 142 | |||
1187 | 143 | <p><code>upgrade-charm</code> runs immediately after any | ||
1188 | 144 | <a href="./authors-charm-upgrades.html">upgrade</a> operation that does <em>not</em> | ||
1189 | 145 | itself interrupt an existing <a href="./authors-hook-errors.html">error state.</a>. It | ||
1190 | 146 | should be used to reconcile local state written by some other version of the charm into | ||
1191 | 147 | whatever form it needs to take to be manipulated by the current version.</p> | ||
1192 | 148 | |||
1193 | 149 | <p>While the forced upgrade functionality is intended as a developer tool, and is | ||
1194 | 150 | not generally suitable for end users, it's somewhat optimistic to depend on the | ||
1195 | 151 | functionality never being abused. In light of this, if you need to run an | ||
1196 | 152 | <code>upgrade-charm</code> hook before your other hooks will work correctly, | ||
1197 | 153 | it may be wise to preface all your other hooks with a quick call to your | ||
1198 | 154 | (idempotent)<code>upgrade-charm</code>.</p> | ||
1199 | 155 | |||
1200 | 156 | <h3 id="hook-stop">stop</h3> | ||
1201 | 157 | |||
1202 | 158 | <p><code>stop</code> runs immediately before the end of the unit's destruction | ||
1203 | 159 | sequence. It should be used to ensure that the charm's software is not running, and | ||
1204 | 160 | will not start again on reboot.</p> | ||
1205 | 161 | </section> | ||
1206 | 162 | |||
1207 | 163 | <section id="relation-hooks"> | ||
1208 | 164 | <h2>Relation hooks</h2> | ||
1209 | 165 | |||
1210 | 166 | <p>Units will only participate in relations after they're been started, and before | ||
1211 | 167 | they've been stopped. Within that time window, the unit may participate in several | ||
1212 | 168 | different relations at a time, <em>including</em> multiple relations with the | ||
1213 | 169 | same name.</p> | ||
1214 | 170 | |||
1215 | 171 | <p>To illustrate, consider a database service that will be used by multiple client | ||
1216 | 172 | services. Units of a single client service will surely want to connect to, and | ||
1217 | 173 | use, the same database; but if units of another client service were to use that | ||
1218 | 174 | same database, the consequences could be catastrophic for all concerned.</p> | ||
1219 | 175 | |||
1220 | 176 | <p>If juju respected the <code>limit</code> field in relation | ||
1221 | 177 | <a href="./authors-charm-metadata.html">metadata</a>, it would be possible | ||
1222 | 178 | to work around this, but it's not a high-priority | ||
1223 | 179 | <a href="https://bugs.launchpad.net/bugs/1089297">bug</a>: most provider services | ||
1224 | 180 | <em>should</em> be able to handle multiple requirers anyway; and most requirers will | ||
1225 | 181 | only be connected to one provider anyway.</p> | ||
1226 | 182 | |||
1227 | 183 | <p>When a unit running a given charm participates in a given relation, it runs at | ||
1228 | 184 | least three hooks for every remote unit it becomes aware of in that relation.</p> | ||
1229 | 185 | </section> | ||
1230 | 186 | |||
1231 | 187 | <section id="hook-relation-joined"> | ||
1232 | 188 | <h3><name>-relation-joined</h3> | ||
1233 | 189 | |||
1234 | 190 | <p><code><name>-relation-joined</code> is run once only, when that remote | ||
1235 | 191 | unit is first observed by the unit. It should be used to <code>relation-set</code> any | ||
1236 | 192 | local unit settings that can be determined using no more than the name of the joining | ||
1237 | 193 | unit and the remote <code>private-address</code> setting, which is always available | ||
1238 | 194 | when the relation is created and is by convention not deleted.</p> | ||
1239 | 195 | |||
1240 | 196 | <p>You should not depend upon any other relation settings in the -joined hook | ||
1241 | 197 | because they're not guaranteed to be present; if you need more information | ||
1242 | 198 | you should wait for a -changed hook that presents the right information.</p> | ||
1243 | 199 | </section> | ||
1244 | 200 | |||
1245 | 201 | <section id="hook-relation-changed"> | ||
1246 | 202 | <h3><name>-relation-changed</h3> | ||
1247 | 203 | |||
1248 | 204 | <p><code><name>-relation-changed</code> is always run once, after -joined, and | ||
1249 | 205 | will subsequently be run whenever that remote unit changes its settings for the | ||
1250 | 206 | relation. It should be the <em>only</em> hook that <em>relies</em> upon remote relation | ||
1251 | 207 | settings from <code>relation-get</code>, and it should <em>not</em> error if the | ||
1252 | 208 | settings are incomplete: you can guarantee that when the remote unit changes its | ||
1253 | 209 | settings, the hook will be run again.</p> | ||
1254 | 210 | |||
1255 | 211 | <p>The settings that you can get, and that you should set, are determined by | ||
1256 | 212 | the relation's <a href="./authors-charm-interfaces.html">interface</a>.</p> | ||
1257 | 213 | </section> | ||
1258 | 214 | |||
1259 | 215 | <section id="hook-relation-departed"> | ||
1260 | 216 | <h3><name>-relation-departed</h3> | ||
1261 | 217 | |||
1262 | 218 | <p><code><name>-relation-departed</code> is run once only, when the remote unit | ||
1263 | 219 | is known to be leaving the relation; it will only run once at least one -changed has | ||
1264 | 220 | been run, and after -departed has run, no further -changeds will be run. This should | ||
1265 | 221 | be used to remove all references to the remote unit, because there's no guarantee that | ||
1266 | 222 | it's still part of the system; it's perfectly probable (although not guaranteed) that | ||
1267 | 223 | the system running that unit has already shut down.</p> | ||
1268 | 224 | |||
1269 | 225 | <p>When a unit's own participation in a relation is known to be ending, the unit | ||
1270 | 226 | agent continues to uphold the ordering guarantees above; but within those | ||
1271 | 227 | constraints, it will run the fewest possible hooks to notify the charm of the | ||
1272 | 228 | departure of each individual remote unit.</p> | ||
1273 | 229 | |||
1274 | 230 | <p>Once all necessary -departed hooks have been run for such a relation, the unit | ||
1275 | 231 | agent will run the final relation hook:</p> | ||
1276 | 232 | </section> | ||
1277 | 233 | |||
1278 | 234 | <section id="hook-relation-broken"> | ||
1279 | 235 | <h3><name>-relation-broken</h3> | ||
1280 | 236 | |||
1281 | 237 | <p><code><name>-relation-broken</code> indicates that the current relation is | ||
1282 | 238 | no longer valid, and that the charm's software must be configured as though the | ||
1283 | 239 | relation had never existed. It will only be called after every necessary -departed | ||
1284 | 240 | hook has been run; if it's being executed, you can be sure that no remote units are | ||
1285 | 241 | currently known locally.</p> | ||
1286 | 242 | |||
1287 | 243 | <p>It is important to note that the -broken hook might run even if no other units | ||
1288 | 244 | have ever joined the relation. This is not a bug: even if no remote units have ever | ||
1289 | 245 | joined, the fact of the unit's participation can be detected in other hooks via the | ||
1290 | 246 | <code>relation-ids</code> tool, and the -broken hook needs to execute to give the | ||
1291 | 247 | charm an opportunity to clean up any optimistically-generated configuration.</p> | ||
1292 | 248 | |||
1293 | 249 | <p>And, again, it's important to internalise the fact that there may be multiple | ||
1294 | 250 | runtime relations in play with the same name, and that they're independent: | ||
1295 | 251 | one -broken hook does not mean that <em>every</em> such relation is broken.</p> | ||
1296 | 252 | </section> | ||
1297 | 253 | |||
1298 | 254 | <section id="writing-hooks"> | ||
1299 | 255 | <h2>Writing hooks</h2> | ||
1300 | 256 | |||
1301 | 257 | <p>If you follow the <a href="./authors-charm-writing.html">tutorial</a>, you'll | ||
1302 | 258 | get a good sense of the basics. To fill out your knowledge, you'll want to study | ||
1303 | 259 | the hook <a href="./authors-hook-environment.html">environment and tools</a>, and | ||
1304 | 260 | to experiment with <a href="./authors-hook-debug.html">debug-hooks</a>.</p> | ||
1305 | 261 | |||
1306 | 262 | <p>Independent of the nuts and bolts, though, good hooks display a number of | ||
1307 | 263 | useful high-level properties:</p> | ||
1308 | 264 | <ul> | ||
1309 | 265 | <li>They are <em>idempotent</em>: that is to say that there should be no | ||
1310 | 266 | observable difference between running a hook once, and running it N times | ||
1311 | 267 | in a row. If this property does not hold, you are likely to be making your | ||
1312 | 268 | own life unnecesarily difficult: apart from anything else, the average user's | ||
1313 | 269 | most likely first response to a failed hook will be to try to run it again | ||
1314 | 270 | (if they don't just skip it).</li> | ||
1315 | 271 | |||
1316 | 272 | <li>They are <em>easy to read</em> and understand. It's tempting to write a | ||
1317 | 273 | single file that does everything, and which just calls different functions | ||
1318 | 274 | internally depending on the value of <code>argv[0]</code>, and to symlink that | ||
1319 | 275 | one file for every hook; but such structures quickly become unwieldy.<br /> | ||
1320 | 276 | The time taken to write a library, separate from the hooks, is very likely | ||
1321 | 277 | to be well spent: it lets you write single hooks that are clear and focused, | ||
1322 | 278 | and insulates the maintainer from irrelevant details.</li> | ||
1323 | 279 | |||
1324 | 280 | <li>Where possible, they reuse | ||
1325 | 281 | <a href="https://launchpad.net/charm-tools">common code</a> already written to | ||
1326 | 282 | ease or solve common use cases.</li> | ||
1327 | 283 | |||
1328 | 284 | <li>They do not return <a href="./authors-hook-errors.html">errors</a> unless | ||
1329 | 285 | there is a good reason to believe that they cannot be resolved without user | ||
1330 | 286 | intervention. Doing so is an admission of defeat: a user who sees your charm | ||
1331 | 287 | returning an error state is unlikely to have the specific expertise necessary | ||
1332 | 288 | to resolve it. If you have to return an error, please be sure to at least write | ||
1333 | 289 | any context you can to the log before you do so.</li> | ||
1334 | 290 | |||
1335 | 291 | <li>They write only <em>very</em> sparingly to the | ||
1336 | 292 | <a href="./authors-charm-contents.html">charm directory</a>.</li> | ||
1337 | 293 | </ul> | ||
1338 | 294 | |||
1339 | 295 | <p>We recommend you also familiarize yourself with the | ||
1340 | 296 | <a href="./authors-charm-best-practice.html">best practices</a> and, if you | ||
1341 | 297 | plan to distribute your charm, the | ||
1342 | 298 | <a href="./authors-charm-policy.html">charm store policy</a>.</p> | ||
1343 | 299 | </section> | ||
1344 | 300 | </article> | ||
1345 | 301 | <!--Postamble--> | ||
1346 | 302 | </div> | ||
1347 | 303 | </div> | ||
1348 | 304 | </section> | ||
1349 | 305 | </div> | ||
1350 | 306 | </div> | ||
1351 | 307 | <!--End-Postamble--> | ||
1352 | 308 | <!--Footer--> | ||
1353 | 309 | <footer class="global clearfix" role="contentinfo"> | ||
1354 | 310 | <nav role="navigation"> | ||
1355 | 311 | <div class="footer-a"> | ||
1356 | 312 | <div class="clearfix"> | ||
1357 | 313 | <ul> | ||
1358 | 314 | <li> | ||
1359 | 315 | <h2><a href="/">Juju</a></h2> | ||
1360 | 316 | <ul> | ||
1361 | 317 | <li><a href="/charms">Charms</a></li> | ||
1362 | 318 | <li><a href="/features">Features</a></li> | ||
1363 | 319 | <li><a href="/deployment">Deployment</a></li> | ||
1364 | 320 | </ul> | ||
1365 | 321 | </li> | ||
1366 | 322 | <li> | ||
1367 | 323 | <h2><a href="/resources">Resources</a></h2> | ||
1368 | 324 | <ul> | ||
1369 | 325 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
1370 | 326 | <li><a href="/docs/">Documentation</a></li> | ||
1371 | 327 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
1372 | 328 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
1373 | 329 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
1374 | 330 | <li><a href="/resources/videos/">Videos</a></li> | ||
1375 | 331 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
1376 | 332 | </ul> | ||
1377 | 333 | </li> | ||
1378 | 334 | <li> | ||
1379 | 335 | <h2><a href="/community">Community</a></h2> | ||
1380 | 336 | <ul> | ||
1381 | 337 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
1382 | 338 | <li><a href="/events/">Events</a></li> | ||
1383 | 339 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
1384 | 340 | <li><a href="/community/charmers/">Charmers</a></li> | ||
1385 | 341 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
1386 | 342 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
1387 | 343 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
1388 | 344 | </ul> | ||
1389 | 345 | </li> | ||
1390 | 346 | <li> | ||
1391 | 347 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
1392 | 348 | <ul> | ||
1393 | 349 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
1394 | 350 | <li><a href="/download/">Download Juju</a></li> | ||
1395 | 351 | </ul> | ||
1396 | 352 | </li> | ||
1397 | 353 | </ul> | ||
1398 | 354 | </div> | ||
1399 | 355 | </div> | ||
1400 | 356 | </nav> | ||
1401 | 357 | <div class="legal clearfix"> | ||
1402 | 358 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
1403 | 359 | </div> | ||
1404 | 360 | </footer> | ||
1405 | 361 | |||
1406 | 362 | <!--End-Footer--> | ||
1407 | 363 | <!--Scripts--> | ||
1408 | 364 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
1409 | 365 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
1410 | 366 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
1411 | 367 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
1412 | 368 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
1413 | 369 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
1414 | 370 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
1415 | 371 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
1416 | 372 | <!-- google analytics --> | ||
1417 | 373 | <script> | ||
1418 | 374 | var _gaq = _gaq || []; | ||
1419 | 375 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
1420 | 376 | _gaq.push(['_trackPageview']); | ||
1421 | 377 | |||
1422 | 378 | (function() { | ||
1423 | 379 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
1424 | 380 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
1425 | 381 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
1426 | 382 | })(); | ||
1427 | 383 | </script> | ||
1428 | 384 | <!--End-Scripts--> | ||
1429 | 385 | |||
1430 | 386 | |||
1431 | 387 | </body></html> | ||
1432 | 0 | 388 | ||
1433 | === modified file 'htmldocs/authors-charm-icon.html' | |||
1434 | --- htmldocs/authors-charm-icon.html 2013-09-27 14:53:30 +0000 | |||
1435 | +++ htmldocs/authors-charm-icon.html 2013-10-09 20:07:46 +0000 | |||
1436 | @@ -23,6 +23,8 @@ | |||
1437 | 23 | 23 | ||
1438 | 24 | 24 | ||
1439 | 25 | 25 | ||
1440 | 26 | |||
1441 | 27 | |||
1442 | 26 | <body class="resources"> | 28 | <body class="resources"> |
1443 | 27 | 29 | ||
1444 | 28 | <!--Header--> | 30 | <!--Header--> |
1445 | @@ -242,4 +244,6 @@ | |||
1446 | 242 | <!--End-Scripts--> | 244 | <!--End-Scripts--> |
1447 | 243 | 245 | ||
1448 | 244 | 246 | ||
1449 | 247 | |||
1450 | 248 | |||
1451 | 245 | </body></html> | 249 | </body></html> |
1452 | 246 | 250 | ||
1453 | === added file 'htmldocs/authors-charm-interfaces.html' | |||
1454 | --- htmldocs/authors-charm-interfaces.html 1970-01-01 00:00:00 +0000 | |||
1455 | +++ htmldocs/authors-charm-interfaces.html 2013-10-09 20:07:46 +0000 | |||
1456 | @@ -0,0 +1,340 @@ | |||
1457 | 1 | <!DOCTYPE html> | ||
1458 | 2 | <html> | ||
1459 | 3 | <!--Head--> | ||
1460 | 4 | <head> | ||
1461 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
1462 | 6 | <title>Juju Documentation</title> | ||
1463 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
1464 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
1465 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
1466 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
1467 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
1468 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
1469 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
1470 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
1471 | 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"> | ||
1472 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
1473 | 17 | |||
1474 | 18 | <!--[if lt IE 9]> | ||
1475 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
1476 | 20 | <![endif]--> | ||
1477 | 21 | </head> | ||
1478 | 22 | <!--End-Head--> | ||
1479 | 23 | |||
1480 | 24 | <body class="resources"> | ||
1481 | 25 | <!--Header--> | ||
1482 | 26 | |||
1483 | 27 | <header class="banner global" role="banner"> | ||
1484 | 28 | <nav role="navigation" class="nav-primary nav-right"> | ||
1485 | 29 | <div class="logo"> | ||
1486 | 30 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
1487 | 31 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
1488 | 32 | <span>Juju</span> | ||
1489 | 33 | </a> | ||
1490 | 34 | </div> | ||
1491 | 35 | <ul> | ||
1492 | 36 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
1493 | 37 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
1494 | 38 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
1495 | 39 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
1496 | 40 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
1497 | 41 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
1498 | 42 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
1499 | 43 | </ul> | ||
1500 | 44 | <div id="box-search"> | ||
1501 | 45 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
1502 | 46 | <label class="off-left" for="s">Search:</label> | ||
1503 | 47 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
1504 | 48 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
1505 | 49 | </form> | ||
1506 | 50 | </div> | ||
1507 | 51 | </nav> | ||
1508 | 52 | </header> | ||
1509 | 53 | <!--End-Header--> | ||
1510 | 54 | <!--Preamble--> | ||
1511 | 55 | <div class="wrapper"> | ||
1512 | 56 | <div id="main-content" class="inner-wrapper" role="main"> | ||
1513 | 57 | <div class="row no-border"> | ||
1514 | 58 | <div class="header-navigation-secondary"></div> | ||
1515 | 59 | <h2 class="pagetitle">Juju documentation</h2> | ||
1516 | 60 | </div> | ||
1517 | 61 | <section id="content" class="container-12"> | ||
1518 | 62 | <div class="grid-12 doc-container"> | ||
1519 | 63 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
1520 | 64 | <div class="grid-9 doc-content"> | ||
1521 | 65 | <!--End-Preamble--> | ||
1522 | 66 | <article> | ||
1523 | 67 | <section id="relation-interfaces"> | ||
1524 | 68 | <h1>Charm relation interfaces</h1> | ||
1525 | 69 | |||
1526 | 70 | <p>As described <a href="./authors-charm-metadata.html">elsewhere</a>, picking an | ||
1527 | 71 | interface is a strong statement; whether you're providing or requiring a given | ||
1528 | 72 | interface, you need to be compatible with all providers and requirers of that | ||
1529 | 73 | interface.</p> | ||
1530 | 74 | |||
1531 | 75 | <p>In short, this means that you need to set the same settings as do all the | ||
1532 | 76 | other charms with the same role for the interface; and you should only expect | ||
1533 | 77 | to be able to read those settings set by the other charms with the counterpart | ||
1534 | 78 | role.</p> | ||
1535 | 79 | </section> | ||
1536 | 80 | |||
1537 | 81 | <section id="determining-interfaces"> | ||
1538 | 82 | <h2>Determining charm relation interfaces</h2> | ||
1539 | 83 | |||
1540 | 84 | <p>This is in some respects an uncomfortable situation to be in. If two charms | ||
1541 | 85 | declare compatibility, but fail when run together due to disagreement about | ||
1542 | 86 | the actual definition of that interface; it's not immediately clear which is | ||
1543 | 87 | at fault, because the "standard" is defined only by consensus among the | ||
1544 | 88 | existing charms that provide or require that interface.</p> | ||
1545 | 89 | |||
1546 | 90 | <p>On the upside, this means that reading any charm that already implements the | ||
1547 | 91 | interface is <em>theoretically</em> good enough to figure it out; in practice, it's | ||
1548 | 92 | sometimes hard to understand the code in isolation. The incontrovertible way | ||
1549 | 93 | to determine the protocol defined by an interface is to deploy a pair of charms | ||
1550 | 94 | that already use that interface, and <a href="./authors-hook-debug.html">intercept</a> | ||
1551 | 95 | the communications between them.</p> | ||
1552 | 96 | |||
1553 | 97 | <pre class="prettyprint"> | ||
1554 | 98 | juju deploy mongodb | ||
1555 | 99 | juju deploy node-app | ||
1556 | 100 | </pre> | ||
1557 | 101 | |||
1558 | 102 | <p>In a separate window, once node-app/0 reports <code>started</code> status:</p> | ||
1559 | 103 | |||
1560 | 104 | <pre class="prettyprint"> | ||
1561 | 105 | juju debug-hooks node-app/0 * | ||
1562 | 106 | </pre> | ||
1563 | 107 | |||
1564 | 108 | <p>This opens a tmux session; when the unit wants to run a hook, it'll create a | ||
1565 | 109 | new window in which you can interactively inspect the environment. In a relation | ||
1566 | 110 | hook, you'll want to run the following commands:</p> | ||
1567 | 111 | |||
1568 | 112 | <pre class="prettyprint"> | ||
1569 | 113 | # discover what's been set by the unit on the other end of the relation: | ||
1570 | 114 | $ relation-get $JUJU_REMOTE_UNIT | ||
1571 | 115 | |||
1572 | 116 | address: example.com:37070 | ||
1573 | 117 | username: bob | ||
1574 | 118 | password: seekrit | ||
1575 | 119 | |||
1576 | 120 | # get the local unit's relation settings, for comparison afterwards: | ||
1577 | 121 | $ relation-get $JUJU_UNIT_NAME | ||
1578 | 122 | # (no results) | ||
1579 | 123 | |||
1580 | 124 | # run the actual hook: | ||
1581 | 125 | $ ./hooks/$JUJU_HOOK_NAME | ||
1582 | 126 | |||
1583 | 127 | # get the local settings again, to see if any changes were made by the hook: | ||
1584 | 128 | $ relation-get $JUJU_UNIT_NAME | ||
1585 | 129 | # (no results) | ||
1586 | 130 | </pre> | ||
1587 | 131 | |||
1588 | 132 | <p>...and then close that tmux window and wait to see if another one opens for the | ||
1589 | 133 | next hook. Assuming you started debugging before creating the relation, you'll | ||
1590 | 134 | see exactly one -joined hook, and at least one -changed hook, and you're only | ||
1591 | 135 | done when new -changed hooks stop popping up.</p> | ||
1592 | 136 | |||
1593 | 137 | <p>The relation-get <a href="./authors-hook-environment.html">tool</a> accepts a | ||
1594 | 138 | <code>--format</code> parameter that accepts <code>json</code> and <code>yaml</code> | ||
1595 | 139 | values, in case you want to consume them programmatically.</p> | ||
1596 | 140 | |||
1597 | 141 | <p>In practice, what you'll most likely find is that one side sets a couple of keys, | ||
1598 | 142 | the other side gets them, and that's that... in no more than two changed hooks. | ||
1599 | 143 | Be aware, though, that it is possible in principle for an interface to imply | ||
1600 | 144 | a more demanding interface, involving multiple rounds of setting and getting.</p> | ||
1601 | 145 | </section> | ||
1602 | 146 | |||
1603 | 147 | <section id="documenting-interfaces"> | ||
1604 | 148 | <h2>Documenting charm relation interfaces</h2> | ||
1605 | 149 | |||
1606 | 150 | <p>In light of the above, there is a clear need for some means of documenting the | ||
1607 | 151 | above. The optional <code>gets</code> and <code>sets</code> fields in a charm's | ||
1608 | 152 | relation <a href="./authors-charm-metadata.html">metadata</a> should be used for | ||
1609 | 153 | this purpose.</p> | ||
1610 | 154 | |||
1611 | 155 | <p>Please be especially careful to note that this format is <em>not</em> checked | ||
1612 | 156 | by juju today. But it does encode the information that's most helpful to your fellow | ||
1613 | 157 | charmers, and by doing so in a consistent and machine-readable format we maximise | ||
1614 | 158 | our chances of one day making use of this information automatically.</p> | ||
1615 | 159 | |||
1616 | 160 | <p>The simple form, which will be the most common form, looks like this:</p> | ||
1617 | 161 | |||
1618 | 162 | <pre class="prettyprint"> | ||
1619 | 163 | name: python-django | ||
1620 | 164 | ... | ||
1621 | 165 | provides: | ||
1622 | 166 | website: | ||
1623 | 167 | interface: http | ||
1624 | 168 | sets: [host, post] | ||
1625 | 169 | </pre> | ||
1626 | 170 | |||
1627 | 171 | <p>...and this:</p> | ||
1628 | 172 | |||
1629 | 173 | <pre class="prettyprint"> | ||
1630 | 174 | name: haproxy | ||
1631 | 175 | ... | ||
1632 | 176 | requires: | ||
1633 | 177 | reverseproxy: | ||
1634 | 178 | interface: http | ||
1635 | 179 | gets: [host, port] | ||
1636 | 180 | </pre> | ||
1637 | 181 | |||
1638 | 182 | <p>...indicating that a relation can surely be made between python-django and haproxy, | ||
1639 | 183 | because the <code>website</code> relation unconditionally sets the keys that the | ||
1640 | 184 | <code>reverseproxy</code> relation requires in order to function.</p> | ||
1641 | 185 | |||
1642 | 186 | <p>The more complex form, which is only required for complex protocols, is defined | ||
1643 | 187 | as follows:</p> | ||
1644 | 188 | <ul> | ||
1645 | 189 | <li><code>gets</code> holds a list of settings keys that must all be set by | ||
1646 | 190 | each unit on the remote end of a relation in order for the local unit to | ||
1647 | 191 | function.</li> | ||
1648 | 192 | <li><code>sets</code> holds a list of settings that will be set by each unit | ||
1649 | 193 | of the local charm. These settings can either be a plain string, indicating that | ||
1650 | 194 | no remote settings need exist for this key to be written; or a single-element | ||
1651 | 195 | map, with the setting to be written mapped to the remote settings that must | ||
1652 | 196 | exist for this to be done.</li> | ||
1653 | 197 | </ul> | ||
1654 | 198 | <p>For example, consider charms <code>a</code> and <code>b</code>, which do the | ||
1655 | 199 | following handshake dance before they can complete their configuration:</p> | ||
1656 | 200 | <ul> | ||
1657 | 201 | <li><code>b/0</code> starts running -joined, which takes a while.</li> | ||
1658 | 202 | <li><code>a/0</code> runs -joined and -changed before <code>b/0</code> has | ||
1659 | 203 | finished -joined. In the -changed hook, it fails to find the remote settings | ||
1660 | 204 | it expected, and exits without error.</li> | ||
1661 | 205 | <li><code>b/0</code> finishes -joined, setting <code>X</code> and <code>Y</code>, | ||
1662 | 206 | thus triggering -changed on <code>a/0</code>.</li> | ||
1663 | 207 | <li><code>a/0</code> sets <code>P</code> and <code>Q</code> in response, causing | ||
1664 | 208 | a -changed on <code>b/0</code>.</li> | ||
1665 | 209 | <li><code>b/0</code> completes local configuration using <code>P</code> and | ||
1666 | 210 | <code>Q</code>, and sets <code>Z</code>, triggering a final -changed on | ||
1667 | 211 | <code>a/0</code>.</li> | ||
1668 | 212 | <li><code>a/0</code> completes local configuration using <code>X</code>, | ||
1669 | 213 | <code>Y</code>, and <code>Z</code>, and sets nothing.</li> | ||
1670 | 214 | </ul> | ||
1671 | 215 | <p>For example, in the hypothetical complex protocol described in the previous | ||
1672 | 216 | section, the metadata for charm <code>a</code> above would contain:</p> | ||
1673 | 217 | |||
1674 | 218 | <pre class="prettyprint"> | ||
1675 | 219 | requires: | ||
1676 | 220 | ab: | ||
1677 | 221 | interface: ab | ||
1678 | 222 | sets: | ||
1679 | 223 | - P: [X, Y] | ||
1680 | 224 | - Q: [X, Y] | ||
1681 | 225 | gets: [X, Y, Z] | ||
1682 | 226 | </pre> | ||
1683 | 227 | |||
1684 | 228 | <p>...indicating that <code>P</code> and <code>Q</code> will only be written when | ||
1685 | 229 | <code>X</code> and <code>Y</code> have; and that configuration will not complete | ||
1686 | 230 | without <code>X</code>, <code>Y</code> and <code>Z</code>. Meanwhile charm | ||
1687 | 231 | <code>b</code> would contain:</p> | ||
1688 | 232 | |||
1689 | 233 | <pre class="prettyprint"> | ||
1690 | 234 | provides: | ||
1691 | 235 | ab: | ||
1692 | 236 | interface: ab | ||
1693 | 237 | sets: | ||
1694 | 238 | - X | ||
1695 | 239 | - Y | ||
1696 | 240 | - Z: [P, Q] | ||
1697 | 241 | gets: [P, Q] | ||
1698 | 242 | </pre> | ||
1699 | 243 | |||
1700 | 244 | <p>...indicating that it will always write <code>X</code> and <code>Y</code>, and | ||
1701 | 245 | that <code>Z</code> will be written when <code>P</code> and <code>Q</code> have; and | ||
1702 | 246 | that configuration will not be complete without <code>P</code> and <code>Q</code>.</p> | ||
1703 | 247 | |||
1704 | 248 | <p>Peer relations are a different matter, in that peer relations are the mechanism | ||
1705 | 249 | by which service units share information internally. It's not unusual for peer | ||
1706 | 250 | service units to maintain convenient caches of distributed information in their | ||
1707 | 251 | own peer settings, and this inevitably involves generating settings keys at | ||
1708 | 252 | runtime.</p> | ||
1709 | 253 | </section> | ||
1710 | 254 | </article> | ||
1711 | 255 | <!--Postamble--> | ||
1712 | 256 | </div> | ||
1713 | 257 | </div> | ||
1714 | 258 | </section> | ||
1715 | 259 | </div> | ||
1716 | 260 | </div> | ||
1717 | 261 | <!--End-Postamble--> | ||
1718 | 262 | <!--Footer--> | ||
1719 | 263 | <footer class="global clearfix" role="contentinfo"> | ||
1720 | 264 | <nav role="navigation"> | ||
1721 | 265 | <div class="footer-a"> | ||
1722 | 266 | <div class="clearfix"> | ||
1723 | 267 | <ul> | ||
1724 | 268 | <li> | ||
1725 | 269 | <h2><a href="/">Juju</a></h2> | ||
1726 | 270 | <ul> | ||
1727 | 271 | <li><a href="/charms">Charms</a></li> | ||
1728 | 272 | <li><a href="/features">Features</a></li> | ||
1729 | 273 | <li><a href="/deployment">Deployment</a></li> | ||
1730 | 274 | </ul> | ||
1731 | 275 | </li> | ||
1732 | 276 | <li> | ||
1733 | 277 | <h2><a href="/resources">Resources</a></h2> | ||
1734 | 278 | <ul> | ||
1735 | 279 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
1736 | 280 | <li><a href="/docs/">Documentation</a></li> | ||
1737 | 281 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
1738 | 282 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
1739 | 283 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
1740 | 284 | <li><a href="/resources/videos/">Videos</a></li> | ||
1741 | 285 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
1742 | 286 | </ul> | ||
1743 | 287 | </li> | ||
1744 | 288 | <li> | ||
1745 | 289 | <h2><a href="/community">Community</a></h2> | ||
1746 | 290 | <ul> | ||
1747 | 291 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
1748 | 292 | <li><a href="/events/">Events</a></li> | ||
1749 | 293 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
1750 | 294 | <li><a href="/community/charmers/">Charmers</a></li> | ||
1751 | 295 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
1752 | 296 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
1753 | 297 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
1754 | 298 | </ul> | ||
1755 | 299 | </li> | ||
1756 | 300 | <li> | ||
1757 | 301 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
1758 | 302 | <ul> | ||
1759 | 303 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
1760 | 304 | <li><a href="/download/">Download Juju</a></li> | ||
1761 | 305 | </ul> | ||
1762 | 306 | </li> | ||
1763 | 307 | </ul> | ||
1764 | 308 | </div> | ||
1765 | 309 | </div> | ||
1766 | 310 | </nav> | ||
1767 | 311 | <div class="legal clearfix"> | ||
1768 | 312 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
1769 | 313 | </div> | ||
1770 | 314 | </footer> | ||
1771 | 315 | |||
1772 | 316 | <!--End-Footer--> | ||
1773 | 317 | <!--Scripts--> | ||
1774 | 318 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
1775 | 319 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
1776 | 320 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
1777 | 321 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
1778 | 322 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
1779 | 323 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
1780 | 324 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
1781 | 325 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
1782 | 326 | <!-- google analytics --> | ||
1783 | 327 | <script> | ||
1784 | 328 | var _gaq = _gaq || []; | ||
1785 | 329 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
1786 | 330 | _gaq.push(['_trackPageview']); | ||
1787 | 331 | |||
1788 | 332 | (function() { | ||
1789 | 333 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
1790 | 334 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
1791 | 335 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
1792 | 336 | })(); | ||
1793 | 337 | </script> | ||
1794 | 338 | <!--End-Scripts--> | ||
1795 | 339 | |||
1796 | 340 | </body></html> | ||
1797 | 0 | 341 | ||
1798 | === added file 'htmldocs/authors-charm-metadata.html' | |||
1799 | --- htmldocs/authors-charm-metadata.html 1970-01-01 00:00:00 +0000 | |||
1800 | +++ htmldocs/authors-charm-metadata.html 2013-10-09 20:07:46 +0000 | |||
1801 | @@ -0,0 +1,376 @@ | |||
1802 | 1 | <!DOCTYPE html> | ||
1803 | 2 | <html> | ||
1804 | 3 | <!--Head--> | ||
1805 | 4 | <head> | ||
1806 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
1807 | 6 | <title>Juju Documentation</title> | ||
1808 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
1809 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
1810 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
1811 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
1812 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
1813 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
1814 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
1815 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
1816 | 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"> | ||
1817 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
1818 | 17 | |||
1819 | 18 | <!--[if lt IE 9]> | ||
1820 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
1821 | 20 | <![endif]--> | ||
1822 | 21 | </head> | ||
1823 | 22 | <!--End-Head--> | ||
1824 | 23 | |||
1825 | 24 | |||
1826 | 25 | <body class="resources"> | ||
1827 | 26 | <!--Header--> | ||
1828 | 27 | |||
1829 | 28 | <header class="banner global" role="banner"> | ||
1830 | 29 | <nav role="navigation" class="nav-primary nav-right"> | ||
1831 | 30 | <div class="logo"> | ||
1832 | 31 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
1833 | 32 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
1834 | 33 | <span>Juju</span> | ||
1835 | 34 | </a> | ||
1836 | 35 | </div> | ||
1837 | 36 | <ul> | ||
1838 | 37 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
1839 | 38 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
1840 | 39 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
1841 | 40 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
1842 | 41 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
1843 | 42 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
1844 | 43 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
1845 | 44 | </ul> | ||
1846 | 45 | <div id="box-search"> | ||
1847 | 46 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
1848 | 47 | <label class="off-left" for="s">Search:</label> | ||
1849 | 48 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
1850 | 49 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
1851 | 50 | </form> | ||
1852 | 51 | </div> | ||
1853 | 52 | </nav> | ||
1854 | 53 | </header> | ||
1855 | 54 | <!--End-Header--> | ||
1856 | 55 | <!--Preamble--> | ||
1857 | 56 | <div class="wrapper"> | ||
1858 | 57 | <div id="main-content" class="inner-wrapper" role="main"> | ||
1859 | 58 | <div class="row no-border"> | ||
1860 | 59 | <div class="header-navigation-secondary"></div> | ||
1861 | 60 | <h2 class="pagetitle">Juju documentation</h2> | ||
1862 | 61 | </div> | ||
1863 | 62 | <section id="content" class="container-12"> | ||
1864 | 63 | <div class="grid-12 doc-container"> | ||
1865 | 64 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
1866 | 65 | <div class="grid-9 doc-content"> | ||
1867 | 66 | <!--End-Preamble--> | ||
1868 | 67 | <article> | ||
1869 | 68 | |||
1870 | 69 | <section id="charm-metadata"> | ||
1871 | 70 | <h1>Charm metadata</h1> | ||
1872 | 71 | |||
1873 | 72 | <p>The only file that must be present in a charm is <code>metadata.yaml</code>, in | ||
1874 | 73 | the root directory. A metadata file must be a valid yaml dictionary, containing at | ||
1875 | 74 | least the following fields:</p> | ||
1876 | 75 | <ul> | ||
1877 | 76 | <li><code>name</code> is the charm name, which is used to form the charm URL. | ||
1878 | 77 | It must contain only <code>a-z</code>, <code>0-9</code>, and <code>-</code>; | ||
1879 | 78 | must start with <code>a-z</code>; must not end with a <code>-</code>; and may | ||
1880 | 79 | only end with digits if the digits are <em>not</em> directly preceded by a | ||
1881 | 80 | space. Stick with names like <code>foo</code> and <code>foo-bar-baz</code> | ||
1882 | 81 | and you needn't pay further attention to the restrictions.</li> | ||
1883 | 82 | <li><code>summary</code> is a one-line description of the charm.</li> | ||
1884 | 83 | <li><code>description</code> is a long-form description of the charm and its | ||
1885 | 84 | features. It will also appear in the juju GUI.</li> | ||
1886 | 85 | </ul> | ||
1887 | 86 | |||
1888 | 87 | <p>Here's a valid metadata file:</p> | ||
1889 | 88 | <pre class="prettyprint lang-yaml"> | ||
1890 | 89 | name: minecraft | ||
1891 | 90 | summary: Minecraft Server | ||
1892 | 91 | description: | | ||
1893 | 92 | Will deploy OpenJDK 6 JRE and the latest Minecraft server | ||
1894 | 93 | </pre> | ||
1895 | 94 | |||
1896 | 95 | <p>With only those fields, a metadata file is valid, but not very useful. Charms | ||
1897 | 96 | for use in the Charm Store should always set the following fields as well, | ||
1898 | 97 | for categorization and display in the GUI:</p> | ||
1899 | 98 | <ul> | ||
1900 | 99 | <li><code>maintainer</code> is the name and email address for the main point | ||
1901 | 100 | of contact for the development and maintenance of the charm. Or, at least, it | ||
1902 | 101 | should be: in frequent practice, it's just a name. Please update your charms | ||
1903 | 102 | as you get the opportunity.</li> | ||
1904 | 103 | <li><code>categories</code> is a list containing one or more of the following: | ||
1905 | 104 | <ul> | ||
1906 | 105 | <li>applications</li> | ||
1907 | 106 | <li>app-servers</li> | ||
1908 | 107 | <li>cache-proxy</li> | ||
1909 | 108 | <li>databases</li> | ||
1910 | 109 | <li>file-servers</li> | ||
1911 | 110 | <li>mis</li> | ||
1912 | 111 | </ul> | ||
1913 | 112 | <p>In almost all cases, only one category will be appropriate. The categories help keep the Charm Store organised.</p></li> | ||
1914 | 113 | </ul> | ||
1915 | 114 | |||
1916 | 115 | <p>Finally, a metadata file defines the charm's relations, and whether it's | ||
1917 | 116 | designed for deployment as a <a href="./authors-subordinate-services.html">subordinate service</a>.</p> | ||
1918 | 117 | <ul> | ||
1919 | 118 | <li><code>subordinate</code> should be set to true if the charm is a | ||
1920 | 119 | subordinate. If omitted, the charm will be presumed not to be subordinate.</li> | ||
1921 | 120 | <li><code>provides</code>, <code>requires</code>, and <code>peers</code> define | ||
1922 | 121 | the various relations the charm will participate in.</li> | ||
1923 | 122 | <li>if the charm is subordinate, it must contain at least one <code>requires</code> | ||
1924 | 123 | relation with container scope.</li> | ||
1925 | 124 | </ul> | ||
1926 | 125 | |||
1927 | 126 | <p>Other field names should be considered to be reserved; please don't use any | ||
1928 | 127 | not listed above to avoid issues with future versions of Juju.</p> | ||
1929 | 128 | </section> | ||
1930 | 129 | |||
1931 | 130 | <section id="simple-relations"> | ||
1932 | 131 | <h2>Simple relations</h2> | ||
1933 | 132 | |||
1934 | 133 | <p>The <code>provides</code> and <code>requires</code> keys are used to define | ||
1935 | 134 | pairings of charms that are likely to be fruitful. Consider a simple mongodb | ||
1936 | 135 | charm's metadata:</p> | ||
1937 | 136 | |||
1938 | 137 | <pre class="prettyprint lang-yaml"> | ||
1939 | 138 | name: my-mongodb | ||
1940 | 139 | ... | ||
1941 | 140 | provides: | ||
1942 | 141 | server: mongodb | ||
1943 | 142 | </pre> | ||
1944 | 143 | |||
1945 | 144 | <p>...and that of a simple node.js application charm:</p> | ||
1946 | 145 | |||
1947 | 146 | <pre class="prettyprint lang-yaml"> | ||
1948 | 147 | name: my-node-app | ||
1949 | 148 | ... | ||
1950 | 149 | requires: | ||
1951 | 150 | database: mongodb | ||
1952 | 151 | provides: | ||
1953 | 152 | website: http | ||
1954 | 153 | </pre> | ||
1955 | 154 | |||
1956 | 155 | <p>Put together, these files indicate that a relation can be made between services | ||
1957 | 156 | running the respective charms. The my-mongodb charm <code>provides</code> a relation named | ||
1958 | 157 | <code>server</code> with the <code>mongodb</code> interface, and the my-node-app charm | ||
1959 | 158 | <code>requires</code> a relation named <code>database</code> with the <code>mongodb</code> | ||
1960 | 159 | interface.</p> | ||
1961 | 160 | |||
1962 | 161 | <p>The my-node-app charm also <code>provides</code> a relation named <code>website</code> | ||
1963 | 162 | with the <code>http</code> interface, but that's irrelevant to the mongodb charm. (But an | ||
1964 | 163 | haproxy charm might well define, say, <code>reverseproxy</code>, that <code>requires</code> | ||
1965 | 164 | the <code>http</code> interface provided by my-node-app.)</p> | ||
1966 | 165 | </section> | ||
1967 | 166 | |||
1968 | 167 | <section id="relation-interfaces"> | ||
1969 | 168 | <h2>Relation interfaces</h2> | ||
1970 | 169 | |||
1971 | 170 | <p>An interface is a string that must only contain <code>a-z</code> and <code>-</code>, | ||
1972 | 171 | and neither start nor end with <code>-</code>. It's the single determiner of | ||
1973 | 172 | compatibility between charms; and it carries with it nothing more than a mutual | ||
1974 | 173 | promise that the provider and requirer somehow know the communication protocol | ||
1975 | 174 | implied by the name.</p> | ||
1976 | 175 | |||
1977 | 176 | <p>So, the relation namespace is essentially unrestricted (with one enforced | ||
1978 | 177 | exception: you may not <em>provide</em> a relation named <code>juju</code>, or | ||
1979 | 178 | starting with <code>juju-</code>). This allows for rapid development in some | ||
1980 | 179 | situations; but, in the example above, there is a potential problem: we've picked | ||
1981 | 180 | <em>two</em> interface names that already have meanings in the charm ecosystem, | ||
1982 | 181 | and that means we have to be <a href="./authors-charm-interfaces.html">compatible</a>; | ||
1983 | 182 | but that's a concern for a bit later, when we're actually writing the relation hooks.</p> | ||
1984 | 183 | </section> | ||
1985 | 184 | |||
1986 | 185 | <section id="peer-relations"> | ||
1987 | 186 | <h2>Peer relations</h2> | ||
1988 | 187 | |||
1989 | 188 | <p>Alongside <code>provides</code> and <code>requires</code>, charms can declare | ||
1990 | 189 | relations under <code>peers</code>. Where <code>provides</code> relations integrate | ||
1991 | 190 | with <code>requires</code> ones, such that providers respond to requirers and vice | ||
1992 | 191 | versa, the <code>peers</code> relation causes each unit of a single service to | ||
1993 | 192 | respond to the other units in the same service. A peer relation is otherwise defined | ||
1994 | 193 | in exactly the same way as any other relation.</p> | ||
1995 | 194 | </section> | ||
1996 | 195 | |||
1997 | 196 | <section id="relation-config"> | ||
1998 | 197 | <h2>Configuring relations</h2> | ||
1999 | 198 | |||
2000 | 199 | <p>There's an alternative syntax for specifying relations, which allows you to | ||
2001 | 200 | set additional fields by replacing the interface name with a dictionary. In this case, the <code>interface</code> key must be specified explicitly, and a number of other possibilities become available:</p> | ||
2002 | 201 | <ul> | ||
2003 | 202 | <li><code>scope</code> defaults to <code>global</code>, but may be set to | ||
2004 | 203 | <code>container</code>. The scope controls the set of remote units that are | ||
2005 | 204 | reported to the unit as members of the relation: container-scoped relations | ||
2006 | 205 | are restricted to reporting details of a single principal unit to a single | ||
2007 | 206 | subordinate, and vice versa, while global relations consider all possible | ||
2008 | 207 | remote units.<br /> | ||
2009 | 208 | <a href="authors-charm-subordinates.html">Subordinate</a> charms are only | ||
2010 | 209 | valid if they have at least one <code>requires</code> relation with | ||
2011 | 210 | <code>container</code> scope.</li> | ||
2012 | 211 | <li><code>limit</code> is ignored by juju, but if present should be a positive | ||
2013 | 212 | integer N indicating that the charm is not designed to use this interface in more | ||
2014 | 213 | than N relations at once.<br /> | ||
2015 | 214 | For example, if you're writing a really simple exploratory charm for your | ||
2016 | 215 | particular data store, you could just create a single shared store and | ||
2017 | 216 | write the same access credentials for every relation. A limit of 1 is | ||
2018 | 217 | thus useful in that it does <em>document</em> the restriction, even though | ||
2019 | 218 | it's not automatically enforced today.</li> | ||
2020 | 219 | <li><code>optional</code> is ignored by juju, but if present should only be | ||
2021 | 220 | set to true, on <code>requires</code> relations, to indicate that the charm | ||
2022 | 221 | can still function effectively without having those relations added.<br /> | ||
2023 | 222 | For example, the my-node-app charm might also define:<br /> | ||
2024 | 223 | <pre class="prettyprint lang-yaml"> | ||
2025 | 224 | requires: | ||
2026 | 225 | database: mongodb | ||
2027 | 226 | memcache: | ||
2028 | 227 | interface: memcached | ||
2029 | 228 | optional: true | ||
2030 | 229 | </code></pre><br /> | ||
2031 | 230 | ...to indicate that it can integrate with memcached if it's available, but | ||
2032 | 231 | that it can't be expected to do anything useful without a mongodb service | ||
2033 | 232 | available.</li> | ||
2034 | 233 | <li><code>gets</code> and <code>sets</code> are ignored by juju at present, | ||
2035 | 234 | but are valuable <a href="./authors-charm-interfaces.html">documentation</a>.</li> | ||
2036 | 235 | </ul> | ||
2037 | 236 | |||
2038 | 237 | </section> | ||
2039 | 238 | |||
2040 | 239 | <section id="examples"> | ||
2041 | 240 | <h2>Sample metadata.yaml files</h2> | ||
2042 | 241 | <p> The MySQL charm metadata: </p> | ||
2043 | 242 | <pre class="prettyprint"> | ||
2044 | 243 | name: mysql | ||
2045 | 244 | summary: MySQL is a fast, stable and true multi-user, multi-threaded SQL database | ||
2046 | 245 | maintainer: Marco Ceppi | ||
2047 | 246 | description: | | ||
2048 | 247 | MySQL is a fast, stable and true multi-user, multi-threaded SQL database | ||
2049 | 248 | server. SQL (Structured Query Language) is the most popular database query | ||
2050 | 249 | language in the world. The main goals of MySQL are speed, robustness and | ||
2051 | 250 | ease of use. | ||
2052 | 251 | categories: | ||
2053 | 252 | - databases | ||
2054 | 253 | provides: | ||
2055 | 254 | db: | ||
2056 | 255 | interface: mysql | ||
2057 | 256 | db-admin: | ||
2058 | 257 | interface: mysql-root | ||
2059 | 258 | shared-db: | ||
2060 | 259 | interface: mysql-shared | ||
2061 | 260 | master: | ||
2062 | 261 | interface: mysql-oneway-replication | ||
2063 | 262 | munin: | ||
2064 | 263 | interface: munin-node | ||
2065 | 264 | monitors: | ||
2066 | 265 | interface: monitors | ||
2067 | 266 | local-monitors: | ||
2068 | 267 | interface: local-monitors | ||
2069 | 268 | scope: container | ||
2070 | 269 | |||
2071 | 270 | peers: | ||
2072 | 271 | cluster: | ||
2073 | 272 | interface: mysql-ha | ||
2074 | 273 | |||
2075 | 274 | requires: | ||
2076 | 275 | slave: | ||
2077 | 276 | interface: mysql-oneway-replication | ||
2078 | 277 | ceph: | ||
2079 | 278 | interface: ceph-client | ||
2080 | 279 | ha: | ||
2081 | 280 | interface: hacluster | ||
2082 | 281 | scope: container | ||
2083 | 282 | </pre> | ||
2084 | 283 | |||
2085 | 284 | |||
2086 | 285 | </section> | ||
2087 | 286 | |||
2088 | 287 | |||
2089 | 288 | </article> | ||
2090 | 289 | <!--Postamble--> | ||
2091 | 290 | </div> | ||
2092 | 291 | </div> | ||
2093 | 292 | </section> | ||
2094 | 293 | </div> | ||
2095 | 294 | </div> | ||
2096 | 295 | <!--End-Postamble--> | ||
2097 | 296 | <!--Footer--> | ||
2098 | 297 | <footer class="global clearfix" role="contentinfo"> | ||
2099 | 298 | <nav role="navigation"> | ||
2100 | 299 | <div class="footer-a"> | ||
2101 | 300 | <div class="clearfix"> | ||
2102 | 301 | <ul> | ||
2103 | 302 | <li> | ||
2104 | 303 | <h2><a href="/">Juju</a></h2> | ||
2105 | 304 | <ul> | ||
2106 | 305 | <li><a href="/charms">Charms</a></li> | ||
2107 | 306 | <li><a href="/features">Features</a></li> | ||
2108 | 307 | <li><a href="/deployment">Deployment</a></li> | ||
2109 | 308 | </ul> | ||
2110 | 309 | </li> | ||
2111 | 310 | <li> | ||
2112 | 311 | <h2><a href="/resources">Resources</a></h2> | ||
2113 | 312 | <ul> | ||
2114 | 313 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
2115 | 314 | <li><a href="/docs/">Documentation</a></li> | ||
2116 | 315 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
2117 | 316 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
2118 | 317 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
2119 | 318 | <li><a href="/resources/videos/">Videos</a></li> | ||
2120 | 319 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
2121 | 320 | </ul> | ||
2122 | 321 | </li> | ||
2123 | 322 | <li> | ||
2124 | 323 | <h2><a href="/community">Community</a></h2> | ||
2125 | 324 | <ul> | ||
2126 | 325 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
2127 | 326 | <li><a href="/events/">Events</a></li> | ||
2128 | 327 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
2129 | 328 | <li><a href="/community/charmers/">Charmers</a></li> | ||
2130 | 329 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
2131 | 330 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
2132 | 331 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
2133 | 332 | </ul> | ||
2134 | 333 | </li> | ||
2135 | 334 | <li> | ||
2136 | 335 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
2137 | 336 | <ul> | ||
2138 | 337 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
2139 | 338 | <li><a href="/download/">Download Juju</a></li> | ||
2140 | 339 | </ul> | ||
2141 | 340 | </li> | ||
2142 | 341 | </ul> | ||
2143 | 342 | </div> | ||
2144 | 343 | </div> | ||
2145 | 344 | </nav> | ||
2146 | 345 | <div class="legal clearfix"> | ||
2147 | 346 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
2148 | 347 | </div> | ||
2149 | 348 | </footer> | ||
2150 | 349 | |||
2151 | 350 | <!--End-Footer--> | ||
2152 | 351 | <!--Scripts--> | ||
2153 | 352 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
2154 | 353 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
2155 | 354 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
2156 | 355 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
2157 | 356 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
2158 | 357 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
2159 | 358 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
2160 | 359 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
2161 | 360 | <!-- google analytics --> | ||
2162 | 361 | <script> | ||
2163 | 362 | var _gaq = _gaq || []; | ||
2164 | 363 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
2165 | 364 | _gaq.push(['_trackPageview']); | ||
2166 | 365 | |||
2167 | 366 | (function() { | ||
2168 | 367 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
2169 | 368 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
2170 | 369 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
2171 | 370 | })(); | ||
2172 | 371 | </script> | ||
2173 | 372 | <!--End-Scripts--> | ||
2174 | 373 | |||
2175 | 374 | |||
2176 | 375 | </body></html> | ||
2177 | 376 | |||
2178 | 0 | 377 | ||
2179 | === modified file 'htmldocs/authors-charm-policy.html' | |||
2180 | --- htmldocs/authors-charm-policy.html 2013-09-27 14:53:30 +0000 | |||
2181 | +++ htmldocs/authors-charm-policy.html 2013-10-09 20:07:46 +0000 | |||
2182 | @@ -23,6 +23,8 @@ | |||
2183 | 23 | 23 | ||
2184 | 24 | 24 | ||
2185 | 25 | 25 | ||
2186 | 26 | |||
2187 | 27 | |||
2188 | 26 | <body class="resources"> | 28 | <body class="resources"> |
2189 | 27 | 29 | ||
2190 | 28 | <!--Header--> | 30 | <!--Header--> |
2191 | @@ -94,7 +96,7 @@ | |||
2192 | 94 | 96 | ||
2193 | 95 | <h2>metadata.yaml</h2> | 97 | <h2>metadata.yaml</h2> |
2194 | 96 | 98 | ||
2196 | 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> |
2197 | 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> |
2198 | 99 | 101 | ||
2199 | 100 | 102 | ||
2200 | @@ -212,4 +214,6 @@ | |||
2201 | 212 | <!--End-Scripts--> | 214 | <!--End-Scripts--> |
2202 | 213 | 215 | ||
2203 | 214 | 216 | ||
2204 | 217 | |||
2205 | 218 | |||
2206 | 215 | </body></html> | 219 | </body></html> |
2207 | 216 | 220 | ||
2208 | === modified file 'htmldocs/authors-charm-quality.html' | |||
2209 | --- htmldocs/authors-charm-quality.html 2013-09-27 14:53:30 +0000 | |||
2210 | +++ htmldocs/authors-charm-quality.html 2013-10-09 20:07:46 +0000 | |||
2211 | @@ -23,6 +23,8 @@ | |||
2212 | 23 | 23 | ||
2213 | 24 | 24 | ||
2214 | 25 | 25 | ||
2215 | 26 | |||
2216 | 27 | |||
2217 | 26 | <body class="resources"> | 28 | <body class="resources"> |
2218 | 27 | 29 | ||
2219 | 28 | <!--Header--> | 30 | <!--Header--> |
2220 | @@ -295,4 +297,6 @@ | |||
2221 | 295 | <!--End-Scripts--> | 297 | <!--End-Scripts--> |
2222 | 296 | 298 | ||
2223 | 297 | 299 | ||
2224 | 300 | |||
2225 | 301 | |||
2226 | 298 | </body></html> | 302 | </body></html> |
2227 | 299 | 303 | ||
2228 | === modified file 'htmldocs/authors-charm-store.html' | |||
2229 | --- htmldocs/authors-charm-store.html 2013-09-27 14:53:30 +0000 | |||
2230 | +++ htmldocs/authors-charm-store.html 2013-10-09 20:07:46 +0000 | |||
2231 | @@ -23,6 +23,8 @@ | |||
2232 | 23 | 23 | ||
2233 | 24 | 24 | ||
2234 | 25 | 25 | ||
2235 | 26 | |||
2236 | 27 | |||
2237 | 26 | <body class="resources"> | 28 | <body class="resources"> |
2238 | 27 | 29 | ||
2239 | 28 | <!--Header--> | 30 | <!--Header--> |
2240 | @@ -297,4 +299,6 @@ | |||
2241 | 297 | <!--End-Scripts--> | 299 | <!--End-Scripts--> |
2242 | 298 | 300 | ||
2243 | 299 | 301 | ||
2244 | 302 | |||
2245 | 303 | |||
2246 | 300 | </body></html> | 304 | </body></html> |
2247 | 301 | 305 | ||
2248 | === added file 'htmldocs/authors-charm-upgrades.html' | |||
2249 | --- htmldocs/authors-charm-upgrades.html 1970-01-01 00:00:00 +0000 | |||
2250 | +++ htmldocs/authors-charm-upgrades.html 2013-10-09 20:07:46 +0000 | |||
2251 | @@ -0,0 +1,212 @@ | |||
2252 | 1 | <!DOCTYPE html> | ||
2253 | 2 | <html> | ||
2254 | 3 | <head> | ||
2255 | 4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||
2256 | 5 | <title>Juju Documentation - Charm Upgrades</title> | ||
2257 | 6 | <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' /> | ||
2258 | 7 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" /> | ||
2259 | 8 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" /> | ||
2260 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" /> | ||
2261 | 10 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" /> | ||
2262 | 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' /> | ||
2263 | 12 | <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/> | ||
2264 | 13 | |||
2265 | 14 | <!--[if lt IE 9]> | ||
2266 | 15 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
2267 | 16 | <![endif]--> | ||
2268 | 17 | </head> | ||
2269 | 18 | <body class="resources"> | ||
2270 | 19 | <header class="global clearfix" role="banner"> | ||
2271 | 20 | <div class="header-navigation"> | ||
2272 | 21 | <div> | ||
2273 | 22 | <nav role="navigation"> | ||
2274 | 23 | <ul> | ||
2275 | 24 | <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li> | ||
2276 | 25 | <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li> | ||
2277 | 26 | <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
2278 | 27 | <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
2279 | 28 | <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li> | ||
2280 | 29 | <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li> | ||
2281 | 30 | <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li> | ||
2282 | 31 | <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li> | ||
2283 | 32 | <li> | ||
2284 | 33 | <form id="form-search" method="get" action="https://juju.ubuntu.com/"> | ||
2285 | 34 | <fieldset> | ||
2286 | 35 | <input id="input-search" type="text" name="s" value="Search" /> | ||
2287 | 36 | </fieldset> | ||
2288 | 37 | </form> | ||
2289 | 38 | </li> | ||
2290 | 39 | </ul> | ||
2291 | 40 | </nav> | ||
2292 | 41 | </div> | ||
2293 | 42 | </div> | ||
2294 | 43 | <div class="header-content"> | ||
2295 | 44 | <div class="clearfix"> | ||
2296 | 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"> | ||
2297 | 46 | <div class="header-navigation-secondary"></div> | ||
2298 | 47 | <div class="header-image"></div> | ||
2299 | 48 | <h1>Resources</h1> | ||
2300 | 49 | <h2>A collection of some of the most important online references for Juju users and developers.</h2> | ||
2301 | 50 | </div> | ||
2302 | 51 | </div> | ||
2303 | 52 | </header> | ||
2304 | 53 | |||
2305 | 54 | <section id="content" class="container-12"> | ||
2306 | 55 | <div class="grid-12 doc-container"> | ||
2307 | 56 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
2308 | 57 | <div class="grid-9 doc-content"> | ||
2309 | 58 | <article> | ||
2310 | 59 | |||
2311 | 60 | |||
2312 | 61 | <!--Actual docs start here--> | ||
2313 | 62 | |||
2314 | 63 | <section id="charm-upgrades"> | ||
2315 | 64 | <h1>Charm upgrades</h1> | ||
2316 | 65 | |||
2317 | 66 | <p>A service's charm can be changed at runtime with the <code>upgrade-charm</code> | ||
2318 | 67 | command. By default, it changes to the latest available version of the same charm; if | ||
2319 | 68 | <code>--revision</code> is specified, it changes to that revision of the same charm; and | ||
2320 | 69 | if <code>--switch</code> is specified it changes to any arbitrary charm, inferred from the | ||
2321 | 70 | argument in the same way as in <code>juju deploy</code>.</p> | ||
2322 | 71 | |||
2323 | 72 | <p>For a charm to replace another, though, there is a minimum standard of | ||
2324 | 73 | compatibility, which applies regardless of the particular change. That is:</p> | ||
2325 | 74 | <ul> | ||
2326 | 75 | <li>a subordinate charm must be replaced by a subordinate charm, and a | ||
2327 | 76 | principal charm must be replaced by a principal charm.</li> | ||
2328 | 77 | <li>every runtime relation used by the service must exist in both charms.</li> | ||
2329 | 78 | <li class=" sub">charm relations that are defined, but not in use at runtime, | ||
2330 | 79 | may be removed freely.</li> | ||
2331 | 80 | <li class=" sub">in particular, it's not possible to remove a peer relation by | ||
2332 | 81 | upgrading, because peer relations are always in use.</li> | ||
2333 | 82 | </ul> | ||
2334 | 83 | <p>No other factor is used in determining compatibility: configuration settings | ||
2335 | 84 | in particular are converted completely naively, such that any settings from | ||
2336 | 85 | the original charm that share a name and type are preserved; any incompatible | ||
2337 | 86 | settings are removed; and any new settings take defaults as though freshly | ||
2338 | 87 | deployed.</p> | ||
2339 | 88 | |||
2340 | 89 | <p>When a service has been upgraded but a particular unit has not, the unit will | ||
2341 | 90 | continue to see the configuration settings from before conversion; these settings | ||
2342 | 91 | will not be affected by subsequent changes to the service's settings.</p> | ||
2343 | 92 | </section> | ||
2344 | 93 | |||
2345 | 94 | <section id="forced-upgrades"> | ||
2346 | 95 | <h2>Forced charm upgrades</h2> | ||
2347 | 96 | |||
2348 | 97 | <p>Juju defines the upgrade-charm <a href="./authors-hook-kinds.html">hook</a> for | ||
2349 | 98 | resolving differences between versions of the same charm. No notice is given of | ||
2350 | 99 | charm upgrades; a charm upgrade may run at any time the unit is started, and the | ||
2351 | 100 | only opportunity for resolution that exists occurs *after* the change has taken | ||
2352 | 101 | place.</p> | ||
2353 | 102 | |||
2354 | 103 | <p>This is quite a tight restriction, but nonetheless valuable, so long as you can | ||
2355 | 104 | guarantee it'll run. However, it's important to understand that the upgrade-charm | ||
2356 | 105 | accepts a <code>--force</code> flag: a forced charm upgrade will upgrade even units | ||
2357 | 106 | that are currently in an <a href="./authors-hook-errors.html">error</a> state, at | ||
2358 | 107 | the cost of skipping the <code>upgrade-charm</code> hook for those units.</p> | ||
2359 | 108 | |||
2360 | 109 | <p>This is useful for charm authors who want to push a new version of a failed hook | ||
2361 | 110 | (they can <code>upgrade-charm --force</code> and then <code>resolved --retry</code> | ||
2362 | 111 | to run it immediately without otherwise disturbing the system); but it's potentially | ||
2363 | 112 | dangerous if abused. We recommend that use of the feature be restricted to charm | ||
2364 | 113 | authors while developing their own charms, and that it's not sensible to devote | ||
2365 | 114 | serious effort to recovering from inappropriately forced upgrades.</p> | ||
2366 | 115 | </section> | ||
2367 | 116 | |||
2368 | 117 | <section id="upgrade-errors"> | ||
2369 | 118 | <h2>Charm upgrade errors</h2> | ||
2370 | 119 | |||
2371 | 120 | <p>These will only occur as a result of conflicts between the contents of the | ||
2372 | 121 | charm directory written at runtime, and should never be seen by a user; users | ||
2373 | 122 | certainly cannot be expected to understand the structure of your charm well | ||
2374 | 123 | enough to solve the conflicts sanely.</p> | ||
2375 | 124 | |||
2376 | 125 | <p>When you're writing a new version of a charm, you should always test upgrading | ||
2377 | 126 | it from (at least) the previous version, to ensure these errors don't slip out | ||
2378 | 127 | into the wild.</p> | ||
2379 | 128 | |||
2380 | 129 | <p>You can completely avoid these errors by <em>never</em> writing to the charm | ||
2381 | 130 | directory; and you can also avoid them by rigorously delineating the parts of | ||
2382 | 131 | your charm directory that you write to at runtime, and ensuring you never add a | ||
2383 | 132 | file to the raw charm that could conflict with the runtime state.</p> | ||
2384 | 133 | |||
2385 | 134 | <p>If you're writing your hooks in python, you should be doubly aware of this: if | ||
2386 | 135 | you don't configure python to suppress bytecode caching, it will write <code>.pyc</code> | ||
2387 | 136 | files next to your python files at runtime, and effectively prevent you from | ||
2388 | 137 | rearranging those directories in future. This is not an unreasonable burden to | ||
2389 | 138 | bear, but it's important to know you're taking it on.</p> | ||
2390 | 139 | |||
2391 | 140 | <p>If you encounter a charm upgrade error, you can run <code>git status</code> in | ||
2392 | 141 | the charm directory to see what the problem is, and use the knowledge thus gleaned to | ||
2393 | 142 | fix the charm and try to upgrade again.</p> | ||
2394 | 143 | </section> | ||
2395 | 144 | |||
2396 | 145 | |||
2397 | 146 | </article> | ||
2398 | 147 | </div> | ||
2399 | 148 | </div> | ||
2400 | 149 | </section> | ||
2401 | 150 | <div class="shadow"></div> | ||
2402 | 151 | <footer class="global clearfix" role="contentinfo"> | ||
2403 | 152 | <div class="row"> | ||
2404 | 153 | <div class="inner-wrapper"> | ||
2405 | 154 | <nav role="navigation" class="clearfix"> | ||
2406 | 155 | <ul class="footer-a"> | ||
2407 | 156 | <li class="grid-3 first-col"> | ||
2408 | 157 | <h4><a href="/get-started">Get started</a></h4> | ||
2409 | 158 | <ul> | ||
2410 | 159 | <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li> | ||
2411 | 160 | <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li> | ||
2412 | 161 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li> | ||
2413 | 162 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li> | ||
2414 | 163 | <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li> | ||
2415 | 164 | <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li> | ||
2416 | 165 | </ul> | ||
2417 | 166 | </li> | ||
2418 | 167 | <li class="grid-3"> | ||
2419 | 168 | <h4><a href="/resources">Resources</a></h4> | ||
2420 | 169 | <ul> | ||
2421 | 170 | <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li> | ||
2422 | 171 | <li><a href="/resources/videos/">Videos</a></li> | ||
2423 | 172 | <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li> | ||
2424 | 173 | </ul> | ||
2425 | 174 | </li> | ||
2426 | 175 | <li class="grid-3"> | ||
2427 | 176 | <h4><a href="/community">Community</a></h4> | ||
2428 | 177 | <ul> | ||
2429 | 178 | <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li> | ||
2430 | 179 | <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li> | ||
2431 | 180 | <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li> | ||
2432 | 181 | <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li> | ||
2433 | 182 | <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li> | ||
2434 | 183 | <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li> | ||
2435 | 184 | </ul> | ||
2436 | 185 | </li> | ||
2437 | 186 | <li class="grid-3 last-col"> | ||
2438 | 187 | <h4><a href="https://launchpad.net/juju">Code</a></h4> | ||
2439 | 188 | <ul> | ||
2440 | 189 | <li><a href="https://launchpad.net/juju-core">Juju Core</a></li> | ||
2441 | 190 | <li><a href="https://launchpad.net/charms">Charms</a></li> | ||
2442 | 191 | </ul> | ||
2443 | 192 | </li> | ||
2444 | 193 | </ul> | ||
2445 | 194 | </nav> | ||
2446 | 195 | </div> | ||
2447 | 196 | </div> | ||
2448 | 197 | <div class="row no-border"> | ||
2449 | 198 | <div class="legal inner-wrapper"> | ||
2450 | 199 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p> | ||
2451 | 200 | <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p> | ||
2452 | 201 | </div> | ||
2453 | 202 | </div> | ||
2454 | 203 | </footer> | ||
2455 | 204 | |||
2456 | 205 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
2457 | 206 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
2458 | 207 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
2459 | 208 | <script type="text/javascript" src="js/main.js"></script> | ||
2460 | 209 | <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script> | ||
2461 | 210 | </body> | ||
2462 | 211 | </html> | ||
2463 | 212 | |||
2464 | 0 | 213 | ||
2465 | === modified file 'htmldocs/authors-charm-writing.html' | |||
2466 | --- htmldocs/authors-charm-writing.html 2013-10-03 07:29:32 +0000 | |||
2467 | +++ htmldocs/authors-charm-writing.html 2013-10-09 20:07:46 +0000 | |||
2468 | @@ -23,6 +23,8 @@ | |||
2469 | 23 | 23 | ||
2470 | 24 | 24 | ||
2471 | 25 | 25 | ||
2472 | 26 | |||
2473 | 27 | |||
2474 | 26 | <body class="resources"> | 28 | <body class="resources"> |
2475 | 27 | 29 | ||
2476 | 28 | <!--Header--> | 30 | <!--Header--> |
2477 | @@ -166,7 +168,7 @@ | |||
2478 | 166 | <span class="number" > 4 </span> | 168 | <span class="number" > 4 </span> |
2479 | 167 | <div class="step" id="step04"> | 169 | <div class="step" id="step04"> |
2480 | 168 | <h2>Writing hooks</h2> | 170 | <h2>Writing hooks</h2> |
2482 | 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> |
2483 | 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> |
2484 | 171 | <ul> | 173 | <ul> |
2485 | 172 | <li>start - for when the service needs to be started.</li> | 174 | <li>start - for when the service needs to be started.</li> |
2486 | @@ -416,4 +418,6 @@ | |||
2487 | 416 | <!--End-Scripts--> | 418 | <!--End-Scripts--> |
2488 | 417 | 419 | ||
2489 | 418 | 420 | ||
2490 | 421 | |||
2491 | 422 | |||
2492 | 419 | </body></html> | 423 | </body></html> |
2493 | 420 | 424 | ||
2494 | === removed file 'htmldocs/authors-charms-in-action.html' | |||
2495 | --- htmldocs/authors-charms-in-action.html 2013-09-27 14:53:30 +0000 | |||
2496 | +++ htmldocs/authors-charms-in-action.html 1970-01-01 00:00:00 +0000 | |||
2497 | @@ -1,296 +0,0 @@ | |||
2498 | 1 | <!DOCTYPE html> | ||
2499 | 2 | <html> | ||
2500 | 3 | <!--Head--> | ||
2501 | 4 | <head> | ||
2502 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
2503 | 6 | <title>Juju Documentation</title> | ||
2504 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
2505 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
2506 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
2507 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
2508 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
2509 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
2510 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
2511 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
2512 | 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"> | ||
2513 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
2514 | 17 | |||
2515 | 18 | <!--[if lt IE 9]> | ||
2516 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
2517 | 20 | <![endif]--> | ||
2518 | 21 | </head> | ||
2519 | 22 | <!--End-Head--> | ||
2520 | 23 | |||
2521 | 24 | |||
2522 | 25 | |||
2523 | 26 | <body class="resources"> | ||
2524 | 27 | |||
2525 | 28 | <!--Header--> | ||
2526 | 29 | |||
2527 | 30 | <header class="banner global" role="banner"> | ||
2528 | 31 | <nav role="navigation" class="nav-primary nav-right"> | ||
2529 | 32 | <div class="logo"> | ||
2530 | 33 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
2531 | 34 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
2532 | 35 | <span>Juju</span> | ||
2533 | 36 | </a> | ||
2534 | 37 | </div> | ||
2535 | 38 | <ul> | ||
2536 | 39 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
2537 | 40 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
2538 | 41 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
2539 | 42 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
2540 | 43 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
2541 | 44 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
2542 | 45 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
2543 | 46 | </ul> | ||
2544 | 47 | <div id="box-search"> | ||
2545 | 48 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
2546 | 49 | <label class="off-left" for="s">Search:</label> | ||
2547 | 50 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
2548 | 51 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
2549 | 52 | </form> | ||
2550 | 53 | </div> | ||
2551 | 54 | </nav> | ||
2552 | 55 | </header> | ||
2553 | 56 | <!--End-Header--> | ||
2554 | 57 | <!--Preamble--> | ||
2555 | 58 | <div class="wrapper"> | ||
2556 | 59 | <div id="main-content" class="inner-wrapper" role="main"> | ||
2557 | 60 | <div class="row no-border"> | ||
2558 | 61 | <div class="header-navigation-secondary"></div> | ||
2559 | 62 | <h2 class="pagetitle">Juju documentation</h2> | ||
2560 | 63 | </div> | ||
2561 | 64 | <section id="content" class="container-12"> | ||
2562 | 65 | <div class="grid-12 doc-container"> | ||
2563 | 66 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
2564 | 67 | <div class="grid-9 doc-content"> | ||
2565 | 68 | <!--End-Preamble--> | ||
2566 | 69 | <article> | ||
2567 | 70 | <section id="charm-in-action"> | ||
2568 | 71 | <h1 id="charms-in-action">Charms in action</h1> | ||
2569 | 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> | ||
2570 | 73 | |||
2571 | 74 | <h2 id="hooks">Hooks</h2> | ||
2572 | 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> | ||
2573 | 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> | ||
2574 | 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> | ||
2575 | 78 | |||
2576 | 79 | <h2 id="errors-in-hooks">Errors in hooks</h2> | ||
2577 | 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> | ||
2578 | 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> | ||
2579 | 82 | <p>[TODO: I have a vague feeling that <code>juju resolved</code> actually defaults to "just pretend the hook ran successfully" mode. I'm not sure that's really the best default, but I'm also not sure we're in a position to change the UI that much.]</p> | ||
2580 | 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> | ||
2581 | 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 "X hook failed". Wishlist, really.]</p> | ||
2582 | 85 | |||
2583 | 86 | <h2 id="charm-deployment">Charm deployment</h2> | ||
2584 | 87 | <ul> | ||
2585 | 88 | <li>A charm is deployed into a directory that is entirely owned and controlled by juju.</li> | ||
2586 | 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> | ||
2587 | 90 | <li>At these times, and only at these times, should the charm directory be used by anything other than juju itself.</li> | ||
2588 | 91 | </ul> | ||
2589 | 92 | |||
2590 | 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> | ||
2591 | 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> | ||
2592 | 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 <unit></code> should also default to a juju-run environment: primarily because, without this, in the context of forced upgrades, the system cannot offer <em>any</em> guarantees about what it might suddenly do to the charm directory while the user's doing things with it. The alternative is to allow unguarded ssh, but tell people that they have to use something like <code>juju-run --interactive</code> before they modify the charm dir; this feels somewhat user-hostile, though.]</p> | ||
2593 | 96 | |||
2594 | 97 | <h2 id="execution-environment">Execution environment</h2> | ||
2595 | 98 | <p>Every hook is run in the deployed charm directory, in an environment with the following characteristics:</p> | ||
2596 | 99 | <ul> | ||
2597 | 100 | <li>$PATH is prefixed by a directory containing command line tools through which the hooks can interact with juju.</li> | ||
2598 | 101 | <li>$CHARM_DIR holds the path to the charm directory.</li> | ||
2599 | 102 | <li>$JUJU_UNIT_NAME holds the name of the local unit.</li> | ||
2600 | 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> | ||
2601 | 104 | <li>$JUJU_API_ADDRESSES holds a space separated list of juju API addresses.</li> | ||
2602 | 105 | </ul> | ||
2603 | 106 | <h2 id="hook-tools">Hook tools</h2> | ||
2604 | 107 | <p>All hooks can directly use the following tools:</p> | ||
2605 | 108 | <ul> | ||
2606 | 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> | ||
2607 | 110 | <li>unit-get (returns the local unit's private-address or public-address)</li> | ||
2608 | 111 | <li>open-port (marks the supplied port/protocol as ready to open when the service is exposed)</li> | ||
2609 | 112 | <li>close-port (reverses the effect of open-port)</li> | ||
2610 | 113 | <li>config-get (get current service configuration values)</li> | ||
2611 | 114 | <li>relation-get (get the settings of some related unit)</li> | ||
2612 | 115 | <li>relation-set (write the local unit's relation settings)</li> | ||
2613 | 116 | <li>relation-ids (list all relations using a given charm relation)</li> | ||
2614 | 117 | <li>relation-list (list all units of a related service)</li> | ||
2615 | 118 | </ul> | ||
2616 | 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> | ||
2617 | 120 | <ul> | ||
2618 | 121 | <li>Any data retrieved corresponds to the real value of the underlying state at some point in time.</li> | ||
2619 | 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> | ||
2620 | 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> | ||
2621 | 124 | <li>Not actually sandboxed: open-port and close-port operate directly on state. [TODO: lp:1089304 - might be a little tricky.]</li> | ||
2622 | 125 | </ul> | ||
2623 | 126 | |||
2624 | 127 | <h2 id="hook-kinds">Hook kinds</h2> | ||
2625 | 128 | <p>There are 5 <code>unit hooks</code> with predefined names that can be implemented by any charm:</p> | ||
2626 | 129 | <ul> | ||
2627 | 130 | <li>install</li> | ||
2628 | 131 | <li>config-changed</li> | ||
2629 | 132 | <li>start</li> | ||
2630 | 133 | <li>upgrade-charm</li> | ||
2631 | 134 | <li>stop</li> | ||
2632 | 135 | </ul> | ||
2633 | 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> | ||
2634 | 137 | <ul> | ||
2635 | 138 | <li><name>-relation-joined</li> | ||
2636 | 139 | <li><name>-relation-changed</li> | ||
2637 | 140 | <li><name>-relation-departed</li> | ||
2638 | 141 | <li><name>-relation-broken</li> | ||
2639 | 142 | </ul> | ||
2640 | 143 | |||
2641 | 144 | <h2 id="unit-hooks">Unit hooks</h2> | ||
2642 | 145 | <p>The <code>install</code> hook always runs once, and only once, before any other hook.</p> | ||
2643 | 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> | ||
2644 | 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> | ||
2645 | 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> | ||
2646 | 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> | ||
2647 | 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> | ||
2648 | 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> | ||
2649 | 152 | |||
2650 | 153 | <h2 id="relation-hooks">Relation hooks</h2> | ||
2651 | 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> | ||
2652 | 155 | <ul> | ||
2653 | 156 | <li>JUJU_RELATION is set to the name of the charm relation. This is of limited value, because every relation hook already "knows" what charm relation it was written for; that is, in the "foo-relation-joined" hook, JUJU_RELATION is "foo".</li> | ||
2654 | 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 "foo" charm relation, JUJU_RELATION_ID always has the form "foo:<id>", where id uniquely but opaquely identifies the runtime relation currently in play.</li> | ||
2655 | 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> | ||
2656 | 159 | </ul> | ||
2657 | 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> | ||
2658 | 161 | <ul> | ||
2659 | 162 | <li>JUJU_REMOTE_UNIT is set to the name of the current related unit.</li> | ||
2660 | 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> | ||
2661 | 164 | </ul> | ||
2662 | 165 | <p>For every relation in which a unit partcipates, hooks for the appropriate charm relation are run according to the following rules.</p> | ||
2663 | 166 | <p>The "relation-joined" hook always runs once when a related unit is first seen.</p> | ||
2664 | 167 | <p>The "relation-changed" 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 "immediately" only applies within the context of this particular runtime relation -- that is, when "foo-relation-joined" is run for unit "bar/99" in relation id "foo:123", the only guarantee is that the next hook to be run <em>in relation id "foo:123"</em> will be "foo-relation-changed" for "bar/99". Unit hooks may intervene, as may hooks for other relations, and even for other "foo" relations.</p> | ||
2665 | 168 | <p>The "relation-departed" hook for a given unit always runs once when a related unit is no longer related. After the "relation-departed" hook has run, no further notifications will be received from that unit; however, its settings will remain accessible via relation-get for the complete lifetime of the relation.</p> | ||
2666 | 169 | <p>The "relation-broken" hook is not specific to any unit, and always runs once when the local unit is ready to depart the relation itself. Before this hook is run, a relation-departed hook will be executed for every unit known to be related; it will never run while the relation appears to have members, but it may be the first and only hook to run for a given relation. The stop hook will not run while relations remain to be broken.</p> | ||
2667 | 170 | <h2 id="relations-in-depth">Relations in depth</h2> | ||
2668 | 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> | ||
2669 | 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> | ||
2670 | 173 | <ul> | ||
2671 | 174 | <li>Write initial relation settings (just one value, "private-address"), to ensure that they will be available to observers before they're triggered by the next step;</li> | ||
2672 | 175 | <li>Signal its existence, and role in the relation, to the rest of the system.</li> | ||
2673 | 176 | </ul> | ||
2674 | 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> | ||
2675 | 178 | <ul> | ||
2676 | 179 | <li>Each provider unit observes every requirer unit</li> | ||
2677 | 180 | <li>Each requirer unit observes every provider unit</li> | ||
2678 | 181 | <li>Each peer unit observes every other peer unit</li> | ||
2679 | 182 | </ul> | ||
2680 | 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> | ||
2681 | 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> | ||
2682 | 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> | ||
2683 | 186 | <p>[TODO: There is a school of thought that maintains that we should add an independent "juju-private-address" setting that <em>is</em> guaranteed, but for now the reality is that relation-get can <em>always</em> fail to produce any given value. However, in the name of sanity, it's probably reasonable to treat a missing private-address as an error, and assume that <code>relation-get private-address</code> is always safe. For all other values, we must operate with the understanding that relation-get can always fail.]</p> | ||
2684 | 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> | ||
2685 | 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> | ||
2686 | 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> | ||
2687 | 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> | ||
2688 | 191 | <h2 id="departing-relations">Departing relations</h2> | ||
2689 | 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> | ||
2690 | 193 | <ul> | ||
2691 | 194 | <li>For every known related unit -- those which have joined and not yet departed -- run the relation-departed hook.</li> | ||
2692 | 195 | <li>Run the relation-broken hook.</li> | ||
2693 | 196 | <li><code>depart</code> from its scope in the relation.</li> | ||
2694 | 197 | </ul> | ||
2695 | 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> | ||
2696 | 199 | <h2 id="debugging-charms">Debugging charms</h2> | ||
2697 | 200 | <p>Facilities are currently not good.</p> | ||
2698 | 201 | <ul> | ||
2699 | 202 | <li>juju ssh</li> | ||
2700 | 203 | <li>juju debug-hooks</li> | ||
2701 | 204 | <li>juju debug-log</li> | ||
2702 | 205 | </ul> | ||
2703 | 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> | ||
2704 | 207 | </article> | ||
2705 | 208 | </section> | ||
2706 | 209 | <!--Postamble--> | ||
2707 | 210 | </div> | ||
2708 | 211 | </div> | ||
2709 | 212 | </section> | ||
2710 | 213 | </div> | ||
2711 | 214 | </div> | ||
2712 | 215 | <!--End-Postamble--> | ||
2713 | 216 | <!--Footer--> | ||
2714 | 217 | <footer class="global clearfix" role="contentinfo"> | ||
2715 | 218 | <nav role="navigation"> | ||
2716 | 219 | <div class="footer-a"> | ||
2717 | 220 | <div class="clearfix"> | ||
2718 | 221 | <ul> | ||
2719 | 222 | <li> | ||
2720 | 223 | <h2><a href="/">Juju</a></h2> | ||
2721 | 224 | <ul> | ||
2722 | 225 | <li><a href="/charms">Charms</a></li> | ||
2723 | 226 | <li><a href="/features">Features</a></li> | ||
2724 | 227 | <li><a href="/deployment">Deployment</a></li> | ||
2725 | 228 | </ul> | ||
2726 | 229 | </li> | ||
2727 | 230 | <li> | ||
2728 | 231 | <h2><a href="/resources">Resources</a></h2> | ||
2729 | 232 | <ul> | ||
2730 | 233 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
2731 | 234 | <li><a href="/docs/">Documentation</a></li> | ||
2732 | 235 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
2733 | 236 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
2734 | 237 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
2735 | 238 | <li><a href="/resources/videos/">Videos</a></li> | ||
2736 | 239 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
2737 | 240 | </ul> | ||
2738 | 241 | </li> | ||
2739 | 242 | <li> | ||
2740 | 243 | <h2><a href="/community">Community</a></h2> | ||
2741 | 244 | <ul> | ||
2742 | 245 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
2743 | 246 | <li><a href="/events/">Events</a></li> | ||
2744 | 247 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
2745 | 248 | <li><a href="/community/charmers/">Charmers</a></li> | ||
2746 | 249 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
2747 | 250 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
2748 | 251 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
2749 | 252 | </ul> | ||
2750 | 253 | </li> | ||
2751 | 254 | <li> | ||
2752 | 255 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
2753 | 256 | <ul> | ||
2754 | 257 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
2755 | 258 | <li><a href="/download/">Download Juju</a></li> | ||
2756 | 259 | </ul> | ||
2757 | 260 | </li> | ||
2758 | 261 | </ul> | ||
2759 | 262 | </div> | ||
2760 | 263 | </div> | ||
2761 | 264 | </nav> | ||
2762 | 265 | <div class="legal clearfix"> | ||
2763 | 266 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
2764 | 267 | </div> | ||
2765 | 268 | </footer> | ||
2766 | 269 | |||
2767 | 270 | <!--End-Footer--> | ||
2768 | 271 | |||
2769 | 272 | <!--Scripts--> | ||
2770 | 273 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
2771 | 274 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
2772 | 275 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
2773 | 276 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
2774 | 277 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
2775 | 278 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
2776 | 279 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
2777 | 280 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
2778 | 281 | <!-- google analytics --> | ||
2779 | 282 | <script> | ||
2780 | 283 | var _gaq = _gaq || []; | ||
2781 | 284 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
2782 | 285 | _gaq.push(['_trackPageview']); | ||
2783 | 286 | |||
2784 | 287 | (function() { | ||
2785 | 288 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
2786 | 289 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
2787 | 290 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
2788 | 291 | })(); | ||
2789 | 292 | </script> | ||
2790 | 293 | <!--End-Scripts--> | ||
2791 | 294 | |||
2792 | 295 | |||
2793 | 296 | </body></html> | ||
2794 | 297 | \ No newline at end of file | 0 | \ No newline at end of file |
2795 | 298 | 1 | ||
2796 | === added file 'htmldocs/authors-hook-debug.html' | |||
2797 | --- htmldocs/authors-hook-debug.html 1970-01-01 00:00:00 +0000 | |||
2798 | +++ htmldocs/authors-hook-debug.html 2013-10-09 20:07:46 +0000 | |||
2799 | @@ -0,0 +1,169 @@ | |||
2800 | 1 | <!DOCTYPE html> | ||
2801 | 2 | <html> | ||
2802 | 3 | <head> | ||
2803 | 4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||
2804 | 5 | <title>Juju Documentation - Hook Debugging</title> | ||
2805 | 6 | <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' /> | ||
2806 | 7 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" /> | ||
2807 | 8 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" /> | ||
2808 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" /> | ||
2809 | 10 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" /> | ||
2810 | 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' /> | ||
2811 | 12 | <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/> | ||
2812 | 13 | |||
2813 | 14 | <!--[if lt IE 9]> | ||
2814 | 15 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
2815 | 16 | <![endif]--> | ||
2816 | 17 | </head> | ||
2817 | 18 | <body class="resources"> | ||
2818 | 19 | <header class="global clearfix" role="banner"> | ||
2819 | 20 | <div class="header-navigation"> | ||
2820 | 21 | <div> | ||
2821 | 22 | <nav role="navigation"> | ||
2822 | 23 | <ul> | ||
2823 | 24 | <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li> | ||
2824 | 25 | <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li> | ||
2825 | 26 | <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
2826 | 27 | <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
2827 | 28 | <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li> | ||
2828 | 29 | <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li> | ||
2829 | 30 | <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li> | ||
2830 | 31 | <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li> | ||
2831 | 32 | <li> | ||
2832 | 33 | <form id="form-search" method="get" action="https://juju.ubuntu.com/"> | ||
2833 | 34 | <fieldset> | ||
2834 | 35 | <input id="input-search" type="text" name="s" value="Search" /> | ||
2835 | 36 | </fieldset> | ||
2836 | 37 | </form> | ||
2837 | 38 | </li> | ||
2838 | 39 | </ul> | ||
2839 | 40 | </nav> | ||
2840 | 41 | </div> | ||
2841 | 42 | </div> | ||
2842 | 43 | <div class="header-content"> | ||
2843 | 44 | <div class="clearfix"> | ||
2844 | 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"> | ||
2845 | 46 | <div class="header-navigation-secondary"></div> | ||
2846 | 47 | <div class="header-image"></div> | ||
2847 | 48 | <h1>Resources</h1> | ||
2848 | 49 | <h2>A collection of some of the most important online references for Juju users and developers.</h2> | ||
2849 | 50 | </div> | ||
2850 | 51 | </div> | ||
2851 | 52 | </header> | ||
2852 | 53 | |||
2853 | 54 | <section id="content" class="container-12"> | ||
2854 | 55 | <div class="grid-12 doc-container"> | ||
2855 | 56 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
2856 | 57 | <div class="grid-9 doc-content"> | ||
2857 | 58 | <article> | ||
2858 | 59 | |||
2859 | 60 | |||
2860 | 61 | <section id="debugging-hooks"> | ||
2861 | 62 | <h1>Debugging hooks</h1> | ||
2862 | 63 | |||
2863 | 64 | <p>The <code>juju debug-hooks</code> command accepts a unit and an optional list | ||
2864 | 65 | of hooks to debug, which must each be named individually -- or all omitted, causing all | ||
2865 | 66 | hooks to be debugged.</p> | ||
2866 | 67 | |||
2867 | 68 | <p>When you start a debug-hooks session, juju creates a tmux session on the | ||
2868 | 69 | machine running the requested unit; while that session persists, all hook | ||
2869 | 70 | executions will be replaced with new windows in that session, which run an | ||
2870 | 71 | <a href="./authors-hook-environment.html">environment</a> matching that of the | ||
2871 | 72 | appropriate hook (with one addition: <code>$JUJU_HOOK_NAME</code>) and which are | ||
2872 | 73 | marked as succeeded or failed depending on the exit code of the window.</p> | ||
2873 | 74 | |||
2874 | 75 | <p>You can stop debugging by closing all windows in the tmux session.</p> | ||
2875 | 76 | </section> | ||
2876 | 77 | |||
2877 | 78 | <section id="intercept-install"> | ||
2878 | 79 | <h2>Debugging early hooks</h2> | ||
2879 | 80 | |||
2880 | 81 | <p>The <code>install</code>, <code>config-changed</code>, and <code>start</code> | ||
2881 | 82 | hooks often execute quite soon after the unit comes up, making it difficult to start | ||
2882 | 83 | a debug-hooks session in time to intercept them. If you're having difficulties, you | ||
2883 | 84 | can temporarily return an error code from your <code>install</code> hook, and start | ||
2884 | 85 | your session only when the unit reports an <a href="./authors-hook-errors.html">error | ||
2885 | 86 | status</a>; then run <code>juju resolved --retry</code> for the affected unit, and go | ||
2886 | 87 | back to the debug-hooks session to interact.</p> | ||
2887 | 88 | </section> | ||
2888 | 89 | |||
2889 | 90 | <section id="notes"> | ||
2890 | 91 | <h2>Special considerations</h2> | ||
2891 | 92 | |||
2892 | 93 | <p>While you're debugging hooks for one unit on a machine, you're blocking | ||
2893 | 94 | execution of all hooks on that machine. This is generally helpful, because | ||
2894 | 95 | you don't want to have to contend with concurrent changes to the machine's | ||
2895 | 96 | software, but you should be aware that multiple debug-hooks sessions for | ||
2896 | 97 | units assigned to the same machine will block one another, and that you | ||
2897 | 98 | can't control relative execution order directly (other than by erroring out | ||
2898 | 99 | of hooks you don't want to run yet, and retrying them later).</p> | ||
2899 | 100 | </section> | ||
2900 | 101 | |||
2901 | 102 | |||
2902 | 103 | </article> | ||
2903 | 104 | </div> | ||
2904 | 105 | </div> | ||
2905 | 106 | </section> | ||
2906 | 107 | <div class="shadow"></div> | ||
2907 | 108 | <footer class="global clearfix" role="contentinfo"> | ||
2908 | 109 | <div class="row"> | ||
2909 | 110 | <div class="inner-wrapper"> | ||
2910 | 111 | <nav role="navigation" class="clearfix"> | ||
2911 | 112 | <ul class="footer-a"> | ||
2912 | 113 | <li class="grid-3 first-col"> | ||
2913 | 114 | <h4><a href="/get-started">Get started</a></h4> | ||
2914 | 115 | <ul> | ||
2915 | 116 | <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li> | ||
2916 | 117 | <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li> | ||
2917 | 118 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li> | ||
2918 | 119 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li> | ||
2919 | 120 | <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li> | ||
2920 | 121 | <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li> | ||
2921 | 122 | </ul> | ||
2922 | 123 | </li> | ||
2923 | 124 | <li class="grid-3"> | ||
2924 | 125 | <h4><a href="/resources">Resources</a></h4> | ||
2925 | 126 | <ul> | ||
2926 | 127 | <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li> | ||
2927 | 128 | <li><a href="/resources/videos/">Videos</a></li> | ||
2928 | 129 | <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li> | ||
2929 | 130 | </ul> | ||
2930 | 131 | </li> | ||
2931 | 132 | <li class="grid-3"> | ||
2932 | 133 | <h4><a href="/community">Community</a></h4> | ||
2933 | 134 | <ul> | ||
2934 | 135 | <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li> | ||
2935 | 136 | <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li> | ||
2936 | 137 | <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li> | ||
2937 | 138 | <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li> | ||
2938 | 139 | <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li> | ||
2939 | 140 | <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li> | ||
2940 | 141 | </ul> | ||
2941 | 142 | </li> | ||
2942 | 143 | <li class="grid-3 last-col"> | ||
2943 | 144 | <h4><a href="https://launchpad.net/juju">Code</a></h4> | ||
2944 | 145 | <ul> | ||
2945 | 146 | <li><a href="https://launchpad.net/juju-core">Juju Core</a></li> | ||
2946 | 147 | <li><a href="https://launchpad.net/charms">Charms</a></li> | ||
2947 | 148 | </ul> | ||
2948 | 149 | </li> | ||
2949 | 150 | </ul> | ||
2950 | 151 | </nav> | ||
2951 | 152 | </div> | ||
2952 | 153 | </div> | ||
2953 | 154 | <div class="row no-border"> | ||
2954 | 155 | <div class="legal inner-wrapper"> | ||
2955 | 156 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p> | ||
2956 | 157 | <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p> | ||
2957 | 158 | </div> | ||
2958 | 159 | </div> | ||
2959 | 160 | </footer> | ||
2960 | 161 | |||
2961 | 162 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
2962 | 163 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
2963 | 164 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
2964 | 165 | <script type="text/javascript" src="js/main.js"></script> | ||
2965 | 166 | <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script> | ||
2966 | 167 | </body> | ||
2967 | 168 | </html> | ||
2968 | 169 | |||
2969 | 0 | 170 | ||
2970 | === added file 'htmldocs/authors-hook-environment.html' | |||
2971 | --- htmldocs/authors-hook-environment.html 1970-01-01 00:00:00 +0000 | |||
2972 | +++ htmldocs/authors-hook-environment.html 2013-10-09 20:07:46 +0000 | |||
2973 | @@ -0,0 +1,561 @@ | |||
2974 | 1 | <!DOCTYPE html> | ||
2975 | 2 | <html> | ||
2976 | 3 | <!--Head--> | ||
2977 | 4 | <head> | ||
2978 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
2979 | 6 | <title>Juju Documentation</title> | ||
2980 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
2981 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
2982 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
2983 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
2984 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
2985 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
2986 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
2987 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
2988 | 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"> | ||
2989 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
2990 | 17 | |||
2991 | 18 | <!--[if lt IE 9]> | ||
2992 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
2993 | 20 | <![endif]--> | ||
2994 | 21 | </head> | ||
2995 | 22 | <!--End-Head--> | ||
2996 | 23 | |||
2997 | 24 | <body class="resources"> | ||
2998 | 25 | <!--Header--> | ||
2999 | 26 | |||
3000 | 27 | <header class="banner global" role="banner"> | ||
3001 | 28 | <nav role="navigation" class="nav-primary nav-right"> | ||
3002 | 29 | <div class="logo"> | ||
3003 | 30 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
3004 | 31 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
3005 | 32 | <span>Juju</span> | ||
3006 | 33 | </a> | ||
3007 | 34 | </div> | ||
3008 | 35 | <ul> | ||
3009 | 36 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
3010 | 37 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
3011 | 38 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
3012 | 39 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
3013 | 40 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
3014 | 41 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
3015 | 42 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
3016 | 43 | </ul> | ||
3017 | 44 | <div id="box-search"> | ||
3018 | 45 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
3019 | 46 | <label class="off-left" for="s">Search:</label> | ||
3020 | 47 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
3021 | 48 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
3022 | 49 | </form> | ||
3023 | 50 | </div> | ||
3024 | 51 | </nav> | ||
3025 | 52 | </header> | ||
3026 | 53 | <!--End-Header--> | ||
3027 | 54 | <!--Preamble--> | ||
3028 | 55 | <div class="wrapper"> | ||
3029 | 56 | <div id="main-content" class="inner-wrapper" role="main"> | ||
3030 | 57 | <div class="row no-border"> | ||
3031 | 58 | <div class="header-navigation-secondary"></div> | ||
3032 | 59 | <h2 class="pagetitle">Juju documentation</h2> | ||
3033 | 60 | </div> | ||
3034 | 61 | <section id="content" class="container-12"> | ||
3035 | 62 | <div class="grid-12 doc-container"> | ||
3036 | 63 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
3037 | 64 | <div class="grid-9 doc-content"> | ||
3038 | 65 | <!--End-Preamble--> | ||
3039 | 66 | <article> | ||
3040 | 67 | <section id="hook-execution-environment"> | ||
3041 | 68 | <h1>Hook execution environment</h1> | ||
3042 | 69 | |||
3043 | 70 | <p>When a charm is deployed onto a unit, the raw charm is extracted into a | ||
3044 | 71 | directory; this directory is known as the charm directory. It's owned and | ||
3045 | 72 | operated by juju, and juju sometimes temporarily cedes control of it to | ||
3046 | 73 | user code, by running a hook inside it.</p> | ||
3047 | 74 | |||
3048 | 75 | <p>When a hook's running, it should be considered to have sole access to the | ||
3049 | 76 | charm directory; at all other times, you should consider that juju may be | ||
3050 | 77 | making arbitrarily scary changes to the directory, and that it is not safe | ||
3051 | 78 | to read or write to anything in there at all.</p> | ||
3052 | 79 | |||
3053 | 80 | <p>This is to say that the software you install must, once it's running, be | ||
3054 | 81 | entirely independent of the charm that created it. It's fine (and encouraged, | ||
3055 | 82 | with some caveats) to store <em>charm</em> state in the charm directory, but the | ||
3056 | 83 | state of your <em>software</em> must remain unperturbed by direct changes to the | ||
3057 | 84 | charm.</p> | ||
3058 | 85 | |||
3059 | 86 | <p>So, every hook runs with easy access to the charm files. Every hook also runs | ||
3060 | 87 | as root, with a number of useful variables set, and has access to hook-specific | ||
3061 | 88 | tools that let you interrogate and affect the juju environment.</p> | ||
3062 | 89 | |||
3063 | 90 | <p>No more than one hook will execute on a given system at a given time. A unit in | ||
3064 | 91 | a container is considered to be on a different system to any unit on the | ||
3065 | 92 | container's host machine.</p> | ||
3066 | 93 | </section> | ||
3067 | 94 | |||
3068 | 95 | <section id="environment-variables"> | ||
3069 | 96 | <h2>Environment variables</h2> | ||
3070 | 97 | |||
3071 | 98 | <p>The following variables are always available.</p> | ||
3072 | 99 | <ul> | ||
3073 | 100 | <li>The <code>$CHARM_DIR</code> variable is the path to the charm directory.</li> | ||
3074 | 101 | <li>The <code>$PATH</code> variable is prefixed with the path to the hook tools | ||
3075 | 102 | directory.</li> | ||
3076 | 103 | <li>The <code>$JUJU_UNIT_NAME</code> variable holds the name of the unit.</li> | ||
3077 | 104 | <li>The <code>$JUJU_API_ADDRESSES</code> variable holds a space-separated list of API | ||
3078 | 105 | server addresses.</li> | ||
3079 | 106 | </ul> | ||
3080 | 107 | <p>In addition, every relation hook makes available relation-specific variables.</p> | ||
3081 | 108 | <ul> | ||
3082 | 109 | <li>The <code>$JUJU_RELATION</code> variable holds the relation name. This | ||
3083 | 110 | information is of limited value, because it's always the same as the part of | ||
3084 | 111 | the hook name just before "-relation-".</li> | ||
3085 | 112 | <li>The <code>$JUJU_RELATION_ID</code> variable holds an opaque relation | ||
3086 | 113 | identifier, used to distinguish between multiple relations with the same name. | ||
3087 | 114 | It is vitally important, because it's the only reasonable way of telling the | ||
3088 | 115 | difference between (say) a database service's many independent clients.</li> | ||
3089 | 116 | </ul> | ||
3090 | 117 | <p>...and, if that relation hook is not a -broken hook:</p> | ||
3091 | 118 | <ul> | ||
3092 | 119 | <li>The <code>$JUJU_REMOTE_UNIT</code> variable holds the name of the unit which | ||
3093 | 120 | is being reported to have -joined, -changed, or -departed.</li> | ||
3094 | 121 | </ul> | ||
3095 | 122 | <p>Juju does <em>not</em> pay any attention to the values of the above variables when | ||
3096 | 123 | running hook tools: they're a one-way communication channel from juju to | ||
3097 | 124 | the charm only. Finally, in all cases:</p> | ||
3098 | 125 | <ul> | ||
3099 | 126 | <li>The <code>$JUJU_AGENT_SOCKET</code> and <code>$JUJU_CONTEXT_ID</code> variables | ||
3100 | 127 | allow the hook tools to work: juju <em>does</em> pay attention to them, but you | ||
3101 | 128 | should treat them as opaque and avoid messing with them.</li> | ||
3102 | 129 | </ul> | ||
3103 | 130 | <p>Finally, if you're <a href="./authors-hook-debug.html">debugging</a>, you'll also | ||
3104 | 131 | have access to:</p> | ||
3105 | 132 | <ul> | ||
3106 | 133 | <li>The <code>$JUJU_HOOK_NAME</code> variable, which will be set to the current | ||
3107 | 134 | hook name.</li> | ||
3108 | 135 | </ul> | ||
3109 | 136 | </section> | ||
3110 | 137 | |||
3111 | 138 | <section id="hook-tools"> | ||
3112 | 139 | <h2>Hook tools</h2> | ||
3113 | 140 | |||
3114 | 141 | <p>All hook tools are available in all hooks. Many of the tools produce output, | ||
3115 | 142 | and those that do accept a <code>--format</code> flag whose value can be set to | ||
3116 | 143 | <code>json</code> or <code>yaml</code> as desired. If it's not specified, the format | ||
3117 | 144 | defaults to <code>smart</code>, which transforms the basic output as follows:</p> | ||
3118 | 145 | <ul> | ||
3119 | 146 | <li>strings are left untouched</li> | ||
3120 | 147 | <li>boolean values are converted to the strings <code>True</code> and | ||
3121 | 148 | <code>False</code></li> | ||
3122 | 149 | <li>ints and floats are converted directly to strings</li> | ||
3123 | 150 | <li>lists of strings are converted to a single newline-separated string</li> | ||
3124 | 151 | <li>all other types (in general, dictionaries) are formatted as YAML</li> | ||
3125 | 152 | </ul> | ||
3126 | 153 | <p>Tools which do not produce output also accept the <code>--format</code> flag, | ||
3127 | 154 | but ignore it, for compatibility reasons.</p> | ||
3128 | 155 | |||
3129 | 156 | <p>The various "relation-" tools infer context from the hook where | ||
3130 | 157 | possible. If they're running in a relation hook, the current relation id is set | ||
3131 | 158 | as the default; and if they're running in a -joined, -changed, or -broken hook, | ||
3132 | 159 | the current remote unit is set as the default.</p> | ||
3133 | 160 | |||
3134 | 161 | <p>Best use of relation hooks will be made by those who understand the | ||
3135 | 162 | <a href="./authors-relations-in-depth">relation model</a>.</p> | ||
3136 | 163 | </section> | ||
3137 | 164 | |||
3138 | 165 | <section id="juju-log"> | ||
3139 | 166 | <h3>juju-log</h3> | ||
3140 | 167 | |||
3141 | 168 | <p><code>juju-log</code> writes its arguments directly to the unit's log file. | ||
3142 | 169 | All hook output is currently logged anyway, so it's theoretically redundant with | ||
3143 | 170 | <code>echo</code>, but this is an implementation detail and should not be depended | ||
3144 | 171 | upon. If it's important, please <code>juju-log</code> it.</p> | ||
3145 | 172 | |||
3146 | 173 | <pre class="prettyprint lang-bash"> | ||
3147 | 174 | juju-log "some important text" | ||
3148 | 175 | </pre> | ||
3149 | 176 | |||
3150 | 177 | <p>It accepts a <code>--debug</code> flag which causes the message to be logged | ||
3151 | 178 | at <code>DEBUG</code> level; in all other cases it's logged at <code>INFO</code> | ||
3152 | 179 | level. The <code>-l</code>/<code>--level</code> argument is ignored, and is present | ||
3153 | 180 | only to prevent legacy charms from entirely failing to run; the inability to specify | ||
3154 | 181 | logging levels and targets in more detail is a known | ||
3155 | 182 | <a href="https://bugs.launchpad.net/juju-core/+bug/1223325">bug</a>.</p> | ||
3156 | 183 | </section> | ||
3157 | 184 | |||
3158 | 185 | <section id="unit-get"> | ||
3159 | 186 | <h3>unit-get</h3> | ||
3160 | 187 | |||
3161 | 188 | <p><code>unit-get</code> returns information about the local unit. It accepts a | ||
3162 | 189 | single argument, which must be <code>private-address</code> or | ||
3163 | 190 | <code>public-address</code>. It is not affected by context.</p> | ||
3164 | 191 | |||
3165 | 192 | <pre class="prettyprint"> | ||
3166 | 193 | unit-get private-address | ||
3167 | 194 | 10.0.1.101 | ||
3168 | 195 | </pre> | ||
3169 | 196 | |||
3170 | 197 | <pre class="prettyprint"> | ||
3171 | 198 | unit-get public-address | ||
3172 | 199 | foo.example.com | ||
3173 | 200 | </pre> | ||
3174 | 201 | |||
3175 | 202 | </section> | ||
3176 | 203 | |||
3177 | 204 | <section id="config-get"> | ||
3178 | 205 | <h3>config-get</h3> | ||
3179 | 206 | |||
3180 | 207 | <p><code>config-get</code> returns information about the service configuration (as | ||
3181 | 208 | defined by the charm). If called without arguments, it returns a dictionary | ||
3182 | 209 | containing all config settings that are either explicitly set, or which | ||
3183 | 210 | have a non-nil default value. If the <code>--all</code> flag is passed, it returns | ||
3184 | 211 | a dictionary containing all definied config settings including nil values | ||
3185 | 212 | (for those without defaults). If called with a single argument, it returns | ||
3186 | 213 | the value of that config key. Missing config keys are reported as having a | ||
3187 | 214 | value of nil, and do not return an error.</p> | ||
3188 | 215 | |||
3189 | 216 | <p>Get the interesting bits of the config:</p> | ||
3190 | 217 | <pre class="prettyprint"> | ||
3191 | 218 | config-get | ||
3192 | 219 | |||
3193 | 220 | key: some-value | ||
3194 | 221 | another-key: default-value | ||
3195 | 222 | </pre> | ||
3196 | 223 | <p>Get the whole config including nulls:</p> | ||
3197 | 224 | <pre class="prettyprint"> | ||
3198 | 225 | config-get --all | ||
3199 | 226 | |||
3200 | 227 | key: some-value | ||
3201 | 228 | another-key: default-value | ||
3202 | 229 | no-default: null | ||
3203 | 230 | </pre> | ||
3204 | 231 | <p>Retrieve a specific value:</p> | ||
3205 | 232 | <pre class="prettyprint"> | ||
3206 | 233 | config-get _key_ | ||
3207 | 234 | |||
3208 | 235 | default-value | ||
3209 | 236 | </pre> | ||
3210 | 237 | <p>Get a config setting with no value:</p> | ||
3211 | 238 | <pre class="prettyprint lang-bash"> | ||
3212 | 239 | config-get no-default | ||
3213 | 240 | </pre> | ||
3214 | 241 | <p>Get a config setting that doesn't exist:</p> | ||
3215 | 242 | <pre class="prettyprint lang-bash"> | ||
3216 | 243 | config-get missing-key | ||
3217 | 244 | </pre> | ||
3218 | 245 | <p class = "note"><strong>Note: </strong> The above two examples are not misprints | ||
3219 | 246 | - asking for a value which doesn't exist or has not been set returns nothing and | ||
3220 | 247 | raises no errors.</p> | ||
3221 | 248 | </section> | ||
3222 | 249 | |||
3223 | 250 | <section id="open-port"> | ||
3224 | 251 | <h3>open-port</h3> | ||
3225 | 252 | |||
3226 | 253 | <p><code>open-port</code> marks a port on the local system as appropriate to | ||
3227 | 254 | open, if and when the service is exposed to the outside world. It accepts a single | ||
3228 | 255 | port with an optional protocol, which may be <code>udp</code> or <code>tcp</code>, | ||
3229 | 256 | where <code>tcp</code> is the default.</p> | ||
3230 | 257 | <p>Examples:</p> | ||
3231 | 258 | <p>Open 80/tcp if and when the service is exposed:</p> | ||
3232 | 259 | <pre class="prettyprint lang-bash"> | ||
3233 | 260 | open-port 80 | ||
3234 | 261 | </pre> | ||
3235 | 262 | <p>Open 1234/udp if and when the service is exposed:</p> | ||
3236 | 263 | <pre class="prettyprint lang-bash"> | ||
3237 | 264 | open-port 1234/udp | ||
3238 | 265 | </code></pre> | ||
3239 | 266 | |||
3240 | 267 | <p><code>open-port</code> will not have any effect if the service is not exposed, | ||
3241 | 268 | and may have a somewhat delayed effect even if it is. It accepts and ignores | ||
3242 | 269 | <code>--format</code>, because it doesn't produce any output.</p> | ||
3243 | 270 | |||
3244 | 271 | </section> | ||
3245 | 272 | |||
3246 | 273 | <section id="close-port"> | ||
3247 | 274 | <h3>close-port</h3> | ||
3248 | 275 | <p><code>close-port</code> unmarks a local system port. If the service is not | ||
3249 | 276 | exposed, it has no effect; otherwise the port is marked for imminent closure. It | ||
3250 | 277 | accepts the same flags and arguments as <code>open-port</code>.</p> | ||
3251 | 278 | <p>Examples:</p> | ||
3252 | 279 | <p>Close 1234/udp if it was open:</p> | ||
3253 | 280 | <pre class="prettyprint lang-bash"> | ||
3254 | 281 | close-port 1234/udp | ||
3255 | 282 | </pre> | ||
3256 | 283 | <p>Close port 80 if it was open:</p> | ||
3257 | 284 | <pre class="prettyprint lang-bash"> | ||
3258 | 285 | close-port 80 | ||
3259 | 286 | </pre> | ||
3260 | 287 | </section> | ||
3261 | 288 | |||
3262 | 289 | <section id="relation-set"> | ||
3263 | 290 | <h3>relation-set</h3> | ||
3264 | 291 | |||
3265 | 292 | <p><code>relation-set</code> writes the local unit's settings for some relation. It | ||
3266 | 293 | accepts any number of <code>key=value</code> strings, and an optional <code>-r</code> | ||
3267 | 294 | argument, which defaults to the current relation id. If it's not running in a relation | ||
3268 | 295 | hook, <code>-r</code> needs to be specified. The <code>value</code> part of an argument | ||
3269 | 296 | is not inspected, and is stored directly as a string. Setting an empty string causes | ||
3270 | 297 | the setting to be removed.</p> | ||
3271 | 298 | <p>Examples:</p> | ||
3272 | 299 | <p>Set a pair of values for the local unit in the default relation:</p> | ||
3273 | 300 | <pre class="prettyprint lang-bash"> | ||
3274 | 301 | echo $JUJU_RELATION_ID | ||
3275 | 302 | |||
3276 | 303 | server:3 | ||
3277 | 304 | |||
3278 | 305 | relation-set username=bob password=2db673e81ffa264c | ||
3279 | 306 | </pre> | ||
3280 | 307 | |||
3281 | 308 | <p>Set a pair of values for the local unit in a specific relation:</p> | ||
3282 | 309 | <pre class="prettyprint lang-bash"> | ||
3283 | 310 | relation-set -r server:3 username=jim password=12345 | ||
3284 | 311 | </pre> | ||
3285 | 312 | <p>Clear a value for the local unit in the default relation:</p> | ||
3286 | 313 | <pre class="prettyprint lang-bash"> | ||
3287 | 314 | echo $JUJU_RELATION_ID | ||
3288 | 315 | server:3 | ||
3289 | 316 | relation-set deprecated-or-unused= | ||
3290 | 317 | </pre> | ||
3291 | 318 | |||
3292 | 319 | <p><code>relation-set</code> is the single tool at your disposal for communicating | ||
3293 | 320 | your own configuration to units of related services. At least by convention, the | ||
3294 | 321 | charm that <code>provides</code> an interface is likely to set values, and a charm | ||
3295 | 322 | that <code>requires</code> that interface will read them; but there's nothing | ||
3296 | 323 | forcing this. Whatever information you need to propagate for the remote charm to | ||
3297 | 324 | work must be propagated via relation-set, with the single exception of the | ||
3298 | 325 | <code>private-address</code> key, which is always set before the unit joins.</p> | ||
3299 | 326 | |||
3300 | 327 | <p>You may wish to overwrite the <code>private-address</code> setting, for example | ||
3301 | 328 | if you're writing a charm that serves as a proxy for some external service; but | ||
3302 | 329 | you should in general avoid <em>removing</em> that key, because most charms expect | ||
3303 | 330 | that value to exist unconditionally.</p> | ||
3304 | 331 | |||
3305 | 332 | <p>All values set are stored locally until the hook completes; at that point, | ||
3306 | 333 | if the hook exit code is 0, all changed values will be communicated to the | ||
3307 | 334 | rest of the system, causing -changed hooks to run in all related units.</p> | ||
3308 | 335 | |||
3309 | 336 | <p>There is no way to write settings for any unit other than the local unit; but | ||
3310 | 337 | any hook on the local unit can write settings for any relation the local unit is | ||
3311 | 338 | participating in.</p> | ||
3312 | 339 | |||
3313 | 340 | </section> | ||
3314 | 341 | |||
3315 | 342 | <section id="relation-get"> | ||
3316 | 343 | <h3>relation-get</h3> | ||
3317 | 344 | |||
3318 | 345 | <p><code>relation-get</code> reads the settings of the local unit, or of any | ||
3319 | 346 | remote unit, in a given relation (set with <code>-r</code>, defaulting to the | ||
3320 | 347 | current relation, as in <code>relation-set</code>). The first argument specifies | ||
3321 | 348 | the settings key, and the second the remote unit, which may be omitted if a | ||
3322 | 349 | default is available (that is, when running a relation hook other than -broken).</p> | ||
3323 | 350 | |||
3324 | 351 | <p>If the first argument is omitted, a dictionary of all current keys and values | ||
3325 | 352 | will be printed; all values are always plain strings without any interpretation. | ||
3326 | 353 | If you need to specify a remote unit but want to see all settings, use <code>-</code> | ||
3327 | 354 | for the first argument.</p> | ||
3328 | 355 | |||
3329 | 356 | <p>Get all settings from the default remote unit in the default relation:</p> | ||
3330 | 357 | <pre class="prettyprint lang-bash"> | ||
3331 | 358 | $ echo $JUJU_RELATION_ID | ||
3332 | 359 | db:1 | ||
3333 | 360 | $ echo $JUJU_REMOTE_UNIT | ||
3334 | 361 | mongodb/2 | ||
3335 | 362 | $ relation-get | ||
3336 | 363 | username: jim | ||
3337 | 364 | password: "12345" | ||
3338 | 365 | </pre> | ||
3339 | 366 | <p>Get one setting from the default remote unit in the default relation:</p> | ||
3340 | 367 | <pre class="prettyprint lang-bash"> | ||
3341 | 368 | echo $JUJU_RELATION_ID | ||
3342 | 369 | db:1 | ||
3343 | 370 | |||
3344 | 371 | echo $JUJU_REMOTE_UNIT | ||
3345 | 372 | mongodb/2 | ||
3346 | 373 | |||
3347 | 374 | relation-get username | ||
3348 | 375 | jim | ||
3349 | 376 | </pre> | ||
3350 | 377 | <p>Get all settings from a particular remote unit in a particular relation:</p> | ||
3351 | 378 | <pre class="prettyprint lang-bash"> | ||
3352 | 379 | echo $JUJU_RELATION_ID | ||
3353 | 380 | |||
3354 | 381 | relation-get -r database:7 - mongodb/5 | ||
3355 | 382 | |||
3356 | 383 | username: bob | ||
3357 | 384 | password: 2db673e81ffa264c | ||
3358 | 385 | </pre> | ||
3359 | 386 | |||
3360 | 387 | <p>Note that <code>relation-get</code> produces results that are <em>consistent</em> | ||
3361 | 388 | but not necessarily <em>accurate</em>, in that you will always see settings that:</p> | ||
3362 | 389 | <ul> | ||
3363 | 390 | <li>were accurate at some point in the reasonably recent past | ||
3364 | 391 | <li>are always the same within a single hook run... | ||
3365 | 392 | <li class=" sub"><em>except</em> when inspecting the unit's own relation settings, | ||
3366 | 393 | in which case local changes from <code>relation-set</code> will be seen correctly.</li> | ||
3367 | 394 | </ul> | ||
3368 | 395 | <p>You should never depend upon the presence of any given key in <code>relation-get</code> | ||
3369 | 396 | output. Processing that depends on specific values (other than | ||
3370 | 397 | <code>private-addres</code>) should be restricted to -changed hooks for the relevant | ||
3371 | 398 | unit, and the absence of a remote unit's value should never be treated as an | ||
3372 | 399 | <a href="./authors-hook-errors.html">error</a> in the local unit.</p> | ||
3373 | 400 | |||
3374 | 401 | <p>In practice, it is common and encouraged for -relation-changed hooks to exit | ||
3375 | 402 | early, without error, after inspecting <code>relation-get</code> output and | ||
3376 | 403 | determining it to be inadequate; and for <a href="./authors-hook-kinds.html">all | ||
3377 | 404 | other hooks</a> to be resilient in the face of missing keys, such that | ||
3378 | 405 | -relation-changed hooks will be sufficient to complete all configuration that | ||
3379 | 406 | depends on remote unit settings.</p> | ||
3380 | 407 | |||
3381 | 408 | <p>Settings for remote units already known to have departed remain accessible | ||
3382 | 409 | for the lifetime of the relation.</p> | ||
3383 | 410 | |||
3384 | 411 | <p><code>relation-get</code> currently has a | ||
3385 | 412 | <a href="https://bugs.launchpad.net/juju-core/+bug/1223339">bug</a> that allows units | ||
3386 | 413 | of the same service to see each other's settings outside of a peer relation. Depending | ||
3387 | 414 | on this behaviour is foolish in the extreme: if you need to share settings between | ||
3388 | 415 | units of the same service, always use a peer relation to do so, or you may be | ||
3389 | 416 | seriously inconvenienced when the hole is closed without notice.</p> | ||
3390 | 417 | |||
3391 | 418 | </section> | ||
3392 | 419 | |||
3393 | 420 | <section id="relation-list"> | ||
3394 | 421 | <h3>relation-list</h3> | ||
3395 | 422 | |||
3396 | 423 | <p><code>relation-list</code> accepts the <code>-r</code> flag as above, and | ||
3397 | 424 | outputs the names of every remote unit currently known to be in the relation.</p> | ||
3398 | 425 | <p>Examples:</p> | ||
3399 | 426 | <p>Show all remote units in the current relation</p> | ||
3400 | 427 | <pre class="prettyprint lang-bash"> | ||
3401 | 428 | $ echo $JUJU_RELATION_ID | ||
3402 | 429 | db:1 | ||
3403 | 430 | |||
3404 | 431 | $ relation-list | ||
3405 | 432 | mongodb/0 | ||
3406 | 433 | mongodb/2 | ||
3407 | 434 | mongodb/3 | ||
3408 | 435 | </pre> | ||
3409 | 436 | |||
3410 | 437 | <p>Show all remote units in a specific relation:</p> | ||
3411 | 438 | <pre class="prettyprint lang-bash"> | ||
3412 | 439 | echo $JUJU_RELATION_ID | ||
3413 | 440 | relation-list -r website:2 | ||
3414 | 441 | |||
3415 | 442 | haproxy/0 | ||
3416 | 443 | </pre> | ||
3417 | 444 | |||
3418 | 445 | </section> | ||
3419 | 446 | |||
3420 | 447 | <section id="relation-ids"> | ||
3421 | 448 | <h3>relation-ids</h3> | ||
3422 | 449 | |||
3423 | 450 | <p><code>relation-ids</code> accepts a single argument which, in a relation | ||
3424 | 451 | hook, defaults to the name of the current relation.</p> | ||
3425 | 452 | <p>Examples:</p> | ||
3426 | 453 | <p>Show all relations like the current one:</p> | ||
3427 | 454 | <pre class="prettyprint lang-bash"> | ||
3428 | 455 | $ echo $JUJU_RELATION | ||
3429 | 456 | server | ||
3430 | 457 | $ relation-ids | ||
3431 | 458 | server:1 | ||
3432 | 459 | server:7 | ||
3433 | 460 | server:9 | ||
3434 | 461 | </pre> | ||
3435 | 462 | <p>Show all relations with the given name:</p> | ||
3436 | 463 | <pre class="prettyprint lang-bash"> | ||
3437 | 464 | $ echo $JUJU_RELATION_ID | ||
3438 | 465 | |||
3439 | 466 | $ relation-ids reverseproxy | ||
3440 | 467 | reverseproxy:3 | ||
3441 | 468 | </pre> | ||
3442 | 469 | |||
3443 | 470 | <p>Note again that all commands that produce output accept <code>--format json</code> | ||
3444 | 471 | and <code>--format yaml</code>, and you may consider it smarter to use those for | ||
3445 | 472 | clarity's sake than to depend on the default <code>smart</code> format. | ||
3446 | 473 | </section> | ||
3447 | 474 | </article> | ||
3448 | 475 | <!--Postamble--> | ||
3449 | 476 | </div> | ||
3450 | 477 | </div> | ||
3451 | 478 | </section> | ||
3452 | 479 | </div> | ||
3453 | 480 | </div> | ||
3454 | 481 | <!--End-Postamble--> | ||
3455 | 482 | <!--Footer--> | ||
3456 | 483 | <footer class="global clearfix" role="contentinfo"> | ||
3457 | 484 | <nav role="navigation"> | ||
3458 | 485 | <div class="footer-a"> | ||
3459 | 486 | <div class="clearfix"> | ||
3460 | 487 | <ul> | ||
3461 | 488 | <li> | ||
3462 | 489 | <h2><a href="/">Juju</a></h2> | ||
3463 | 490 | <ul> | ||
3464 | 491 | <li><a href="/charms">Charms</a></li> | ||
3465 | 492 | <li><a href="/features">Features</a></li> | ||
3466 | 493 | <li><a href="/deployment">Deployment</a></li> | ||
3467 | 494 | </ul> | ||
3468 | 495 | </li> | ||
3469 | 496 | <li> | ||
3470 | 497 | <h2><a href="/resources">Resources</a></h2> | ||
3471 | 498 | <ul> | ||
3472 | 499 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
3473 | 500 | <li><a href="/docs/">Documentation</a></li> | ||
3474 | 501 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
3475 | 502 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
3476 | 503 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
3477 | 504 | <li><a href="/resources/videos/">Videos</a></li> | ||
3478 | 505 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
3479 | 506 | </ul> | ||
3480 | 507 | </li> | ||
3481 | 508 | <li> | ||
3482 | 509 | <h2><a href="/community">Community</a></h2> | ||
3483 | 510 | <ul> | ||
3484 | 511 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
3485 | 512 | <li><a href="/events/">Events</a></li> | ||
3486 | 513 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
3487 | 514 | <li><a href="/community/charmers/">Charmers</a></li> | ||
3488 | 515 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
3489 | 516 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
3490 | 517 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
3491 | 518 | </ul> | ||
3492 | 519 | </li> | ||
3493 | 520 | <li> | ||
3494 | 521 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
3495 | 522 | <ul> | ||
3496 | 523 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
3497 | 524 | <li><a href="/download/">Download Juju</a></li> | ||
3498 | 525 | </ul> | ||
3499 | 526 | </li> | ||
3500 | 527 | </ul> | ||
3501 | 528 | </div> | ||
3502 | 529 | </div> | ||
3503 | 530 | </nav> | ||
3504 | 531 | <div class="legal clearfix"> | ||
3505 | 532 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
3506 | 533 | </div> | ||
3507 | 534 | </footer> | ||
3508 | 535 | |||
3509 | 536 | <!--End-Footer--> | ||
3510 | 537 | <!--Scripts--> | ||
3511 | 538 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
3512 | 539 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
3513 | 540 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
3514 | 541 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
3515 | 542 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
3516 | 543 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
3517 | 544 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
3518 | 545 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
3519 | 546 | <!-- google analytics --> | ||
3520 | 547 | <script> | ||
3521 | 548 | var _gaq = _gaq || []; | ||
3522 | 549 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
3523 | 550 | _gaq.push(['_trackPageview']); | ||
3524 | 551 | |||
3525 | 552 | (function() { | ||
3526 | 553 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
3527 | 554 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
3528 | 555 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
3529 | 556 | })(); | ||
3530 | 557 | </script> | ||
3531 | 558 | <!--End-Scripts--> | ||
3532 | 559 | |||
3533 | 560 | </body></html> | ||
3534 | 561 | |||
3535 | 0 | 562 | ||
3536 | === added file 'htmldocs/authors-hook-errors.html' | |||
3537 | --- htmldocs/authors-hook-errors.html 1970-01-01 00:00:00 +0000 | |||
3538 | +++ htmldocs/authors-hook-errors.html 2013-10-09 20:07:46 +0000 | |||
3539 | @@ -0,0 +1,194 @@ | |||
3540 | 1 | <!DOCTYPE html> | ||
3541 | 2 | <html> | ||
3542 | 3 | <head> | ||
3543 | 4 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||
3544 | 5 | <title>Juju Documentation - Hook Errors</title> | ||
3545 | 6 | <link href='https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono' rel='stylesheet' type='text/css' /> | ||
3546 | 7 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css" /> | ||
3547 | 8 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/960.css" /> | ||
3548 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/base.css" /> | ||
3549 | 10 | <link rel="stylesheet" type="text/css" media="screen" href="//juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css" /> | ||
3550 | 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' /> | ||
3551 | 12 | <link href="css/main.css?1375975745" rel="stylesheet" type="text/css"/> | ||
3552 | 13 | |||
3553 | 14 | <!--[if lt IE 9]> | ||
3554 | 15 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
3555 | 16 | <![endif]--> | ||
3556 | 17 | </head> | ||
3557 | 18 | <body class="resources"> | ||
3558 | 19 | <header class="global clearfix" role="banner"> | ||
3559 | 20 | <div class="header-navigation"> | ||
3560 | 21 | <div> | ||
3561 | 22 | <nav role="navigation"> | ||
3562 | 23 | <ul> | ||
3563 | 24 | <li class="page_item page-item-6"><a href="https://juju.ubuntu.com/">Home</a></li> | ||
3564 | 25 | <li class="page_item page-item-7"><a href="https://juju.ubuntu.com/get-started/">Get started</a></li> | ||
3565 | 26 | <li class="page_item page-item-9 current_page_item"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
3566 | 27 | <li class="page_item page-item-13"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
3567 | 28 | <li class="page_item page-item-3688"><a href="https://juju.ubuntu.com/charm-store/">Charm Store</a></li> | ||
3568 | 29 | <li class="page_item page-item-3691"><a href="https://juju.ubuntu.com/events/">Events</a></li> | ||
3569 | 30 | <li class="page_item page-item-4474"><a href="https://juju.ubuntu.com/charm-championship/">Charm Championship</a></li> | ||
3570 | 31 | <li class="page_item page-item-4249"><a href="https://juju.ubuntu.com/survey/">Survey</a></li> | ||
3571 | 32 | <li> | ||
3572 | 33 | <form id="form-search" method="get" action="https://juju.ubuntu.com/"> | ||
3573 | 34 | <fieldset> | ||
3574 | 35 | <input id="input-search" type="text" name="s" value="Search" /> | ||
3575 | 36 | </fieldset> | ||
3576 | 37 | </form> | ||
3577 | 38 | </li> | ||
3578 | 39 | </ul> | ||
3579 | 40 | </nav> | ||
3580 | 41 | </div> | ||
3581 | 42 | </div> | ||
3582 | 43 | <div class="header-content"> | ||
3583 | 44 | <div class="clearfix"> | ||
3584 | 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"> | ||
3585 | 46 | <div class="header-navigation-secondary"></div> | ||
3586 | 47 | <div class="header-image"></div> | ||
3587 | 48 | <h1>Resources</h1> | ||
3588 | 49 | <h2>A collection of some of the most important online references for Juju users and developers.</h2> | ||
3589 | 50 | </div> | ||
3590 | 51 | </div> | ||
3591 | 52 | </header> | ||
3592 | 53 | |||
3593 | 54 | <section id="content" class="container-12"> | ||
3594 | 55 | <div class="grid-12 doc-container"> | ||
3595 | 56 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
3596 | 57 | <div class="grid-9 doc-content"> | ||
3597 | 58 | <article> | ||
3598 | 59 | |||
3599 | 60 | |||
3600 | 61 | <section id="hook-errors"> | ||
3601 | 62 | <h1>Hook errors</h1> | ||
3602 | 63 | |||
3603 | 64 | <p>If any of your hooks returns a non-zero exit code, juju will stop managing the | ||
3604 | 65 | unit directly and will wait for user intervention. This is a Bad Thing, and you | ||
3605 | 66 | should make every effort to avoid it, because the average user may not be in a | ||
3606 | 67 | position to diagnose the fault with any great degree of sophistication.</p> | ||
3607 | 68 | |||
3608 | 69 | <p>So, in general, you should write your hooks as robustly as possible: if an | ||
3609 | 70 | operation suffers a possibly-transient failure, it's wise to wait a moment and | ||
3610 | 71 | retry a couple of times, to avoid needlessly bothering the user with a decision | ||
3611 | 72 | or call to action that they're not necessarily equipped to make.</p> | ||
3612 | 73 | |||
3613 | 74 | <p>However, you will no doubt encounter errors on occasion -- in particular, if | ||
3614 | 75 | the unit agent is aborted while it's running a hook, it'll set an error status | ||
3615 | 76 | for that hook when it comes back up. You will in that case have to deal with | ||
3616 | 77 | users' potentially underinformed responses to those errors.</p> | ||
3617 | 78 | </section> | ||
3618 | 79 | |||
3619 | 80 | <section id="error-status"> | ||
3620 | 81 | <h2>Error status</h2> | ||
3621 | 82 | |||
3622 | 83 | <p>When a unit agent sets an error status, it stops running hooks and relinquishes | ||
3623 | 84 | control over the charm directory. This means that it's generally safe to | ||
3624 | 85 | <code>juju ssh</code> into the unit and use it as though you were the sole | ||
3625 | 86 | administrator; juju will only take back control of the directory when explicitly | ||
3626 | 87 | requested, in response to either <code>juju resolved</code> or | ||
3627 | 88 | <code>juju upgrade-charm --force</code>. | ||
3628 | 89 | <ul> | ||
3629 | 90 | <li><code>juju resolved</code> causes the unit to unblock itself and continue | ||
3630 | 91 | as though the hook had completed successfuly. The ideal charm will be aware of | ||
3631 | 92 | this possibility and will therefore trust information from its | ||
3632 | 93 | <a href="./authors-hook-environment.html">environment</a> to be more recent and | ||
3633 | 94 | correct than anything it may have previously have recorded in the local | ||
3634 | 95 | <a href="./authors-charm-contents.html">charm directory</a>.</li> | ||
3635 | 96 | |||
3636 | 97 | <li><code>juju resolved --retry</code> reverts the charm directory's contents | ||
3637 | 98 | to whatever they were at the start of the failed hook, and runs the hook again | ||
3638 | 99 | exactly as before. This, in combination with the | ||
3639 | 100 | <a href="./authors-hook-debug.html">debug-hooks</a> command, is your main entry | ||
3640 | 101 | point for investigating an error in detail. If the hook fails again when retried, | ||
3641 | 102 | it will set an error as before and wait again for user resolution.</li> | ||
3642 | 103 | |||
3643 | 104 | <li><code>juju upgrade-charm --force</code> merges into the charm directory the | ||
3644 | 105 | contents of the newer charm version, and continues blocking in the original hook | ||
3645 | 106 | error state. Each time a new upgrade is forced, the charm directory is rolled | ||
3646 | 107 | back to the state from which it was originally upgraded before proceeding; this | ||
3647 | 108 | means that a forced upgrade back to the original charm will always be a no-op, | ||
3648 | 109 | regardless of what other upgrade attempts have been made in the interim.</li> | ||
3649 | 110 | </ul> | ||
3650 | 111 | <p>Once you have issued one of the above commands, the charm directory should | ||
3651 | 112 | once again be treated as inaccessible.</p> | ||
3652 | 113 | </section> | ||
3653 | 114 | |||
3654 | 115 | <section id="upgrade-errors"> | ||
3655 | 116 | <h2>Charm upgrade errors</h2> | ||
3656 | 117 | |||
3657 | 118 | <p>Finally, there's another reason a unit might set an error status: a | ||
3658 | 119 | <a href="./authors-charm-upgrades.html">charm upgrade</a> conflict, which | ||
3659 | 120 | should never happen except during development.</p> | ||
3660 | 121 | |||
3661 | 122 | <p>They can be resolved either by forcing an upgrade to a different charm version, | ||
3662 | 123 | or by manually resolving the git conflicts in the charm directory and running | ||
3663 | 124 | <code>juju resolved</code> to cause the unit agent to continue.</p> | ||
3664 | 125 | </section> | ||
3665 | 126 | |||
3666 | 127 | |||
3667 | 128 | </article> | ||
3668 | 129 | </div> | ||
3669 | 130 | </div> | ||
3670 | 131 | </section> | ||
3671 | 132 | <div class="shadow"></div> | ||
3672 | 133 | <footer class="global clearfix" role="contentinfo"> | ||
3673 | 134 | <div class="row"> | ||
3674 | 135 | <div class="inner-wrapper"> | ||
3675 | 136 | <nav role="navigation" class="clearfix"> | ||
3676 | 137 | <ul class="footer-a"> | ||
3677 | 138 | <li class="grid-3 first-col"> | ||
3678 | 139 | <h4><a href="/get-started">Get started</a></h4> | ||
3679 | 140 | <ul> | ||
3680 | 141 | <li class="page_item page-item-20"><a href="https://juju.ubuntu.com/get-started/local/">Local</a></li> | ||
3681 | 142 | <li class="page_item page-item-22"><a href="https://juju.ubuntu.com/get-started/amazon/">Amazon Web Services</a></li> | ||
3682 | 143 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/get-started/hp-cloud/">HP Cloud</a></li> | ||
3683 | 144 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/get-started/rackspace/">Rackspace</a></li> | ||
3684 | 145 | <li class="page_item page-item-3596"><a href="https://juju.ubuntu.com/get-started/openstack/">Openstack</a></li> | ||
3685 | 146 | <li class="page_item page-item-3600"><a href="https://juju.ubuntu.com/get-started/maas/">MAAS</a></li> | ||
3686 | 147 | </ul> | ||
3687 | 148 | </li> | ||
3688 | 149 | <li class="grid-3"> | ||
3689 | 150 | <h4><a href="/resources">Resources</a></h4> | ||
3690 | 151 | <ul> | ||
3691 | 152 | <li><a href="http://juju.ubuntu.com/docs">Documentation</a></li> | ||
3692 | 153 | <li><a href="/resources/videos/">Videos</a></li> | ||
3693 | 154 | <li><a href="http://uistage.jujucharms.com:8080/">Juju GUI demo site</a></li> | ||
3694 | 155 | </ul> | ||
3695 | 156 | </li> | ||
3696 | 157 | <li class="grid-3"> | ||
3697 | 158 | <h4><a href="/community">Community</a></h4> | ||
3698 | 159 | <ul> | ||
3699 | 160 | <li class="page_item page-item-28"><a href="https://juju.ubuntu.com/community/juju-blog/">Juju Blog</a></li> | ||
3700 | 161 | <li class="page_item page-item-4262"><a href="https://juju.ubuntu.com/community/weekly-charm-meeting/">Weekly Charm Meeting</a></li> | ||
3701 | 162 | <li class="page_item page-item-4036"><a href="https://juju.ubuntu.com/community/charmers/">Charmers</a></li> | ||
3702 | 163 | <li><a href="https://lists.ubuntu.com/mailman/listinfo/juju">Mailing List</a></li> | ||
3703 | 164 | <li><a href="http://webchat.freenode.net/?channels=juju">Chat</a></li> | ||
3704 | 165 | <li><a href="http://askubuntu.com/questions/tagged/juju?sort=faq&pagesize=50">FAQ</a></li> | ||
3705 | 166 | </ul> | ||
3706 | 167 | </li> | ||
3707 | 168 | <li class="grid-3 last-col"> | ||
3708 | 169 | <h4><a href="https://launchpad.net/juju">Code</a></h4> | ||
3709 | 170 | <ul> | ||
3710 | 171 | <li><a href="https://launchpad.net/juju-core">Juju Core</a></li> | ||
3711 | 172 | <li><a href="https://launchpad.net/charms">Charms</a></li> | ||
3712 | 173 | </ul> | ||
3713 | 174 | </li> | ||
3714 | 175 | </ul> | ||
3715 | 176 | </nav> | ||
3716 | 177 | </div> | ||
3717 | 178 | </div> | ||
3718 | 179 | <div class="row no-border"> | ||
3719 | 180 | <div class="legal inner-wrapper"> | ||
3720 | 181 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.</p> | ||
3721 | 182 | <p><a href="https://bugs.launchpad.net/juju-website/+filebug">Report a bug on this site</a></p> | ||
3722 | 183 | </div> | ||
3723 | 184 | </div> | ||
3724 | 185 | </footer> | ||
3725 | 186 | |||
3726 | 187 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
3727 | 188 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
3728 | 189 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
3729 | 190 | <script type="text/javascript" src="js/main.js"></script> | ||
3730 | 191 | <script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script> | ||
3731 | 192 | </body> | ||
3732 | 193 | </html> | ||
3733 | 194 | |||
3734 | 0 | 195 | ||
3735 | === added file 'htmldocs/authors-hook-kinds.html' | |||
3736 | --- htmldocs/authors-hook-kinds.html 1970-01-01 00:00:00 +0000 | |||
3737 | +++ htmldocs/authors-hook-kinds.html 2013-10-09 20:07:46 +0000 | |||
3738 | @@ -0,0 +1,402 @@ | |||
3739 | 1 | <!DOCTYPE html> | ||
3740 | 2 | <html> | ||
3741 | 3 | <!--Head--> | ||
3742 | 4 | <head> | ||
3743 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
3744 | 6 | <title>Juju Documentation</title> | ||
3745 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
3746 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
3747 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
3748 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
3749 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
3750 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
3751 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
3752 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
3753 | 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"> | ||
3754 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
3755 | 17 | |||
3756 | 18 | <!--[if lt IE 9]> | ||
3757 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
3758 | 20 | <![endif]--> | ||
3759 | 21 | </head> | ||
3760 | 22 | <!--End-Head--> | ||
3761 | 23 | |||
3762 | 24 | |||
3763 | 25 | <body class="resources"> | ||
3764 | 26 | <!--Header--> | ||
3765 | 27 | |||
3766 | 28 | <header class="banner global" role="banner"> | ||
3767 | 29 | <nav role="navigation" class="nav-primary nav-right"> | ||
3768 | 30 | <div class="logo"> | ||
3769 | 31 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
3770 | 32 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
3771 | 33 | <span>Juju</span> | ||
3772 | 34 | </a> | ||
3773 | 35 | </div> | ||
3774 | 36 | <ul> | ||
3775 | 37 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
3776 | 38 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
3777 | 39 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
3778 | 40 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
3779 | 41 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
3780 | 42 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
3781 | 43 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
3782 | 44 | </ul> | ||
3783 | 45 | <div id="box-search"> | ||
3784 | 46 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
3785 | 47 | <label class="off-left" for="s">Search:</label> | ||
3786 | 48 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
3787 | 49 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
3788 | 50 | </form> | ||
3789 | 51 | </div> | ||
3790 | 52 | </nav> | ||
3791 | 53 | </header> | ||
3792 | 54 | <!--End-Header--> | ||
3793 | 55 | <!--Preamble--> | ||
3794 | 56 | <div class="wrapper"> | ||
3795 | 57 | <div id="main-content" class="inner-wrapper" role="main"> | ||
3796 | 58 | <div class="row no-border"> | ||
3797 | 59 | <div class="header-navigation-secondary"></div> | ||
3798 | 60 | <h2 class="pagetitle">Juju documentation</h2> | ||
3799 | 61 | </div> | ||
3800 | 62 | <section id="content" class="container-12"> | ||
3801 | 63 | <div class="grid-12 doc-container"> | ||
3802 | 64 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
3803 | 65 | <div class="grid-9 doc-content"> | ||
3804 | 66 | <!--End-Preamble--> | ||
3805 | 67 | <article> | ||
3806 | 68 | <section id="charm-hooks"> | ||
3807 | 69 | <h1>Charm hooks</h1> | ||
3808 | 70 | |||
3809 | 71 | <p>A service unit's direct action is entirely defined by its charm's hooks. Hooks | ||
3810 | 72 | are executable files in a charm's <code>hooks</code> directory; hooks with particular | ||
3811 | 73 | names (see below) will be invoked by the juju unit agent at particular times, and thereby cause | ||
3812 | 74 | changes to the world.</p> | ||
3813 | 75 | |||
3814 | 76 | <p>Whenever a hook-worthy event takes place, the unit agent first checks whether | ||
3815 | 77 | that hook is being <a href="./authors-hook-debug.html">debugged</a>, and if so | ||
3816 | 78 | hands over control to the user. Otherwise, it tries to find a hook with precisely | ||
3817 | 79 | the right name. If the hook doesn't exist, the agent continues without complaint; | ||
3818 | 80 | if it does, it is invoked without arguments in a specific | ||
3819 | 81 | <a href="./authors-hook-environment.html">environment</a>, and its output is written | ||
3820 | 82 | to the unit agent's log. If it returns a non-zero exit code, the agent enters an | ||
3821 | 83 | <a href="./authors-hook-errors.html">error state</a> and awaits user intervention.</p> | ||
3822 | 84 | |||
3823 | 85 | <p>The agent will also enter an error state if the unit agent process is aborted | ||
3824 | 86 | during hook execution.</p> | ||
3825 | 87 | |||
3826 | 88 | <p>There are two types of hooks, described in more detail in the following sections.</p> | ||
3827 | 89 | |||
3828 | 90 | <p class = "note"><strong>Note: </strong>None of the unit or relation hooks are required; if you don't implement a hook, | ||
3829 | 91 | it just doesn't get run. When a hook event occurs, Juju will look for the corresponding hook file to execute, but if it finds none, will continue running without generating an error.</p> | ||
3830 | 92 | </section> | ||
3831 | 93 | |||
3832 | 94 | <section id="unit-hooks"> | ||
3833 | 95 | <h2>Unit hooks</h2> | ||
3834 | 96 | |||
3835 | 97 | <p>There are 5 "unit hooks" with predefined names that can be implemented | ||
3836 | 98 | by any charm:</p> | ||
3837 | 99 | <ul> | ||
3838 | 100 | <li>install</li> | ||
3839 | 101 | <li>config-changed</li> | ||
3840 | 102 | <li>start</li> | ||
3841 | 103 | <li>upgrade-charm</li> | ||
3842 | 104 | <li>stop</li> | ||
3843 | 105 | </ul> | ||
3844 | 106 | |||
3845 | 107 | <p>For every relation defined by a charm, an additional 4 "relation hooks" | ||
3846 | 108 | can be implemented, named after the charm relation:</p> | ||
3847 | 109 | <ul> | ||
3848 | 110 | <li><name>-relation-joined</li> | ||
3849 | 111 | <li><name>-relation-changed</li> | ||
3850 | 112 | <li><name>-relation-departed</li> | ||
3851 | 113 | <li><name>-relation-broken</li> | ||
3852 | 114 | </ul> | ||
3853 | 115 | <p>None of the unit or relation hooks are required; if you don't implement a hook, | ||
3854 | 116 | it just doesn't get run, except when debugging. When a hook event occurs, Juju will look for the corresponding hook file to execute, but if it finds none, will continue running without generating an error.</p> | ||
3855 | 117 | </section> | ||
3856 | 118 | |||
3857 | 119 | <p>The unit hooks are run under the following circumstances.</p> | ||
3858 | 120 | </section> | ||
3859 | 121 | |||
3860 | 122 | <section id="hook-install"> | ||
3861 | 123 | <h3>install</h3> | ||
3862 | 124 | |||
3863 | 125 | <p><code>install</code> runs just once, before any other hook. It should be used to | ||
3864 | 126 | perform one-time setup operations only.</p> | ||
3865 | 127 | </section> | ||
3866 | 128 | |||
3867 | 129 | <section id="hook-config-changed"> | ||
3868 | 130 | <h3>config-changed</h3> | ||
3869 | 131 | |||
3870 | 132 | <p><code>config-changed</code> runs in several different situations.</p> | ||
3871 | 133 | <ul> | ||
3872 | 134 | <li>immediately after "install"</li> | ||
3873 | 135 | <li>immediately after "upgrade-charm"</li> | ||
3874 | 136 | <li>at least once when the unit agent is restarted (but, if the unit is in | ||
3875 | 137 | an <a href="./authors-hook-errors.html">error state</a>, it won't be run | ||
3876 | 138 | until after the error state is cleared).</li> | ||
3877 | 139 | </ul> | ||
3878 | 140 | <p>It cannot assume that the software has already been started; it should not | ||
3879 | 141 | start stopped software, but should (if appropriate) restart running software | ||
3880 | 142 | to take configuration changes into account.</p> | ||
3881 | 143 | </section> | ||
3882 | 144 | |||
3883 | 145 | <section id="hook-start"> | ||
3884 | 146 | <h3>start</h3> | ||
3885 | 147 | <p><code>start</code> runs immediately after the first <code>config-changed</code> | ||
3886 | 148 | hook. It should be used to ensure the charm's software is running. Note that the | ||
3887 | 149 | charm's software should be configured so as to persist through reboots without further | ||
3888 | 150 | intervention on juju's part. | ||
3889 | 151 | </section> | ||
3890 | 152 | |||
3891 | 153 | <section id="hook-upgrade-charm"> | ||
3892 | 154 | <h3>upgrade-charm</h3> | ||
3893 | 155 | |||
3894 | 156 | <p><code>upgrade-charm</code> runs immediately after any | ||
3895 | 157 | <a href="./authors-charm-upgrades.html">upgrade</a> operation that does <em>not</em> | ||
3896 | 158 | itself interrupt an existing <a href="./authors-hook-errors.html">error state.</a>. It | ||
3897 | 159 | should be used to reconcile local state written by some other version of the charm into | ||
3898 | 160 | whatever form it needs to take to be manipulated by the current version.</p> | ||
3899 | 161 | |||
3900 | 162 | <p>While the forced upgrade functionality is intended as a developer tool, and is | ||
3901 | 163 | not generally suitable for end users, it's somewhat optimistic to depend on the | ||
3902 | 164 | functionality never being abused. In light of this, if you need to run an | ||
3903 | 165 | <code>upgrade-charm</code> hook before your other hooks will work correctly, | ||
3904 | 166 | it may be wise to preface all your other hooks with a quick call to your | ||
3905 | 167 | (idempotent)<code>upgrade-charm</code>.</p> | ||
3906 | 168 | </section> | ||
3907 | 169 | |||
3908 | 170 | <section id="hook-stop"> | ||
3909 | 171 | <h3>stop</h3> | ||
3910 | 172 | |||
3911 | 173 | <p><code>stop</code> runs immediately before the end of the unit's destruction | ||
3912 | 174 | sequence. It should be used to ensure that the charm's software is not running, and | ||
3913 | 175 | will not start again on reboot.</p> | ||
3914 | 176 | </section> | ||
3915 | 177 | |||
3916 | 178 | <section id="relation-hooks"> | ||
3917 | 179 | <h2>Relation hooks</h2> | ||
3918 | 180 | |||
3919 | 181 | <p>Units will only participate in relations after they're been started, and before | ||
3920 | 182 | they've been stopped. Within that time window, the unit may participate in several | ||
3921 | 183 | different relations at a time, <em>including</em> multiple relations with the | ||
3922 | 184 | same name.</p> | ||
3923 | 185 | |||
3924 | 186 | <p>To illustrate, consider a database service that will be used by multiple client | ||
3925 | 187 | services. Units of a single client service will surely want to connect to, and | ||
3926 | 188 | use, the same database; but if units of another client service were to use that | ||
3927 | 189 | same database, the consequences could be catastrophic for all concerned.</p> | ||
3928 | 190 | |||
3929 | 191 | <p>If juju respected the <code>limit</code> field in relation | ||
3930 | 192 | <a href="./authors-charm-metadata.html">metadata</a>, it would be possible | ||
3931 | 193 | to work around this, but it's not a high-priority | ||
3932 | 194 | <a href="https://bugs.launchpad.net/bugs/1089297">bug</a>: most provider services | ||
3933 | 195 | <em>should</em> be able to handle multiple requirers anyway; and most requirers will | ||
3934 | 196 | only be connected to one provider anyway.</p> | ||
3935 | 197 | |||
3936 | 198 | <p>When a unit running a given charm participates in a given relation, it runs at | ||
3937 | 199 | least three hooks for every remote unit it becomes aware of in that relation.</p> | ||
3938 | 200 | </section> | ||
3939 | 201 | |||
3940 | 202 | <section id="hook-relation-joined"> | ||
3941 | 203 | <h3><name>-relation-joined</h3> | ||
3942 | 204 | |||
3943 | 205 | <p><code><name>-relation-joined</code> is run once only, when that remote | ||
3944 | 206 | unit is first observed by the unit. It should be used to <code>relation-set</code> any | ||
3945 | 207 | local unit settings that can be determined using no more than the name of the joining | ||
3946 | 208 | unit and the remote <code>private-address</code> setting, which is always available | ||
3947 | 209 | when the relation is created and is by convention not deleted.</p> | ||
3948 | 210 | |||
3949 | 211 | <p>You should not depend upon any other relation settings in the -joined hook | ||
3950 | 212 | because they're not guaranteed to be present; if you need more information | ||
3951 | 213 | you should wait for a -changed hook that presents the right information.</p> | ||
3952 | 214 | </section> | ||
3953 | 215 | |||
3954 | 216 | <section id="hook-relation-changed"> | ||
3955 | 217 | <h3><name>-relation-changed</h3> | ||
3956 | 218 | |||
3957 | 219 | <p><code><name>-relation-changed</code> is always run once, after -joined, and | ||
3958 | 220 | will subsequently be run whenever that remote unit changes its settings for the | ||
3959 | 221 | relation. It should be the <em>only</em> hook that <em>relies</em> upon remote relation | ||
3960 | 222 | settings from <code>relation-get</code>, and it should <em>not</em> error if the | ||
3961 | 223 | settings are incomplete: you can guarantee that when the remote unit changes its | ||
3962 | 224 | settings, the hook will be run again.</p> | ||
3963 | 225 | |||
3964 | 226 | <p>The settings that you can get, and that you should set, are determined by | ||
3965 | 227 | the relation's <a href="./authors-charm-interfaces.html">interface</a>.</p> | ||
3966 | 228 | </section> | ||
3967 | 229 | |||
3968 | 230 | <section id="hook-relation-departed"> | ||
3969 | 231 | <h3><name>-relation-departed</h3> | ||
3970 | 232 | |||
3971 | 233 | <p><code><name>-relation-departed</code> is run once only, when the remote unit | ||
3972 | 234 | is known to be leaving the relation; it will only run once at least one -changed has | ||
3973 | 235 | been run, and after -departed has run, no further -changeds will be run. This should | ||
3974 | 236 | be used to remove all references to the remote unit, because there's no guarantee that | ||
3975 | 237 | it's still part of the system; it's perfectly probable (although not guaranteed) that | ||
3976 | 238 | the system running that unit has already shut down.</p> | ||
3977 | 239 | |||
3978 | 240 | <p>When a unit's own participation in a relation is known to be ending, the unit | ||
3979 | 241 | agent continues to uphold the ordering guarantees above; but within those | ||
3980 | 242 | constraints, it will run the fewest possible hooks to notify the charm of the | ||
3981 | 243 | departure of each individual remote unit.</p> | ||
3982 | 244 | |||
3983 | 245 | <p>Once all necessary -departed hooks have been run for such a relation, the unit | ||
3984 | 246 | agent will run the final relation hook:</p> | ||
3985 | 247 | </section> | ||
3986 | 248 | |||
3987 | 249 | <section id="hook-relation-broken"> | ||
3988 | 250 | <h3><name>-relation-broken</h3> | ||
3989 | 251 | |||
3990 | 252 | <p><code><name>-relation-broken</code> indicates that the current relation is | ||
3991 | 253 | no longer valid, and that the charm's software must be configured as though the | ||
3992 | 254 | relation had never existed. It will only be called after every necessary -departed | ||
3993 | 255 | hook has been run; if it's being executed, you can be sure that no remote units are | ||
3994 | 256 | currently known locally.</p> | ||
3995 | 257 | |||
3996 | 258 | <p>It is important to note that the -broken hook might run even if no other units | ||
3997 | 259 | have ever joined the relation. This is not a bug: even if no remote units have ever | ||
3998 | 260 | joined, the fact of the unit's participation can be detected in other hooks via the | ||
3999 | 261 | <code>relation-ids</code> tool, and the -broken hook needs to execute to give the | ||
4000 | 262 | charm an opportunity to clean up any optimistically-generated configuration.</p> | ||
4001 | 263 | |||
4002 | 264 | <p>And, again, it's important to internalise the fact that there may be multiple | ||
4003 | 265 | runtime relations in play with the same name, and that they're independent: | ||
4004 | 266 | one -broken hook does not mean that <em>every</em> such relation is broken.</p> | ||
4005 | 267 | </section> | ||
4006 | 268 | |||
4007 | 269 | <section id="writing-hooks"> | ||
4008 | 270 | <h2>Writing hooks</h2> | ||
4009 | 271 | |||
4010 | 272 | <p>If you follow the <a href="./authors-charm-writing.html">tutorial</a>, you'll | ||
4011 | 273 | get a good sense of the basics. To fill out your knowledge, you'll want to study | ||
4012 | 274 | the hook <a href="./authors-hook-environment.html">environment and tools</a>, and | ||
4013 | 275 | to experiment with <a href="./authors-hook-debug.html">debug-hooks</a>.</p> | ||
4014 | 276 | |||
4015 | 277 | <p>Independent of the nuts and bolts, though, good hooks display a number of | ||
4016 | 278 | useful high-level properties:</p> | ||
4017 | 279 | <ul> | ||
4018 | 280 | <li>They are <em>idempotent</em>: that is to say that there should be no | ||
4019 | 281 | observable difference between running a hook once, and running it N times | ||
4020 | 282 | in a row. If this property does not hold, you are likely to be making your | ||
4021 | 283 | own life unnecesarily difficult: apart from anything else, the average user's | ||
4022 | 284 | most likely first response to a failed hook will be to try to run it again | ||
4023 | 285 | (if they don't just skip it).</li> | ||
4024 | 286 | |||
4025 | 287 | <li>They are <em>easy to read</em> and understand. It's tempting to write a | ||
4026 | 288 | single file that does everything, and which just calls different functions | ||
4027 | 289 | internally depending on the value of <code>argv[0]</code>, and to symlink that | ||
4028 | 290 | one file for every hook; but such structures quickly become unwieldy.<br /> | ||
4029 | 291 | The time taken to write a library, separate from the hooks, is very likely | ||
4030 | 292 | to be well spent: it lets you write single hooks that are clear and focused, | ||
4031 | 293 | and insulates the maintainer from irrelevant details.</li> | ||
4032 | 294 | |||
4033 | 295 | <li>Where possible, they reuse | ||
4034 | 296 | <a href="https://launchpad.net/charm-tools">common code</a> already written to | ||
4035 | 297 | ease or solve common use cases.</li> | ||
4036 | 298 | |||
4037 | 299 | <li>They do not return <a href="./authors-hook-errors.html">errors</a> unless | ||
4038 | 300 | there is a good reason to believe that they cannot be resolved without user | ||
4039 | 301 | intervention. Doing so is an admission of defeat: a user who sees your charm | ||
4040 | 302 | returning an error state is unlikely to have the specific expertise necessary | ||
4041 | 303 | to resolve it. If you have to return an error, please be sure to at least write | ||
4042 | 304 | any context you can to the log before you do so.</li> | ||
4043 | 305 | |||
4044 | 306 | <li>They write only <em>very</em> sparingly to the | ||
4045 | 307 | <a href="./authors-charm-contents.html">charm directory</a>.</li> | ||
4046 | 308 | </ul> | ||
4047 | 309 | |||
4048 | 310 | <p>We recommend you also familiarize yourself with the | ||
4049 | 311 | <a href="./authors-charm-best-practice.html">best practices</a> and, if you | ||
4050 | 312 | plan to distribute your charm, the | ||
4051 | 313 | <a href="./authors-charm-policy.html">charm store policy</a>.</p> | ||
4052 | 314 | </section> | ||
4053 | 315 | </article> | ||
4054 | 316 | <!--Postamble--> | ||
4055 | 317 | </div> | ||
4056 | 318 | </div> | ||
4057 | 319 | </section> | ||
4058 | 320 | </div> | ||
4059 | 321 | </div> | ||
4060 | 322 | <!--End-Postamble--> | ||
4061 | 323 | <!--Footer--> | ||
4062 | 324 | <footer class="global clearfix" role="contentinfo"> | ||
4063 | 325 | <nav role="navigation"> | ||
4064 | 326 | <div class="footer-a"> | ||
4065 | 327 | <div class="clearfix"> | ||
4066 | 328 | <ul> | ||
4067 | 329 | <li> | ||
4068 | 330 | <h2><a href="/">Juju</a></h2> | ||
4069 | 331 | <ul> | ||
4070 | 332 | <li><a href="/charms">Charms</a></li> | ||
4071 | 333 | <li><a href="/features">Features</a></li> | ||
4072 | 334 | <li><a href="/deployment">Deployment</a></li> | ||
4073 | 335 | </ul> | ||
4074 | 336 | </li> | ||
4075 | 337 | <li> | ||
4076 | 338 | <h2><a href="/resources">Resources</a></h2> | ||
4077 | 339 | <ul> | ||
4078 | 340 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
4079 | 341 | <li><a href="/docs/">Documentation</a></li> | ||
4080 | 342 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
4081 | 343 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
4082 | 344 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
4083 | 345 | <li><a href="/resources/videos/">Videos</a></li> | ||
4084 | 346 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
4085 | 347 | </ul> | ||
4086 | 348 | </li> | ||
4087 | 349 | <li> | ||
4088 | 350 | <h2><a href="/community">Community</a></h2> | ||
4089 | 351 | <ul> | ||
4090 | 352 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
4091 | 353 | <li><a href="/events/">Events</a></li> | ||
4092 | 354 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
4093 | 355 | <li><a href="/community/charmers/">Charmers</a></li> | ||
4094 | 356 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
4095 | 357 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
4096 | 358 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
4097 | 359 | </ul> | ||
4098 | 360 | </li> | ||
4099 | 361 | <li> | ||
4100 | 362 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
4101 | 363 | <ul> | ||
4102 | 364 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
4103 | 365 | <li><a href="/download/">Download Juju</a></li> | ||
4104 | 366 | </ul> | ||
4105 | 367 | </li> | ||
4106 | 368 | </ul> | ||
4107 | 369 | </div> | ||
4108 | 370 | </div> | ||
4109 | 371 | </nav> | ||
4110 | 372 | <div class="legal clearfix"> | ||
4111 | 373 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
4112 | 374 | </div> | ||
4113 | 375 | </footer> | ||
4114 | 376 | |||
4115 | 377 | <!--End-Footer--> | ||
4116 | 378 | <!--Scripts--> | ||
4117 | 379 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
4118 | 380 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
4119 | 381 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
4120 | 382 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
4121 | 383 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
4122 | 384 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
4123 | 385 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
4124 | 386 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
4125 | 387 | <!-- google analytics --> | ||
4126 | 388 | <script> | ||
4127 | 389 | var _gaq = _gaq || []; | ||
4128 | 390 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
4129 | 391 | _gaq.push(['_trackPageview']); | ||
4130 | 392 | |||
4131 | 393 | (function() { | ||
4132 | 394 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
4133 | 395 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
4134 | 396 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
4135 | 397 | })(); | ||
4136 | 398 | </script> | ||
4137 | 399 | <!--End-Scripts--> | ||
4138 | 400 | |||
4139 | 401 | |||
4140 | 402 | </body></html> | ||
4141 | 0 | 403 | ||
4142 | === removed file 'htmldocs/authors-hooks.html' | |||
4143 | --- htmldocs/authors-hooks.html 2013-09-27 14:53:30 +0000 | |||
4144 | +++ htmldocs/authors-hooks.html 1970-01-01 00:00:00 +0000 | |||
4145 | @@ -1,185 +0,0 @@ | |||
4146 | 1 | <!DOCTYPE html> | ||
4147 | 2 | <html> | ||
4148 | 3 | <!--Head--> | ||
4149 | 4 | <head> | ||
4150 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
4151 | 6 | <title>Juju Documentation</title> | ||
4152 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
4153 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
4154 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
4155 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
4156 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
4157 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
4158 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
4159 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
4160 | 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"> | ||
4161 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
4162 | 17 | |||
4163 | 18 | <!--[if lt IE 9]> | ||
4164 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
4165 | 20 | <![endif]--> | ||
4166 | 21 | </head> | ||
4167 | 22 | <!--End-Head--> | ||
4168 | 23 | |||
4169 | 24 | |||
4170 | 25 | |||
4171 | 26 | <body class="resources"> | ||
4172 | 27 | |||
4173 | 28 | <!--Header--> | ||
4174 | 29 | |||
4175 | 30 | <header class="banner global" role="banner"> | ||
4176 | 31 | <nav role="navigation" class="nav-primary nav-right"> | ||
4177 | 32 | <div class="logo"> | ||
4178 | 33 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
4179 | 34 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
4180 | 35 | <span>Juju</span> | ||
4181 | 36 | </a> | ||
4182 | 37 | </div> | ||
4183 | 38 | <ul> | ||
4184 | 39 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
4185 | 40 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
4186 | 41 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
4187 | 42 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
4188 | 43 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
4189 | 44 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
4190 | 45 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
4191 | 46 | </ul> | ||
4192 | 47 | <div id="box-search"> | ||
4193 | 48 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
4194 | 49 | <label class="off-left" for="s">Search:</label> | ||
4195 | 50 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
4196 | 51 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
4197 | 52 | </form> | ||
4198 | 53 | </div> | ||
4199 | 54 | </nav> | ||
4200 | 55 | </header> | ||
4201 | 56 | <!--End-Header--> | ||
4202 | 57 | <!--Preamble--> | ||
4203 | 58 | <div class="wrapper"> | ||
4204 | 59 | <div id="main-content" class="inner-wrapper" role="main"> | ||
4205 | 60 | <div class="row no-border"> | ||
4206 | 61 | <div class="header-navigation-secondary"></div> | ||
4207 | 62 | <h2 class="pagetitle">Juju documentation</h2> | ||
4208 | 63 | </div> | ||
4209 | 64 | <section id="content" class="container-12"> | ||
4210 | 65 | <div class="grid-12 doc-container"> | ||
4211 | 66 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
4212 | 67 | <div class="grid-9 doc-content"> | ||
4213 | 68 | <!--End-Preamble--> | ||
4214 | 69 | <article> | ||
4215 | 70 | <section id ="hook-debugging"> | ||
4216 | 71 | <h1>Hook debugging</h1> | ||
4217 | 72 | |||
4218 | 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> | ||
4219 | 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> | ||
4220 | 75 | |||
4221 | 76 | <h2>How it works</h2> | ||
4222 | 77 | <p>When the juju user utilizes the hook debug command like so:</p> | ||
4223 | 78 | <pre>juju debug-hooks unit_name [hook_name]</pre> | ||
4224 | 79 | |||
4225 | 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> | ||
4226 | 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> | ||
4227 | 82 | <p>The native capabilities of tmux can be exploited to construct a full debug/development environment on the remote machine.</p> | ||
4228 | 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> | ||
4229 | 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> | ||
4230 | 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> | ||
4231 | 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> | ||
4232 | 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> | ||
4233 | 88 | |||
4234 | 89 | <h2>Internals</h2> | ||
4235 | 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> | ||
4236 | 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> | ||
4237 | 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> | ||
4238 | 93 | </section> | ||
4239 | 94 | </article> | ||
4240 | 95 | </div> | ||
4241 | 96 | </div> | ||
4242 | 97 | </section> | ||
4243 | 98 | <!--Postamble--> | ||
4244 | 99 | </div> | ||
4245 | 100 | </div> | ||
4246 | 101 | </section> | ||
4247 | 102 | </div> | ||
4248 | 103 | </div> | ||
4249 | 104 | <!--End-Postamble--> | ||
4250 | 105 | <!--Footer--> | ||
4251 | 106 | <footer class="global clearfix" role="contentinfo"> | ||
4252 | 107 | <nav role="navigation"> | ||
4253 | 108 | <div class="footer-a"> | ||
4254 | 109 | <div class="clearfix"> | ||
4255 | 110 | <ul> | ||
4256 | 111 | <li> | ||
4257 | 112 | <h2><a href="/">Juju</a></h2> | ||
4258 | 113 | <ul> | ||
4259 | 114 | <li><a href="/charms">Charms</a></li> | ||
4260 | 115 | <li><a href="/features">Features</a></li> | ||
4261 | 116 | <li><a href="/deployment">Deployment</a></li> | ||
4262 | 117 | </ul> | ||
4263 | 118 | </li> | ||
4264 | 119 | <li> | ||
4265 | 120 | <h2><a href="/resources">Resources</a></h2> | ||
4266 | 121 | <ul> | ||
4267 | 122 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
4268 | 123 | <li><a href="/docs/">Documentation</a></li> | ||
4269 | 124 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
4270 | 125 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
4271 | 126 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
4272 | 127 | <li><a href="/resources/videos/">Videos</a></li> | ||
4273 | 128 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
4274 | 129 | </ul> | ||
4275 | 130 | </li> | ||
4276 | 131 | <li> | ||
4277 | 132 | <h2><a href="/community">Community</a></h2> | ||
4278 | 133 | <ul> | ||
4279 | 134 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
4280 | 135 | <li><a href="/events/">Events</a></li> | ||
4281 | 136 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
4282 | 137 | <li><a href="/community/charmers/">Charmers</a></li> | ||
4283 | 138 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
4284 | 139 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
4285 | 140 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
4286 | 141 | </ul> | ||
4287 | 142 | </li> | ||
4288 | 143 | <li> | ||
4289 | 144 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
4290 | 145 | <ul> | ||
4291 | 146 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
4292 | 147 | <li><a href="/download/">Download Juju</a></li> | ||
4293 | 148 | </ul> | ||
4294 | 149 | </li> | ||
4295 | 150 | </ul> | ||
4296 | 151 | </div> | ||
4297 | 152 | </div> | ||
4298 | 153 | </nav> | ||
4299 | 154 | <div class="legal clearfix"> | ||
4300 | 155 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
4301 | 156 | </div> | ||
4302 | 157 | </footer> | ||
4303 | 158 | |||
4304 | 159 | <!--End-Footer--> | ||
4305 | 160 | |||
4306 | 161 | <!--Scripts--> | ||
4307 | 162 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
4308 | 163 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
4309 | 164 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
4310 | 165 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
4311 | 166 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
4312 | 167 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
4313 | 168 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
4314 | 169 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
4315 | 170 | <!-- google analytics --> | ||
4316 | 171 | <script> | ||
4317 | 172 | var _gaq = _gaq || []; | ||
4318 | 173 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
4319 | 174 | _gaq.push(['_trackPageview']); | ||
4320 | 175 | |||
4321 | 176 | (function() { | ||
4322 | 177 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
4323 | 178 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
4324 | 179 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
4325 | 180 | })(); | ||
4326 | 181 | </script> | ||
4327 | 182 | <!--End-Scripts--> | ||
4328 | 183 | |||
4329 | 184 | |||
4330 | 185 | </body></html> | ||
4331 | 186 | 0 | ||
4332 | === modified file 'htmldocs/authors-implicit-relations.html' | |||
4333 | --- htmldocs/authors-implicit-relations.html 2013-09-27 14:53:30 +0000 | |||
4334 | +++ htmldocs/authors-implicit-relations.html 2013-10-09 20:07:46 +0000 | |||
4335 | @@ -23,6 +23,8 @@ | |||
4336 | 23 | 23 | ||
4337 | 24 | 24 | ||
4338 | 25 | 25 | ||
4339 | 26 | |||
4340 | 27 | |||
4341 | 26 | <body class="resources"> | 28 | <body class="resources"> |
4342 | 27 | 29 | ||
4343 | 28 | <!--Header--> | 30 | <!--Header--> |
4344 | @@ -186,4 +188,6 @@ | |||
4345 | 186 | <!--End-Scripts--> | 188 | <!--End-Scripts--> |
4346 | 187 | 189 | ||
4347 | 188 | 190 | ||
4348 | 191 | |||
4349 | 192 | |||
4350 | 189 | </body></html> | 193 | </body></html> |
4351 | 190 | 194 | ||
4352 | === modified file 'htmldocs/authors-interfaces.html' | |||
4353 | --- htmldocs/authors-interfaces.html 2013-09-27 14:53:30 +0000 | |||
4354 | +++ htmldocs/authors-interfaces.html 2013-10-09 20:07:46 +0000 | |||
4355 | @@ -23,6 +23,8 @@ | |||
4356 | 23 | 23 | ||
4357 | 24 | 24 | ||
4358 | 25 | 25 | ||
4359 | 26 | |||
4360 | 27 | |||
4361 | 26 | <body class="resources"> | 28 | <body class="resources"> |
4362 | 27 | 29 | ||
4363 | 28 | <!--Header--> | 30 | <!--Header--> |
4364 | @@ -362,4 +364,6 @@ | |||
4365 | 362 | <!--End-Scripts--> | 364 | <!--End-Scripts--> |
4366 | 363 | 365 | ||
4367 | 364 | 366 | ||
4368 | 367 | |||
4369 | 368 | |||
4370 | 365 | </body></html> | 369 | </body></html> |
4371 | 366 | 370 | ||
4372 | === modified file 'htmldocs/authors-intro.html' | |||
4373 | --- htmldocs/authors-intro.html 2013-09-27 14:53:30 +0000 | |||
4374 | +++ htmldocs/authors-intro.html 2013-10-09 20:07:46 +0000 | |||
4375 | @@ -21,6 +21,8 @@ | |||
4376 | 21 | </head> | 21 | </head> |
4377 | 22 | <!--End-Head--> | 22 | <!--End-Head--> |
4378 | 23 | 23 | ||
4379 | 24 | |||
4380 | 25 | |||
4381 | 24 | <body class="resources"> | 26 | <body class="resources"> |
4382 | 25 | <!--Header--> | 27 | <!--Header--> |
4383 | 26 | 28 | ||
4384 | @@ -67,7 +69,7 @@ | |||
4385 | 67 | <section id='author-intro'> | 69 | <section id='author-intro'> |
4386 | 68 | <h1>Becoming a charm author</h1> | 70 | <h1>Becoming a charm author</h1> |
4387 | 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> |
4389 | 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> |
4390 | 71 | </article> | 73 | </article> |
4391 | 72 | <!--Postamble--> | 74 | <!--Postamble--> |
4392 | 73 | </div> | 75 | </div> |
4393 | @@ -154,4 +156,6 @@ | |||
4394 | 154 | </script> | 156 | </script> |
4395 | 155 | <!--End-Scripts--> | 157 | <!--End-Scripts--> |
4396 | 156 | 158 | ||
4397 | 159 | |||
4398 | 160 | |||
4399 | 157 | </body></html> | 161 | </body></html> |
4400 | 158 | 162 | ||
4401 | === added file 'htmldocs/authors-relations-in-depth.html' | |||
4402 | --- htmldocs/authors-relations-in-depth.html 1970-01-01 00:00:00 +0000 | |||
4403 | +++ htmldocs/authors-relations-in-depth.html 2013-10-09 20:07:46 +0000 | |||
4404 | @@ -0,0 +1,187 @@ | |||
4405 | 1 | <!DOCTYPE html> | ||
4406 | 2 | <html> | ||
4407 | 3 | <!--Head--> | ||
4408 | 4 | <head> | ||
4409 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
4410 | 6 | <title>Juju Documentation</title> | ||
4411 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
4412 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
4413 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
4414 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
4415 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
4416 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
4417 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
4418 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
4419 | 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"> | ||
4420 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
4421 | 17 | |||
4422 | 18 | <!--[if lt IE 9]> | ||
4423 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
4424 | 20 | <![endif]--> | ||
4425 | 21 | </head> | ||
4426 | 22 | <!--End-Head--> | ||
4427 | 23 | |||
4428 | 24 | <body class="resources"> | ||
4429 | 25 | <!--Header--> | ||
4430 | 26 | |||
4431 | 27 | <header class="banner global" role="banner"> | ||
4432 | 28 | <nav role="navigation" class="nav-primary nav-right"> | ||
4433 | 29 | <div class="logo"> | ||
4434 | 30 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
4435 | 31 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
4436 | 32 | <span>Juju</span> | ||
4437 | 33 | </a> | ||
4438 | 34 | </div> | ||
4439 | 35 | <ul> | ||
4440 | 36 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
4441 | 37 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
4442 | 38 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
4443 | 39 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
4444 | 40 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
4445 | 41 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
4446 | 42 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
4447 | 43 | </ul> | ||
4448 | 44 | <div id="box-search"> | ||
4449 | 45 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
4450 | 46 | <label class="off-left" for="s">Search:</label> | ||
4451 | 47 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
4452 | 48 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
4453 | 49 | </form> | ||
4454 | 50 | </div> | ||
4455 | 51 | </nav> | ||
4456 | 52 | </header> | ||
4457 | 53 | <!--End-Header--> | ||
4458 | 54 | <!--Preamble--> | ||
4459 | 55 | <div class="wrapper"> | ||
4460 | 56 | <div id="main-content" class="inner-wrapper" role="main"> | ||
4461 | 57 | <div class="row no-border"> | ||
4462 | 58 | <div class="header-navigation-secondary"></div> | ||
4463 | 59 | <h2 class="pagetitle">Juju documentation</h2> | ||
4464 | 60 | </div> | ||
4465 | 61 | <section id="content" class="container-12"> | ||
4466 | 62 | <div class="grid-12 doc-container"> | ||
4467 | 63 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
4468 | 64 | <div class="grid-9 doc-content"> | ||
4469 | 65 | <!--End-Preamble--> | ||
4470 | 66 | <article> | ||
4471 | 67 | <section id="relations-in-depth"> | ||
4472 | 68 | <h1>Relations in depth</h1> | ||
4473 | 69 | |||
4474 | 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> | ||
4475 | 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> | ||
4476 | 72 | <ul> | ||
4477 | 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> | ||
4478 | 74 | <li>Signal its existence, and role in the relation, to the rest of the system.</li> | ||
4479 | 75 | </ul> | ||
4480 | 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> | ||
4481 | 77 | <ul> | ||
4482 | 78 | <li>Each provider unit observes every requirer unit</li> | ||
4483 | 79 | <li>Each requirer unit observes every provider unit</li> | ||
4484 | 80 | <li>Each peer unit observes every other peer unit</li> | ||
4485 | 81 | </ul> | ||
4486 | 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> | ||
4487 | 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> | ||
4488 | 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> | ||
4489 | 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> | ||
4490 | 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> | ||
4491 | 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> | ||
4492 | 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> | ||
4493 | 89 | </section> | ||
4494 | 90 | |||
4495 | 91 | <section id="relations-in-depth"> | ||
4496 | 92 | <h2 id="departing-relations">Departing relations</h2> | ||
4497 | 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> | ||
4498 | 94 | <ul> | ||
4499 | 95 | <li>For every known related unit -- those which have joined and not yet departed -- run the relation-departed hook.</li> | ||
4500 | 96 | <li>Run the relation-broken hook.</li> | ||
4501 | 97 | <li><code>depart</code> from its scope in the relation.</li> | ||
4502 | 98 | </ul> | ||
4503 | 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> | ||
4504 | 100 | </section> | ||
4505 | 101 | </article> | ||
4506 | 102 | <!--Postamble--> | ||
4507 | 103 | </div> | ||
4508 | 104 | </div> | ||
4509 | 105 | </section> | ||
4510 | 106 | </div> | ||
4511 | 107 | </div> | ||
4512 | 108 | <!--End-Postamble--> | ||
4513 | 109 | <!--Footer--> | ||
4514 | 110 | <footer class="global clearfix" role="contentinfo"> | ||
4515 | 111 | <nav role="navigation"> | ||
4516 | 112 | <div class="footer-a"> | ||
4517 | 113 | <div class="clearfix"> | ||
4518 | 114 | <ul> | ||
4519 | 115 | <li> | ||
4520 | 116 | <h2><a href="/">Juju</a></h2> | ||
4521 | 117 | <ul> | ||
4522 | 118 | <li><a href="/charms">Charms</a></li> | ||
4523 | 119 | <li><a href="/features">Features</a></li> | ||
4524 | 120 | <li><a href="/deployment">Deployment</a></li> | ||
4525 | 121 | </ul> | ||
4526 | 122 | </li> | ||
4527 | 123 | <li> | ||
4528 | 124 | <h2><a href="/resources">Resources</a></h2> | ||
4529 | 125 | <ul> | ||
4530 | 126 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
4531 | 127 | <li><a href="/docs/">Documentation</a></li> | ||
4532 | 128 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
4533 | 129 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
4534 | 130 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
4535 | 131 | <li><a href="/resources/videos/">Videos</a></li> | ||
4536 | 132 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
4537 | 133 | </ul> | ||
4538 | 134 | </li> | ||
4539 | 135 | <li> | ||
4540 | 136 | <h2><a href="/community">Community</a></h2> | ||
4541 | 137 | <ul> | ||
4542 | 138 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
4543 | 139 | <li><a href="/events/">Events</a></li> | ||
4544 | 140 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
4545 | 141 | <li><a href="/community/charmers/">Charmers</a></li> | ||
4546 | 142 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
4547 | 143 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
4548 | 144 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
4549 | 145 | </ul> | ||
4550 | 146 | </li> | ||
4551 | 147 | <li> | ||
4552 | 148 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
4553 | 149 | <ul> | ||
4554 | 150 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
4555 | 151 | <li><a href="/download/">Download Juju</a></li> | ||
4556 | 152 | </ul> | ||
4557 | 153 | </li> | ||
4558 | 154 | </ul> | ||
4559 | 155 | </div> | ||
4560 | 156 | </div> | ||
4561 | 157 | </nav> | ||
4562 | 158 | <div class="legal clearfix"> | ||
4563 | 159 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
4564 | 160 | </div> | ||
4565 | 161 | </footer> | ||
4566 | 162 | |||
4567 | 163 | <!--End-Footer--> | ||
4568 | 164 | <!--Scripts--> | ||
4569 | 165 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
4570 | 166 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
4571 | 167 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
4572 | 168 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
4573 | 169 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
4574 | 170 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
4575 | 171 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
4576 | 172 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
4577 | 173 | <!-- google analytics --> | ||
4578 | 174 | <script> | ||
4579 | 175 | var _gaq = _gaq || []; | ||
4580 | 176 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
4581 | 177 | _gaq.push(['_trackPageview']); | ||
4582 | 178 | |||
4583 | 179 | (function() { | ||
4584 | 180 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
4585 | 181 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
4586 | 182 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
4587 | 183 | })(); | ||
4588 | 184 | </script> | ||
4589 | 185 | <!--End-Scripts--> | ||
4590 | 186 | |||
4591 | 187 | </body></html> | ||
4592 | 0 | 188 | ||
4593 | === added file 'htmldocs/authors-service-config.html' | |||
4594 | --- htmldocs/authors-service-config.html 1970-01-01 00:00:00 +0000 | |||
4595 | +++ htmldocs/authors-service-config.html 2013-10-09 20:07:46 +0000 | |||
4596 | @@ -0,0 +1,210 @@ | |||
4597 | 1 | <!DOCTYPE html> | ||
4598 | 2 | <html> | ||
4599 | 3 | <!--Head--> | ||
4600 | 4 | <head> | ||
4601 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
4602 | 6 | <title>Juju Documentation</title> | ||
4603 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
4604 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
4605 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
4606 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
4607 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
4608 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
4609 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
4610 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
4611 | 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"> | ||
4612 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
4613 | 17 | |||
4614 | 18 | <!--[if lt IE 9]> | ||
4615 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
4616 | 20 | <![endif]--> | ||
4617 | 21 | </head> | ||
4618 | 22 | <!--End-Head--> | ||
4619 | 23 | |||
4620 | 24 | |||
4621 | 25 | |||
4622 | 26 | |||
4623 | 27 | <body class="resources"> | ||
4624 | 28 | |||
4625 | 29 | <!--Header--> | ||
4626 | 30 | |||
4627 | 31 | <header class="banner global" role="banner"> | ||
4628 | 32 | <nav role="navigation" class="nav-primary nav-right"> | ||
4629 | 33 | <div class="logo"> | ||
4630 | 34 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
4631 | 35 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
4632 | 36 | <span>Juju</span> | ||
4633 | 37 | </a> | ||
4634 | 38 | </div> | ||
4635 | 39 | <ul> | ||
4636 | 40 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
4637 | 41 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
4638 | 42 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
4639 | 43 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
4640 | 44 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
4641 | 45 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
4642 | 46 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
4643 | 47 | </ul> | ||
4644 | 48 | <div id="box-search"> | ||
4645 | 49 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
4646 | 50 | <label class="off-left" for="s">Search:</label> | ||
4647 | 51 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
4648 | 52 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
4649 | 53 | </form> | ||
4650 | 54 | </div> | ||
4651 | 55 | </nav> | ||
4652 | 56 | </header> | ||
4653 | 57 | <!--End-Header--> | ||
4654 | 58 | <!--Preamble--> | ||
4655 | 59 | <div class="wrapper"> | ||
4656 | 60 | <div id="main-content" class="inner-wrapper" role="main"> | ||
4657 | 61 | <div class="row no-border"> | ||
4658 | 62 | <div class="header-navigation-secondary"></div> | ||
4659 | 63 | <h2 class="pagetitle">Juju documentation</h2> | ||
4660 | 64 | </div> | ||
4661 | 65 | <section id="content" class="container-12"> | ||
4662 | 66 | <div class="grid-12 doc-container"> | ||
4663 | 67 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
4664 | 68 | <div class="grid-9 doc-content"> | ||
4665 | 69 | <!--End-Preamble--> | ||
4666 | 70 | <article> | ||
4667 | 71 | <h1>Service configuration</h1> | ||
4668 | 72 | <h2>Introduction</h2> | ||
4669 | 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> | ||
4670 | 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> | ||
4671 | 75 | <h2>Using configuration options</h2> | ||
4672 | 76 | <p>Configuration options are manipulated using a command line interface. juju provide a set command to aid the administrator in changing values.</p> | ||
4673 | 77 | <pre><code>juju set <service name> option=value [option=value]</code></pre> | ||
4674 | 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> | ||
4675 | 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> | ||
4676 | 80 | <p>A configuration file may be provided at deployment time using the --config option, as follows:</p> | ||
4677 | 81 | <pre><code>juju deploy [--config local.yaml] wordpress myblog | ||
4678 | 82 | juju deploy [--config local.yaml] postgres</code></pre> | ||
4679 | 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> | ||
4680 | 84 | <p>Below is an example local.yaml containing options which would be used during deployment of a service named myblog.</p> | ||
4681 | 85 | <pre><code>myblog: | ||
4682 | 86 | blog-roll: ['http://foobar.com', 'http://testing.com'] | ||
4683 | 87 | blog-title: Awesome Sauce | ||
4684 | 88 | password: n0nsense | ||
4685 | 89 | postgres: | ||
4686 | 90 | port: 5432 | ||
4687 | 91 | cluster-name: main</code></pre> | ||
4688 | 92 | <h2>Creating charms</h2> | ||
4689 | 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> | ||
4690 | 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> | ||
4691 | 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> | ||
4692 | 96 | <pre><code>options: | ||
4693 | 97 | port: | ||
4694 | 98 | default: 80 | ||
4695 | 99 | type: int | ||
4696 | 100 | description: Port to listen on | ||
4697 | 101 | admin-email: | ||
4698 | 102 | # type: str is implied | ||
4699 | 103 | default: null | ||
4700 | 104 | description: Email address for the site administrator.</code></pre> | ||
4701 | 105 | <p>To access these configuration options from a hook we provide the following:</p> | ||
4702 | 106 | <pre><code>config-get [option name]</code></pre> | ||
4703 | 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> | ||
4704 | 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> | ||
4705 | 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> | ||
4706 | 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> | ||
4707 | 111 | <h2>Internals</h2> | ||
4708 | 112 | <blockquote> | ||
4709 | 113 | <p><strong>note</strong></p> | ||
4710 | 114 | <dl> | ||
4711 | 115 | <dt>This section explains details useful to the implementation but not of</dt> | ||
4712 | 116 | <dd><p>interest to the casual reader.</p> | ||
4713 | 117 | </dd> | ||
4714 | 118 | </dl> | ||
4715 | 119 | </blockquote> | ||
4716 | 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> | ||
4717 | 121 | </article> | ||
4718 | 122 | <!--Postamble--> | ||
4719 | 123 | </div> | ||
4720 | 124 | </div> | ||
4721 | 125 | </section> | ||
4722 | 126 | </div> | ||
4723 | 127 | </div> | ||
4724 | 128 | <!--End-Postamble--> | ||
4725 | 129 | <!--Footer--> | ||
4726 | 130 | <footer class="global clearfix" role="contentinfo"> | ||
4727 | 131 | <nav role="navigation"> | ||
4728 | 132 | <div class="footer-a"> | ||
4729 | 133 | <div class="clearfix"> | ||
4730 | 134 | <ul> | ||
4731 | 135 | <li> | ||
4732 | 136 | <h2><a href="/">Juju</a></h2> | ||
4733 | 137 | <ul> | ||
4734 | 138 | <li><a href="/charms">Charms</a></li> | ||
4735 | 139 | <li><a href="/features">Features</a></li> | ||
4736 | 140 | <li><a href="/deployment">Deployment</a></li> | ||
4737 | 141 | </ul> | ||
4738 | 142 | </li> | ||
4739 | 143 | <li> | ||
4740 | 144 | <h2><a href="/resources">Resources</a></h2> | ||
4741 | 145 | <ul> | ||
4742 | 146 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
4743 | 147 | <li><a href="/docs/">Documentation</a></li> | ||
4744 | 148 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
4745 | 149 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
4746 | 150 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
4747 | 151 | <li><a href="/resources/videos/">Videos</a></li> | ||
4748 | 152 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
4749 | 153 | </ul> | ||
4750 | 154 | </li> | ||
4751 | 155 | <li> | ||
4752 | 156 | <h2><a href="/community">Community</a></h2> | ||
4753 | 157 | <ul> | ||
4754 | 158 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
4755 | 159 | <li><a href="/events/">Events</a></li> | ||
4756 | 160 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
4757 | 161 | <li><a href="/community/charmers/">Charmers</a></li> | ||
4758 | 162 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
4759 | 163 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
4760 | 164 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
4761 | 165 | </ul> | ||
4762 | 166 | </li> | ||
4763 | 167 | <li> | ||
4764 | 168 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
4765 | 169 | <ul> | ||
4766 | 170 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
4767 | 171 | <li><a href="/download/">Download Juju</a></li> | ||
4768 | 172 | </ul> | ||
4769 | 173 | </li> | ||
4770 | 174 | </ul> | ||
4771 | 175 | </div> | ||
4772 | 176 | </div> | ||
4773 | 177 | </nav> | ||
4774 | 178 | <div class="legal clearfix"> | ||
4775 | 179 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
4776 | 180 | </div> | ||
4777 | 181 | </footer> | ||
4778 | 182 | |||
4779 | 183 | <!--End-Footer--> | ||
4780 | 184 | |||
4781 | 185 | <!--Scripts--> | ||
4782 | 186 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
4783 | 187 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
4784 | 188 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
4785 | 189 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
4786 | 190 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> | ||
4787 | 191 | <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js"></script> | ||
4788 | 192 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/core.js"></script> | ||
4789 | 193 | <script src="//assets.ubuntu.com/sites/ubuntu/latest/u/js/global.js"></script> | ||
4790 | 194 | <!-- google analytics --> | ||
4791 | 195 | <script> | ||
4792 | 196 | var _gaq = _gaq || []; | ||
4793 | 197 | _gaq.push(['_setAccount', 'UA-1018242-41']); | ||
4794 | 198 | _gaq.push(['_trackPageview']); | ||
4795 | 199 | |||
4796 | 200 | (function() { | ||
4797 | 201 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; | ||
4798 | 202 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | ||
4799 | 203 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); | ||
4800 | 204 | })(); | ||
4801 | 205 | </script> | ||
4802 | 206 | <!--End-Scripts--> | ||
4803 | 207 | |||
4804 | 208 | |||
4805 | 209 | |||
4806 | 210 | </body></html> | ||
4807 | 0 | 211 | ||
4808 | === removed file 'htmldocs/authors-service-config.html' | |||
4809 | --- htmldocs/authors-service-config.html 2013-09-27 14:53:30 +0000 | |||
4810 | +++ htmldocs/authors-service-config.html 1970-01-01 00:00:00 +0000 | |||
4811 | @@ -1,208 +0,0 @@ | |||
4812 | 1 | <!DOCTYPE html> | ||
4813 | 2 | <html> | ||
4814 | 3 | <!--Head--> | ||
4815 | 4 | <head> | ||
4816 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | ||
4817 | 6 | <title>Juju Documentation</title> | ||
4818 | 7 | <script src="/wp-content/themes/ubuntu/library/js/all-yui.js"></script> | ||
4819 | 8 | <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,300,300italic,400italic,700,700italic|Ubuntu+Mono" rel="stylesheet" type="text/css"> | ||
4820 | 9 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/reset.css"> | ||
4821 | 10 | <link rel="shortcut icon" href="//assets.ubuntu.com/sites/ubuntu/latest/u/img/favicon.ico" /> | ||
4822 | 11 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/guidelines/css/latest/ubuntu-styles.css" /> | ||
4823 | 12 | <link rel="stylesheet" type="text/css" media="screen" href="//assets.ubuntu.com/sites/ubuntu/latest/u/css/global.css" /> | ||
4824 | 13 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/960.css"> | ||
4825 | 14 | <link rel="stylesheet" type="text/css" media="screen" href="https://juju.ubuntu.com/wp-content/themes/juju-website/css/home-new.css"> | ||
4826 | 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"> | ||
4827 | 16 | <link href="./css/main.css" rel="stylesheet" type="text/css"> | ||
4828 | 17 | |||
4829 | 18 | <!--[if lt IE 9]> | ||
4830 | 19 | <script type="text/javascript" src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> | ||
4831 | 20 | <![endif]--> | ||
4832 | 21 | </head> | ||
4833 | 22 | <!--End-Head--> | ||
4834 | 23 | |||
4835 | 24 | |||
4836 | 25 | |||
4837 | 26 | <body class="resources"> | ||
4838 | 27 | |||
4839 | 28 | <!--Header--> | ||
4840 | 29 | |||
4841 | 30 | <header class="banner global" role="banner"> | ||
4842 | 31 | <nav role="navigation" class="nav-primary nav-right"> | ||
4843 | 32 | <div class="logo"> | ||
4844 | 33 | <a class="logo-ubuntu" href="https://juju.ubuntu.com/"> | ||
4845 | 34 | <img width="118" height="27" src="//assets.ubuntu.com/sites/ubuntu/latest/u/img/logo.png" alt="Juju logo" /> | ||
4846 | 35 | <span>Juju</span> | ||
4847 | 36 | </a> | ||
4848 | 37 | </div> | ||
4849 | 38 | <ul> | ||
4850 | 39 | <li class="accessibility-aid"><a accesskey="s" href="#main-content">Jump to content</a></li> | ||
4851 | 40 | <li class="page_item page-item-8"><a href="https://juju.ubuntu.com/charms/">Charms</a></li> | ||
4852 | 41 | <li class="page_item page-item-10"><a href="https://juju.ubuntu.com/features/">Features</a></li> | ||
4853 | 42 | <li class="page_item page-item-12"><a href="https://juju.ubuntu.com/deployment/">Deploy</a></li> | ||
4854 | 43 | <li class="page_item page-item-14"><a href="https://juju.ubuntu.com/resources/">Resources</a></li> | ||
4855 | 44 | <li class="page_item page-item-16"><a href="https://juju.ubuntu.com/community/">Community</a></li> | ||
4856 | 45 | <li class="page_item page-item-18"><a href="https://juju.ubuntu.com/download/">Install Juju</a></li> | ||
4857 | 46 | </ul> | ||
4858 | 47 | <div id="box-search"> | ||
4859 | 48 | <form class="search-form" method="get" id="searchform" action="https://juju.ubuntu.com/"> | ||
4860 | 49 | <label class="off-left" for="s">Search:</label> | ||
4861 | 50 | <input class="form-text" type="text" value="" name="s" id="s" /> | ||
4862 | 51 | <button class="off-left form-submit" type="submit" id="searchsubmit">Search</button> | ||
4863 | 52 | </form> | ||
4864 | 53 | </div> | ||
4865 | 54 | </nav> | ||
4866 | 55 | </header> | ||
4867 | 56 | <!--End-Header--> | ||
4868 | 57 | <!--Preamble--> | ||
4869 | 58 | <div class="wrapper"> | ||
4870 | 59 | <div id="main-content" class="inner-wrapper" role="main"> | ||
4871 | 60 | <div class="row no-border"> | ||
4872 | 61 | <div class="header-navigation-secondary"></div> | ||
4873 | 62 | <h2 class="pagetitle">Juju documentation</h2> | ||
4874 | 63 | </div> | ||
4875 | 64 | <section id="content" class="container-12"> | ||
4876 | 65 | <div class="grid-12 doc-container"> | ||
4877 | 66 | <div id="navlinks" class="grid-3 doc-navigation">LINKS</div> | ||
4878 | 67 | <div class="grid-9 doc-content"> | ||
4879 | 68 | <!--End-Preamble--> | ||
4880 | 69 | <article> | ||
4881 | 70 | <h1>Service configuration</h1> | ||
4882 | 71 | <h2>Introduction</h2> | ||
4883 | 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> | ||
4884 | 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> | ||
4885 | 74 | <h2>Using configuration options</h2> | ||
4886 | 75 | <p>Configuration options are manipulated using a command line interface. juju provide a set command to aid the administrator in changing values.</p> | ||
4887 | 76 | <pre><code>juju set <service name> option=value [option=value]</code></pre> | ||
4888 | 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> | ||
4889 | 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> | ||
4890 | 79 | <p>A configuration file may be provided at deployment time using the --config option, as follows:</p> | ||
4891 | 80 | <pre><code>juju deploy [--config local.yaml] wordpress myblog | ||
4892 | 81 | juju deploy [--config local.yaml] postgres</code></pre> | ||
4893 | 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> | ||
4894 | 83 | <p>Below is an example local.yaml containing options which would be used during deployment of a service named myblog.</p> | ||
4895 | 84 | <pre><code>myblog: | ||
4896 | 85 | blog-roll: ['http://foobar.com', 'http://testing.com'] | ||
4897 | 86 | blog-title: Awesome Sauce | ||
4898 | 87 | password: n0nsense | ||
4899 | 88 | postgres: | ||
4900 | 89 | port: 5432 | ||
4901 | 90 | cluster-name: main</code></pre> | ||
4902 | 91 | <h2>Creating charms</h2> | ||
4903 | 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> | ||
4904 | 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> | ||
4905 | 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> | ||
4906 | 95 | <pre><code>options: | ||
4907 | 96 | port: | ||
4908 | 97 | default: 80 | ||
4909 | 98 | type: int | ||
4910 | 99 | description: Port to listen on | ||
4911 | 100 | admin-email: | ||
4912 | 101 | # type: str is implied | ||
4913 | 102 | default: null | ||
4914 | 103 | description: Email address for the site administrator.</code></pre> | ||
4915 | 104 | <p>To access these configuration options from a hook we provide the following:</p> | ||
4916 | 105 | <pre><code>config-get [option name]</code></pre> | ||
4917 | 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> | ||
4918 | 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> | ||
4919 | 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> | ||
4920 | 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> | ||
4921 | 110 | <h2>Internals</h2> | ||
4922 | 111 | <blockquote> | ||
4923 | 112 | <p><strong>note</strong></p> | ||
4924 | 113 | <dl> | ||
4925 | 114 | <dt>This section explains details useful to the implementation but not of</dt> | ||
4926 | 115 | <dd><p>interest to the casual reader.</p> | ||
4927 | 116 | </dd> | ||
4928 | 117 | </dl> | ||
4929 | 118 | </blockquote> | ||
4930 | 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> | ||
4931 | 120 | </article> | ||
4932 | 121 | <!--Postamble--> | ||
4933 | 122 | </div> | ||
4934 | 123 | </div> | ||
4935 | 124 | </section> | ||
4936 | 125 | </div> | ||
4937 | 126 | </div> | ||
4938 | 127 | <!--End-Postamble--> | ||
4939 | 128 | <!--Footer--> | ||
4940 | 129 | <footer class="global clearfix" role="contentinfo"> | ||
4941 | 130 | <nav role="navigation"> | ||
4942 | 131 | <div class="footer-a"> | ||
4943 | 132 | <div class="clearfix"> | ||
4944 | 133 | <ul> | ||
4945 | 134 | <li> | ||
4946 | 135 | <h2><a href="/">Juju</a></h2> | ||
4947 | 136 | <ul> | ||
4948 | 137 | <li><a href="/charms">Charms</a></li> | ||
4949 | 138 | <li><a href="/features">Features</a></li> | ||
4950 | 139 | <li><a href="/deployment">Deployment</a></li> | ||
4951 | 140 | </ul> | ||
4952 | 141 | </li> | ||
4953 | 142 | <li> | ||
4954 | 143 | <h2><a href="/resources">Resources</a></h2> | ||
4955 | 144 | <ul> | ||
4956 | 145 | <li><a href="/resources/juju-overview/">Overview</a></li> | ||
4957 | 146 | <li><a href="/docs/">Documentation</a></li> | ||
4958 | 147 | <li><a href="/resources/the-juju-gui/">The Juju web UI</a></li> | ||
4959 | 148 | <li><a href="/docs/authors-charm-store.html">The charm store</a></li> | ||
4960 | 149 | <li><a href="/docs/getting-started.html#test">Tutorial</a></li> | ||
4961 | 150 | <li><a href="/resources/videos/">Videos</a></li> | ||
4962 | 151 | <li><a href="/resources/easy-tasks-for-new-developers/">Easy tasks for new developers</a></li> | ||
4963 | 152 | </ul> | ||
4964 | 153 | </li> | ||
4965 | 154 | <li> | ||
4966 | 155 | <h2><a href="/community">Community</a></h2> | ||
4967 | 156 | <ul> | ||
4968 | 157 | <li><a href="/community/blog/">Juju Blog</a></li> | ||
4969 | 158 | <li><a href="/events/">Events</a></li> | ||
4970 | 159 | <li><a href="/community/weekly-charm-meeting/">Weekly charm meeting</a></li> | ||
4971 | 160 | <li><a href="/community/charmers/">Charmers</a></li> | ||
4972 | 161 | <li><a href="/docs/authors-charm-writing.html">Write a charm</a></li> | ||
4973 | 162 | <li><a href="/docs/contributing.html">Help with documentation</a></li> | ||
4974 | 163 | <li><a href="https://bugs.launchpad.net/juju-website/+filebug">File a bug</a></li> <li><a href="/labs/">Juju Labs</a></li> | ||
4975 | 164 | </ul> | ||
4976 | 165 | </li> | ||
4977 | 166 | <li> | ||
4978 | 167 | <h2><a href="https://jujucharms.com/sidebar/">Try Juju</a></h2> | ||
4979 | 168 | <ul> | ||
4980 | 169 | <li><a href="https://jujucharms.com/">Charm store</a></li> | ||
4981 | 170 | <li><a href="/download/">Download Juju</a></li> | ||
4982 | 171 | </ul> | ||
4983 | 172 | </li> | ||
4984 | 173 | </ul> | ||
4985 | 174 | </div> | ||
4986 | 175 | </div> | ||
4987 | 176 | </nav> | ||
4988 | 177 | <div class="legal clearfix"> | ||
4989 | 178 | <p>© 2013 Canonical Ltd. Ubuntu and Canonical are registered trademarks of <a href="http://canonical.com">Canonical Ltd</a>.</p> | ||
4990 | 179 | </div> | ||
4991 | 180 | </footer> | ||
4992 | 181 | |||
4993 | 182 | <!--End-Footer--> | ||
4994 | 183 | |||
4995 | 184 | <!--Scripts--> | ||
4996 | 185 | <script src="//google-code-prettify.googlecode.com/svn/loader/run_prettify.js?skin=sunburst"></script> | ||
4997 | 186 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | ||
4998 | 187 | <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script> | ||
4999 | 188 | <script src="//d38yea5fb4e2oh.cloudfront.net/jquery.stacktack.min.js"></script> | ||
5000 | 189 | <script type="text/javascript" src="https://juju.ubuntu.com/docs/js/main.js"></script> |
The diff has been truncated for viewing.
Um, this is why it has taken a long time...
"Diff against target: 5678 lines (+3495/-1230)"