~adam-stokes/conjure/conjure-up-io

« back to all changes in this revision

Viewing changes to public/docs/en/developers/index.html

  • Committer: Adam Stokes
  • Date: 2016-09-13 09:40:11 UTC
  • Revision ID: adam.stokes@ubuntu.com-20160913094011-qeey5hfm0eu4lgp7
Add more developer and user documentation

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE html>
 
2
<html lang="en">
 
3
<head>
 
4
<meta charset="UTF-8">
 
5
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
 
6
<meta name="viewport" content="width=device-width, initial-scale=1.0">
 
7
<meta name="generator" content="Asciidoctor 1.5.4">
 
8
<meta name="author" content="Adam Stokes, Mike McCracken">
 
9
<title>conjure-up Developers Manual</title>
 
10
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
 
11
<style>
 
12
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
 
13
/* Remove comment around @import statement below when using as a custom stylesheet */
 
14
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
 
15
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
 
16
audio,canvas,video{display:inline-block}
 
17
audio:not([controls]){display:none;height:0}
 
18
[hidden],template{display:none}
 
19
script{display:none!important}
 
20
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
 
21
body{margin:0}
 
22
a{background:transparent}
 
23
a:focus{outline:thin dotted}
 
24
a:active,a:hover{outline:0}
 
25
h1{font-size:2em;margin:.67em 0}
 
26
abbr[title]{border-bottom:1px dotted}
 
27
b,strong{font-weight:bold}
 
28
dfn{font-style:italic}
 
29
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
 
30
mark{background:#ff0;color:#000}
 
31
code,kbd,pre,samp{font-family:monospace;font-size:1em}
 
32
pre{white-space:pre-wrap}
 
33
q{quotes:"\201C" "\201D" "\2018" "\2019"}
 
34
small{font-size:80%}
 
35
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
 
36
sup{top:-.5em}
 
37
sub{bottom:-.25em}
 
38
img{border:0}
 
39
svg:not(:root){overflow:hidden}
 
40
figure{margin:0}
 
41
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
 
42
legend{border:0;padding:0}
 
43
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
 
44
button,input{line-height:normal}
 
45
button,select{text-transform:none}
 
46
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
 
47
button[disabled],html input[disabled]{cursor:default}
 
48
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
 
49
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
 
50
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
 
51
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
 
52
textarea{overflow:auto;vertical-align:top}
 
53
table{border-collapse:collapse;border-spacing:0}
 
54
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
 
55
html,body{font-size:100%}
 
56
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
 
57
a:hover{cursor:pointer}
 
58
img,object,embed{max-width:100%;height:auto}
 
59
object,embed{height:100%}
 
60
img{-ms-interpolation-mode:bicubic}
 
61
.left{float:left!important}
 
62
.right{float:right!important}
 
63
.text-left{text-align:left!important}
 
64
.text-right{text-align:right!important}
 
65
.text-center{text-align:center!important}
 
66
.text-justify{text-align:justify!important}
 
67
.hide{display:none}
 
68
body{-webkit-font-smoothing:antialiased}
 
69
img,object,svg{display:inline-block;vertical-align:middle}
 
70
textarea{height:auto;min-height:50px}
 
71
select{width:100%}
 
72
.center{margin-left:auto;margin-right:auto}
 
73
.spread{width:100%}
 
74
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
 
75
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
 
76
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
 
77
a{color:#2156a5;text-decoration:underline;line-height:inherit}
 
78
a:hover,a:focus{color:#1d4b8f}
 
79
a img{border:none}
 
80
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
 
81
p aside{font-size:.875em;line-height:1.35;font-style:italic}
 
82
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
 
83
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
 
84
h1{font-size:2.125em}
 
85
h2{font-size:1.6875em}
 
86
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
 
87
h4,h5{font-size:1.125em}
 
88
h6{font-size:1em}
 
89
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
 
90
em,i{font-style:italic;line-height:inherit}
 
91
strong,b{font-weight:bold;line-height:inherit}
 
92
small{font-size:60%;line-height:inherit}
 
93
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
 
94
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
 
95
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
 
96
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
 
97
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
 
98
ul.square{list-style-type:square}
 
99
ul.circle{list-style-type:circle}
 
100
ul.disc{list-style-type:disc}
 
101
ul.no-bullet{list-style:none}
 
102
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
 
103
dl dt{margin-bottom:.3125em;font-weight:bold}
 
104
dl dd{margin-bottom:1.25em}
 
105
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
 
106
abbr{text-transform:none}
 
107
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
 
108
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
 
109
blockquote cite:before{content:"\2014 \0020"}
 
110
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
 
111
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
 
112
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
 
113
h1{font-size:2.75em}
 
114
h2{font-size:2.3125em}
 
115
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
 
116
h4{font-size:1.4375em}}
 
117
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
 
118
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
 
119
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
 
120
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
 
121
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
 
122
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
 
123
body{tab-size:4}
 
124
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
 
125
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
 
126
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
 
127
.clearfix:after,.float-group:after{clear:both}
 
128
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
 
129
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
 
130
.keyseq{color:rgba(51,51,51,.8)}
 
131
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
 
132
.keyseq kbd:first-child{margin-left:0}
 
133
.keyseq kbd:last-child{margin-right:0}
 
134
.menuseq,.menu{color:rgba(0,0,0,.8)}
 
135
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
 
136
b.button:before{content:"[";padding:0 3px 0 2px}
 
137
b.button:after{content:"]";padding:0 2px 0 3px}
 
138
p a>code:hover{color:rgba(0,0,0,.9)}
 
139
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
 
140
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
 
141
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
 
142
#content{margin-top:1.25em}
 
143
#content:before{content:none}
 
144
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
 
145
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
 
146
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
 
147
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
 
148
#header .details span:first-child{margin-left:-.125em}
 
149
#header .details span.email a{color:rgba(0,0,0,.85)}
 
150
#header .details br{display:none}
 
151
#header .details br+span:before{content:"\00a0\2013\00a0"}
 
152
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
 
153
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
 
154
#header #revnumber{text-transform:capitalize}
 
155
#header #revnumber:after{content:"\00a0"}
 
156
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
 
157
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
 
158
#toc>ul{margin-left:.125em}
 
159
#toc ul.sectlevel0>li>a{font-style:italic}
 
160
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
 
161
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
 
162
#toc li{line-height:1.3334;margin-top:.3334em}
 
163
#toc a{text-decoration:none}
 
164
#toc a:active{text-decoration:underline}
 
165
#toctitle{color:#7a2518;font-size:1.2em}
 
166
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
 
167
body.toc2{padding-left:15em;padding-right:0}
 
168
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
 
169
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
 
170
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
 
171
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
 
172
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
 
173
body.toc2.toc-right{padding-left:0;padding-right:15em}
 
174
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
 
175
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
 
176
#toc.toc2{width:20em}
 
177
#toc.toc2 #toctitle{font-size:1.375em}
 
178
#toc.toc2>ul{font-size:.95em}
 
179
#toc.toc2 ul ul{padding-left:1.25em}
 
180
body.toc2.toc-right{padding-left:0;padding-right:20em}}
 
181
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
 
182
#content #toc>:first-child{margin-top:0}
 
183
#content #toc>:last-child{margin-bottom:0}
 
184
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
 
185
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
 
186
.sect1{padding-bottom:.625em}
 
187
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
 
188
.sect1+.sect1{border-top:1px solid #efefed}
 
189
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
 
190
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
 
191
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
 
192
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
 
193
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
 
194
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
 
195
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
 
196
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
 
197
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
 
198
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
 
199
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
 
200
.admonitionblock>table td.icon{text-align:center;width:80px}
 
201
.admonitionblock>table td.icon img{max-width:none}
 
202
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
 
203
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
 
204
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
 
205
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
 
206
.exampleblock>.content>:first-child{margin-top:0}
 
207
.exampleblock>.content>:last-child{margin-bottom:0}
 
208
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
 
209
.sidebarblock>:first-child{margin-top:0}
 
210
.sidebarblock>:last-child{margin-bottom:0}
 
211
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
 
212
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
 
213
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
 
214
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
 
215
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
 
216
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
 
217
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
 
218
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
 
219
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
 
220
.listingblock pre.highlightjs{padding:0}
 
221
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
 
222
.listingblock pre.prettyprint{border-width:0}
 
223
.listingblock>.content{position:relative}
 
224
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
 
225
.listingblock:hover code[data-lang]:before{display:block}
 
226
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
 
227
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
 
228
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
 
229
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
 
230
table.pyhltable td.code{padding-left:.75em;padding-right:0}
 
231
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
 
232
pre.pygments .lineno{display:inline-block;margin-right:.25em}
 
233
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
 
234
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
 
235
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
 
236
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
 
237
.quoteblock blockquote{margin:0;padding:0;border:0}
 
238
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
 
239
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
 
240
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
 
241
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
 
242
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
 
243
.quoteblock .quoteblock blockquote:before{display:none}
 
244
.verseblock{margin:0 1em 1.25em 1em}
 
245
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
 
246
.verseblock pre strong{font-weight:400}
 
247
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
 
248
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
 
249
.quoteblock .attribution br,.verseblock .attribution br{display:none}
 
250
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
 
251
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
 
252
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
 
253
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
 
254
table.tableblock{max-width:100%;border-collapse:separate}
 
255
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
 
256
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
 
257
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
 
258
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
 
259
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
 
260
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
 
261
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
 
262
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
 
263
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
 
264
table.frame-all{border-width:1px}
 
265
table.frame-sides{border-width:0 1px}
 
266
table.frame-topbot{border-width:1px 0}
 
267
th.halign-left,td.halign-left{text-align:left}
 
268
th.halign-right,td.halign-right{text-align:right}
 
269
th.halign-center,td.halign-center{text-align:center}
 
270
th.valign-top,td.valign-top{vertical-align:top}
 
271
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
 
272
th.valign-middle,td.valign-middle{vertical-align:middle}
 
273
table thead th,table tfoot th{font-weight:bold}
 
274
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
 
275
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
 
276
p.tableblock>code:only-child{background:none;padding:0}
 
277
p.tableblock{font-size:1em}
 
278
td>div.verse{white-space:pre}
 
279
ol{margin-left:1.75em}
 
280
ul li ol{margin-left:1.5em}
 
281
dl dd{margin-left:1.125em}
 
282
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
 
283
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
 
284
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
 
285
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
 
286
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
 
287
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
 
288
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
 
289
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
 
290
ul.inline>li>*{display:block}
 
291
.unstyled dl dt{font-weight:400;font-style:normal}
 
292
ol.arabic{list-style-type:decimal}
 
293
ol.decimal{list-style-type:decimal-leading-zero}
 
294
ol.loweralpha{list-style-type:lower-alpha}
 
295
ol.upperalpha{list-style-type:upper-alpha}
 
296
ol.lowerroman{list-style-type:lower-roman}
 
297
ol.upperroman{list-style-type:upper-roman}
 
298
ol.lowergreek{list-style-type:lower-greek}
 
299
.hdlist>table,.colist>table{border:0;background:none}
 
300
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
 
301
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
 
302
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
 
303
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
 
304
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
 
305
.colist>table tr>td:last-of-type{padding:.25em 0}
 
306
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
 
307
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
 
308
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
 
309
.imageblock>.title{margin-bottom:0}
 
310
.imageblock.thumb,.imageblock.th{border-width:6px}
 
311
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
 
312
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
 
313
.image.left{margin-right:.625em}
 
314
.image.right{margin-left:.625em}
 
315
a.image{text-decoration:none;display:inline-block}
 
316
a.image object{pointer-events:none}
 
317
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
 
318
sup.footnote a,sup.footnoteref a{text-decoration:none}
 
319
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
 
320
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
 
321
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
 
322
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
 
323
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
 
324
#footnotes .footnote:last-of-type{margin-bottom:0}
 
325
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
 
326
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
 
327
.gist .file-data>table td.line-data{width:99%}
 
328
div.unbreakable{page-break-inside:avoid}
 
329
.big{font-size:larger}
 
330
.small{font-size:smaller}
 
331
.underline{text-decoration:underline}
 
332
.overline{text-decoration:overline}
 
333
.line-through{text-decoration:line-through}
 
334
.aqua{color:#00bfbf}
 
335
.aqua-background{background-color:#00fafa}
 
336
.black{color:#000}
 
337
.black-background{background-color:#000}
 
338
.blue{color:#0000bf}
 
339
.blue-background{background-color:#0000fa}
 
340
.fuchsia{color:#bf00bf}
 
341
.fuchsia-background{background-color:#fa00fa}
 
342
.gray{color:#606060}
 
343
.gray-background{background-color:#7d7d7d}
 
344
.green{color:#006000}
 
345
.green-background{background-color:#007d00}
 
346
.lime{color:#00bf00}
 
347
.lime-background{background-color:#00fa00}
 
348
.maroon{color:#600000}
 
349
.maroon-background{background-color:#7d0000}
 
350
.navy{color:#000060}
 
351
.navy-background{background-color:#00007d}
 
352
.olive{color:#606000}
 
353
.olive-background{background-color:#7d7d00}
 
354
.purple{color:#600060}
 
355
.purple-background{background-color:#7d007d}
 
356
.red{color:#bf0000}
 
357
.red-background{background-color:#fa0000}
 
358
.silver{color:#909090}
 
359
.silver-background{background-color:#bcbcbc}
 
360
.teal{color:#006060}
 
361
.teal-background{background-color:#007d7d}
 
362
.white{color:#bfbfbf}
 
363
.white-background{background-color:#fafafa}
 
364
.yellow{color:#bfbf00}
 
365
.yellow-background{background-color:#fafa00}
 
366
span.icon>.fa{cursor:default}
 
367
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
 
368
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
 
369
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
 
370
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
 
371
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
 
372
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
 
373
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
 
374
.conum[data-value] *{color:#fff!important}
 
375
.conum[data-value]+b{display:none}
 
376
.conum[data-value]:after{content:attr(data-value)}
 
377
pre .conum[data-value]{position:relative;top:-.125em}
 
378
b.conum *{color:inherit!important}
 
379
.conum:not([data-value]):empty{display:none}
 
380
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
 
381
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
 
382
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
 
383
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
 
384
p{margin-bottom:1.25rem}
 
385
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
 
386
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
 
387
.print-only{display:none!important}
 
388
@media print{@page{margin:1.25cm .75cm}
 
389
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
 
390
a{color:inherit!important;text-decoration:underline!important}
 
391
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
 
392
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
 
393
abbr[title]:after{content:" (" attr(title) ")"}
 
394
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
 
395
thead{display:table-header-group}
 
396
svg{max-width:100%}
 
397
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
 
398
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
 
399
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
 
400
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
 
401
.sect1{padding-bottom:0!important}
 
402
.sect1+.sect1{border:0!important}
 
403
#header>h1:first-child{margin-top:1.25rem}
 
404
body.book #header{text-align:center}
 
405
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
 
406
body.book #header .details{border:0!important;display:block;padding:0!important}
 
407
body.book #header .details span:first-child{margin-left:0!important}
 
408
body.book #header .details br{display:block}
 
409
body.book #header .details br+span:before{content:none!important}
 
410
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
 
411
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
 
412
.listingblock code[data-lang]:before{display:block}
 
413
#footer{background:none!important;padding:0 .9375em}
 
414
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
 
415
.hide-on-print{display:none!important}
 
416
.print-only{display:block!important}
 
417
.hide-for-print{display:none!important}
 
418
.show-for-print{display:inherit!important}}
 
419
</style>
 
420
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
 
421
<style>
 
422
.listingblock .pygments .hll { background-color: #ffffcc }
 
423
.listingblock .pygments  { background: #f8f8f8; }
 
424
.listingblock .pygments .tok-c { color: #408080; font-style: italic } /* Comment */
 
425
.listingblock .pygments .tok-err { border: 1px solid #FF0000 } /* Error */
 
426
.listingblock .pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */
 
427
.listingblock .pygments .tok-o { color: #666666 } /* Operator */
 
428
.listingblock .pygments .tok-ch { color: #408080; font-style: italic } /* Comment.Hashbang */
 
429
.listingblock .pygments .tok-cm { color: #408080; font-style: italic } /* Comment.Multiline */
 
430
.listingblock .pygments .tok-cp { color: #BC7A00 } /* Comment.Preproc */
 
431
.listingblock .pygments .tok-cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
 
432
.listingblock .pygments .tok-c1 { color: #408080; font-style: italic } /* Comment.Single */
 
433
.listingblock .pygments .tok-cs { color: #408080; font-style: italic } /* Comment.Special */
 
434
.listingblock .pygments .tok-gd { color: #A00000 } /* Generic.Deleted */
 
435
.listingblock .pygments .tok-ge { font-style: italic } /* Generic.Emph */
 
436
.listingblock .pygments .tok-gr { color: #FF0000 } /* Generic.Error */
 
437
.listingblock .pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */
 
438
.listingblock .pygments .tok-gi { color: #00A000 } /* Generic.Inserted */
 
439
.listingblock .pygments .tok-go { color: #888888 } /* Generic.Output */
 
440
.listingblock .pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */
 
441
.listingblock .pygments .tok-gs { font-weight: bold } /* Generic.Strong */
 
442
.listingblock .pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */
 
443
.listingblock .pygments .tok-gt { color: #0044DD } /* Generic.Traceback */
 
444
.listingblock .pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */
 
445
.listingblock .pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
 
446
.listingblock .pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
 
447
.listingblock .pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */
 
448
.listingblock .pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
 
449
.listingblock .pygments .tok-kt { color: #B00040 } /* Keyword.Type */
 
450
.listingblock .pygments .tok-m { color: #666666 } /* Literal.Number */
 
451
.listingblock .pygments .tok-s { color: #BA2121 } /* Literal.String */
 
452
.listingblock .pygments .tok-na { color: #7D9029 } /* Name.Attribute */
 
453
.listingblock .pygments .tok-nb { color: #008000 } /* Name.Builtin */
 
454
.listingblock .pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */
 
455
.listingblock .pygments .tok-no { color: #880000 } /* Name.Constant */
 
456
.listingblock .pygments .tok-nd { color: #AA22FF } /* Name.Decorator */
 
457
.listingblock .pygments .tok-ni { color: #999999; font-weight: bold } /* Name.Entity */
 
458
.listingblock .pygments .tok-ne { color: #D2413A; font-weight: bold } /* Name.Exception */
 
459
.listingblock .pygments .tok-nf { color: #0000FF } /* Name.Function */
 
460
.listingblock .pygments .tok-nl { color: #A0A000 } /* Name.Label */
 
461
.listingblock .pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
 
462
.listingblock .pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */
 
463
.listingblock .pygments .tok-nv { color: #19177C } /* Name.Variable */
 
464
.listingblock .pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
 
465
.listingblock .pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */
 
466
.listingblock .pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */
 
467
.listingblock .pygments .tok-mf { color: #666666 } /* Literal.Number.Float */
 
468
.listingblock .pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */
 
469
.listingblock .pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */
 
470
.listingblock .pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */
 
471
.listingblock .pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */
 
472
.listingblock .pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */
 
473
.listingblock .pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
 
474
.listingblock .pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */
 
475
.listingblock .pygments .tok-se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
 
476
.listingblock .pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */
 
477
.listingblock .pygments .tok-si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
 
478
.listingblock .pygments .tok-sx { color: #008000 } /* Literal.String.Other */
 
479
.listingblock .pygments .tok-sr { color: #BB6688 } /* Literal.String.Regex */
 
480
.listingblock .pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */
 
481
.listingblock .pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */
 
482
.listingblock .pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */
 
483
.listingblock .pygments .tok-vc { color: #19177C } /* Name.Variable.Class */
 
484
.listingblock .pygments .tok-vg { color: #19177C } /* Name.Variable.Global */
 
485
.listingblock .pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */
 
486
.listingblock .pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */
 
487
</style>
 
488
</head>
 
489
<body class="article toc2 toc-left">
 
490
<div id="header">
 
491
<h1>conjure-up Developers Manual</h1>
 
492
<div class="details">
 
493
<span id="author" class="author">Adam Stokes</span><br>
 
494
<span id="email" class="email"><a href="https://github.com/battlemidget">@battlemidget</a></span><br>
 
495
<span id="author2" class="author">Mike McCracken</span><br>
 
496
<span id="email2" class="email"><a href="https://github.com/mmcc">@mmcc</a></span><br>
 
497
<span id="revnumber">version 2.0.1~beta1,</span>
 
498
<span id="revdate">2016-09-12</span>
 
499
<br><span id="revremark">WIP</span>
 
500
</div>
 
501
<div id="toc" class="toc2">
 
502
<div id="toctitle">Table of Contents</div>
 
503
<ul class="sectlevel1">
 
504
<li><a href="#spell-anatomy">Anatomy of a conjure-up spell</a>
 
505
<ul class="sectlevel2">
 
506
<li><a href="#spell-metadata">Spell Metadata</a></li>
 
507
<li><a href="#spell-steps">Steps</a>
 
508
<ul class="sectlevel3">
 
509
<li><a href="#pre-deploy">00_pre-deploy</a></li>
 
510
<li><a href="#deploy-done">00_deploy-done</a></li>
 
511
<li><a href="#post-processing-steps">Post processing</a>
 
512
<ul class="sectlevel4">
 
513
<li><a href="#_additional_input">Additional Input</a></li>
 
514
</ul>
 
515
</li>
 
516
</ul>
 
517
</li>
 
518
</ul>
 
519
</li>
 
520
</ul>
 
521
</div>
 
522
</div>
 
523
<div id="content">
 
524
<div id="preamble">
 
525
<div class="sectionbody">
 
526
<div class="paragraph">
 
527
<p>At the heart of <strong>conjure-up</strong> are spells. They consist of all the information
 
528
required to deploy your applications and walk the user through getting started
 
529
as quickly as possible.</p>
 
530
</div>
 
531
<div class="paragraph">
 
532
<p>There are 2 main parts that make up a spell. The first being a <strong>Juju bundle</strong>,
 
533
these are your blueprints for defining the amount of units for each application
 
534
along with any default configuration options you wish to expose to the user for
 
535
modification.</p>
 
536
</div>
 
537
<div class="paragraph">
 
538
<p>The second part is the additional data added to the spell to be <strong>conjure-up</strong>
 
539
enabled. This contains your metadata which describes the spell and a set of
 
540
steps that you define for a user to walkthrough. This allows you as a spell
 
541
author to ensure that a user can learn about your application and at the end
 
542
know exactly what to do next in order to make the most out of your application.</p>
 
543
</div>
 
544
<div class="paragraph">
 
545
<p>It is recommended to learn the <a href="#spell-anatomy">Anatomy of a conjure-up spell</a>
 
546
in order to get started building your spell!</p>
 
547
</div>
 
548
</div>
 
549
</div>
 
550
<div class="sect1">
 
551
<h2 id="spell-anatomy">Anatomy of a conjure-up spell</h2>
 
552
<div class="sectionbody">
 
553
<div class="paragraph">
 
554
<p>We will start with the directory layout of a typical spell. Some of this will be
 
555
familiar as we build on the existing Juju bundle specification.</p>
 
556
</div>
 
557
<div class="listingblock">
 
558
<div class="content">
 
559
<pre class="pygments highlight"><code data-lang="bash">my-super-application&gt;
 
560
   - bundle.yaml <i class="conum" data-value="1"></i><b>(1)</b>
 
561
   - README.md
 
562
   - metadata.yaml <i class="conum" data-value="2"></i><b>(2)</b>
 
563
   - steps/ <i class="conum" data-value="3"></i><b>(3)</b>
 
564
     - 00_deploy-done
 
565
     - 00_pre-deploy
 
566
     - step-01_my_first_step
 
567
     - step-01_my_first_step.yaml</code></pre>
 
568
</div>
 
569
</div>
 
570
<div class="colist arabic">
 
571
<table>
 
572
<tr>
 
573
<td><i class="conum" data-value="1"></i><b>1</b></td>
 
574
<td>More information on creating Juju <a href="https://jujucharms.com/docs/stable/charms-bundles">bundle files</a></td>
 
575
</tr>
 
576
<tr>
 
577
<td><i class="conum" data-value="2"></i><b>2</b></td>
 
578
<td><a href="#spell-metadata">Spell Metadata</a></td>
 
579
</tr>
 
580
<tr>
 
581
<td><i class="conum" data-value="3"></i><b>3</b></td>
 
582
<td>Excutable scripts to be run prior to deployment, to check when a deployment is finished, and steps to be processed for configuring deployment. See <a href="#spell-steps">Steps</a> for more information.</td>
 
583
</tr>
 
584
</table>
 
585
</div>
 
586
<div class="sect2">
 
587
<h3 id="spell-metadata">Spell Metadata</h3>
 
588
<div class="paragraph">
 
589
<p>The spell metadata contains properties that are useful for conjure-up to process
 
590
certain aspects of a spell. Available properties are as follows:</p>
 
591
</div>
 
592
<div class="dlist">
 
593
<dl>
 
594
<dt class="hdlist1">friendly-name</dt>
 
595
<dd>
 
596
<p>This is used during the spell selection within conjure-up.</p>
 
597
</dd>
 
598
<dt class="hdlist1">cloud-whitelist</dt>
 
599
<dd>
 
600
<p>A list of Public clouds available for a spell.</p>
 
601
</dd>
 
602
<dt class="hdlist1">cloud-blacklist</dt>
 
603
<dd>
 
604
<p>A list of Public clouds that are known to not work with a spell.</p>
 
605
</dd>
 
606
<dt class="hdlist1">packages</dt>
 
607
<dd>
 
608
<p>Additional <code>apt</code> packages required for spell.</p>
 
609
</dd>
 
610
<dt class="hdlist1">options-whitelist</dt>
 
611
<dd>
 
612
<p>Additional charm options to be exposed for editing within conjure-up.</p>
 
613
</dd>
 
614
</dl>
 
615
</div>
 
616
<div class="listingblock">
 
617
<div class="title">metadata.yaml example</div>
 
618
<div class="content">
 
619
<pre class="pygments highlight"><code data-lang="yaml"><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">cloud-whitelist</span><span class="tok-p tok-p-Indicator">:</span>
 
620
<span class="tok-p tok-p-Indicator">-</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">localhost</span>
 
621
<span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">friendly-name</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">OpenStack with NovaLXD</span>
 
622
<span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">options-whitelist</span><span class="tok-p tok-p-Indicator">:</span>
 
623
  <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">keystone</span><span class="tok-p tok-p-Indicator">:</span>
 
624
  <span class="tok-p tok-p-Indicator">-</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">admin-password</span>
 
625
  <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">lxd</span><span class="tok-p tok-p-Indicator">:</span>
 
626
  <span class="tok-p tok-p-Indicator">-</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block-devices</span>
 
627
  <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">mysql</span><span class="tok-p tok-p-Indicator">:</span>
 
628
  <span class="tok-p tok-p-Indicator">-</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">max-connections</span>
 
629
  <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">neutron-gateway</span><span class="tok-p tok-p-Indicator">:</span>
 
630
  <span class="tok-p tok-p-Indicator">-</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ext-port</span>
 
631
  <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">nova-compute</span><span class="tok-p tok-p-Indicator">:</span>
 
632
  <span class="tok-p tok-p-Indicator">-</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">virt-type</span></code></pre>
 
633
</div>
 
634
</div>
 
635
</div>
 
636
<div class="sect2">
 
637
<h3 id="spell-steps">Steps</h3>
 
638
<div class="paragraph">
 
639
<p>During a deployment, <strong>conjure-up</strong> will always check for and run a predefined set of scripts:</p>
 
640
</div>
 
641
<div class="dlist">
 
642
<dl>
 
643
<dt class="hdlist1">00_pre-deploy</dt>
 
644
<dd>
 
645
<p>This script contains necessary instructions for configuring a system prior to a deployment (<a href="#pre-deploy">00_pre-deploy</a>).</p>
 
646
</dd>
 
647
<dt class="hdlist1">00_deploy-done</dt>
 
648
<dd>
 
649
<p>This script will contain instructions for verifying that deployment has finished and is ready for its next steps (<a href="#deploy-done">00_deploy-done</a>).</p>
 
650
</dd>
 
651
<dt class="hdlist1">step-##_a_step</dt>
 
652
<dd>
 
653
<p>This is an alpha numerical script that will be executed in order to perform any actions necessary to provide a turn key and usuable deployment.</p>
 
654
</dd>
 
655
</dl>
 
656
</div>
 
657
<div class="sect3">
 
658
<h4 id="pre-deploy">00_pre-deploy</h4>
 
659
<div class="paragraph">
 
660
<p>In some cases, like OpenStack with NovaLXD modifications need to be made to the
 
661
LXD container profile to allow for certain kernel modules and networking to be
 
662
enabled. This needs to happen prior to any applications being deployed in the container.</p>
 
663
</div>
 
664
<div class="listingblock">
 
665
<div class="title">An example of 00_pre-deploy for OpenStack with NovaLXD</div>
 
666
<div class="content">
 
667
<pre class="pygments highlight"><code data-lang="python"><span class="tok-ch">#!/usr/bin/env python3</span>
 
668
 
 
669
<span class="tok-kn">import</span> <span class="tok-nn">os</span>
 
670
<span class="tok-kn">import</span> <span class="tok-nn">time</span>
 
671
<span class="tok-kn">from</span> <span class="tok-nn">subprocess</span> <span class="tok-kn">import</span> <span class="tok-n">run</span><span class="tok-p">,</span> <span class="tok-n">PIPE</span><span class="tok-p">,</span> <span class="tok-n">CalledProcessError</span>
 
672
<span class="tok-kn">from</span> <span class="tok-nn">conjureup.hooklib.writer</span> <span class="tok-kn">import</span> <span class="tok-n">success</span><span class="tok-p">,</span> <span class="tok-n">error</span><span class="tok-p">,</span> <span class="tok-n">log</span>
 
673
 
 
674
<span class="tok-n">SCRIPTPATH</span> <span class="tok-o">=</span> <span class="tok-n">os</span><span class="tok-o">.</span><span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">dirname</span><span class="tok-p">(</span><span class="tok-n">os</span><span class="tok-o">.</span><span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">abspath</span><span class="tok-p">(</span><span class="tok-n">__file__</span><span class="tok-p">))</span>
 
675
 
 
676
 
 
677
<span class="tok-n">provider_type</span> <span class="tok-o">=</span> <span class="tok-n">os</span><span class="tok-o">.</span><span class="tok-n">environ</span><span class="tok-o">.</span><span class="tok-n">get</span><span class="tok-p">(</span><span class="tok-s1">&#39;JUJU_PROVIDERTYPE&#39;</span><span class="tok-p">,</span> <span class="tok-bp">None</span><span class="tok-p">)</span> <i class="conum" data-value="1"></i><b>(1)</b>
 
678
 
 
679
<span class="tok-k">if</span> <span class="tok-n">provider_type</span> <span class="tok-o">==</span> <span class="tok-s2">&quot;lxd&quot;</span><span class="tok-p">:</span> <i class="conum" data-value="2"></i><b>(2)</b>
 
680
    <span class="tok-n">log</span><span class="tok-o">.</span><span class="tok-n">debug</span><span class="tok-p">(</span><span class="tok-s2">&quot;Running pre-deploy for OpenStack&quot;</span><span class="tok-p">)</span>
 
681
    <span class="tok-c1"># Give LXD enough time to learn about the profile</span>
 
682
    <span class="tok-n">time</span><span class="tok-o">.</span><span class="tok-n">sleep</span><span class="tok-p">(</span><span class="tok-mi">5</span><span class="tok-p">)</span>
 
683
    <span class="tok-k">try</span><span class="tok-p">:</span>
 
684
        <span class="tok-n">profilename</span> <span class="tok-o">=</span> <span class="tok-n">run</span><span class="tok-p">(</span><span class="tok-s1">&#39;juju switch | cut -d/ -f2&#39;</span><span class="tok-p">,</span>
 
685
                          <span class="tok-n">shell</span><span class="tok-o">=</span><span class="tok-bp">True</span><span class="tok-p">,</span>
 
686
                          <span class="tok-n">stdout</span><span class="tok-o">=</span><span class="tok-n">PIPE</span><span class="tok-p">,</span>
 
687
                          <span class="tok-n">stderr</span><span class="tok-o">=</span><span class="tok-n">PIPE</span><span class="tok-p">)</span>
 
688
        <span class="tok-n">profilename</span> <span class="tok-o">=</span> <span class="tok-n">profilename</span><span class="tok-o">.</span><span class="tok-n">stdout</span><span class="tok-o">.</span><span class="tok-n">decode</span><span class="tok-p">()</span><span class="tok-o">.</span><span class="tok-n">strip</span><span class="tok-p">()</span>
 
689
    <span class="tok-k">except</span> <span class="tok-n">CalledProcessError</span> <span class="tok-k">as</span> <span class="tok-n">e</span><span class="tok-p">:</span>
 
690
        <span class="tok-n">error</span><span class="tok-p">(</span><span class="tok-n">e</span><span class="tok-p">)</span>
 
691
 
 
692
    <span class="tok-n">log</span><span class="tok-o">.</span><span class="tok-n">debug</span><span class="tok-p">(</span><span class="tok-s2">&quot;Processing lxd profile: {}&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">profilename</span><span class="tok-p">))</span>
 
693
 
 
694
    <span class="tok-k">try</span><span class="tok-p">:</span>
 
695
        <span class="tok-n">profile_edit</span> <span class="tok-o">=</span> <span class="tok-n">run</span><span class="tok-p">(</span>
 
696
            <span class="tok-s1">&#39;sed &quot;s/##MODEL##/{profile}/&quot; &#39;</span>
 
697
            <span class="tok-s1">&#39;{scriptpath}/lxd-profile.yaml | &#39;</span>
 
698
            <span class="tok-s1">&#39;lxc profile edit &quot;juju-{profile}&quot;&#39;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span>
 
699
                <span class="tok-n">profile</span><span class="tok-o">=</span><span class="tok-n">profilename</span><span class="tok-p">,</span>
 
700
                <span class="tok-n">scriptpath</span><span class="tok-o">=</span><span class="tok-n">SCRIPTPATH</span><span class="tok-p">),</span>
 
701
            <span class="tok-n">shell</span><span class="tok-o">=</span><span class="tok-bp">True</span><span class="tok-p">,</span>
 
702
            <span class="tok-n">stdout</span><span class="tok-o">=</span><span class="tok-n">PIPE</span><span class="tok-p">,</span>
 
703
            <span class="tok-n">stderr</span><span class="tok-o">=</span><span class="tok-n">PIPE</span><span class="tok-p">)</span> <i class="conum" data-value="3"></i><b>(3)</b>
 
704
    <span class="tok-k">except</span> <span class="tok-n">CalledProcessError</span> <span class="tok-k">as</span> <span class="tok-n">e</span><span class="tok-p">:</span>
 
705
        <span class="tok-n">error</span><span class="tok-p">(</span><span class="tok-n">e</span><span class="tok-p">)</span>
 
706
 
 
707
    <span class="tok-k">if</span> <span class="tok-n">profile_edit</span><span class="tok-o">.</span><span class="tok-n">returncode</span> <span class="tok-o">&gt;</span> <span class="tok-mi">0</span><span class="tok-p">:</span>
 
708
        <span class="tok-n">error</span><span class="tok-p">(</span><span class="tok-n">profile_edit</span><span class="tok-o">.</span><span class="tok-n">stderr</span><span class="tok-p">)</span>
 
709
 
 
710
<span class="tok-n">success</span><span class="tok-p">(</span><span class="tok-s2">&quot;Successful pre-deploy.&quot;</span><span class="tok-p">)</span> <i class="conum" data-value="4"></i><b>(4)</b></code></pre>
 
711
</div>
 
712
</div>
 
713
<div class="colist arabic">
 
714
<table>
 
715
<tr>
 
716
<td><i class="conum" data-value="1"></i><b>1</b></td>
 
717
<td>Is exposed as an environment variable to check the type of public cloud this script is running in.</td>
 
718
</tr>
 
719
<tr>
 
720
<td><i class="conum" data-value="2"></i><b>2</b></td>
 
721
<td>Since we are doing this on a container it makes sense to only work with the <strong>LXD</strong> type.</td>
 
722
</tr>
 
723
<tr>
 
724
<td><i class="conum" data-value="3"></i><b>3</b></td>
 
725
<td>This performs an inplace update of the LXD profile. Due to the nature of LXD this profile will be available immediately even on containers that have already started.</td>
 
726
</tr>
 
727
<tr>
 
728
<td><i class="conum" data-value="4"></i><b>4</b></td>
 
729
<td>Helper function part of the builtin hooklib for writing steps. This lets conjure-up know that this pre-deploy task has completed without error.</td>
 
730
</tr>
 
731
</table>
 
732
</div>
 
733
</div>
 
734
<div class="sect3">
 
735
<h4 id="deploy-done">00_deploy-done</h4>
 
736
<div class="paragraph">
 
737
<p>Before we can process any additional steps we need to wait for all the deployed applications to become in a <strong>ready</strong> state. Below demonstrates a couple of ways to check for an error of the unit or machine:</p>
 
738
</div>
 
739
<div class="listingblock">
 
740
<div class="title">An example of 00_deploy-done for OpenStack with NovaLXD</div>
 
741
<div class="content">
 
742
<pre class="pygments highlight"><code data-lang="python"><span class="tok-ch">#!/usr/bin/env python3</span>
 
743
<span class="tok-kn">from</span> <span class="tok-nn">conjureup.hooklib.writer</span> <span class="tok-kn">import</span> <span class="tok-n">success</span><span class="tok-p">,</span> <span class="tok-n">fail</span><span class="tok-p">,</span> <span class="tok-n">error</span><span class="tok-p">,</span> <span class="tok-n">log</span>
 
744
<span class="tok-kn">from</span> <span class="tok-nn">conjureup.hooklib</span> <span class="tok-kn">import</span> <span class="tok-n">juju</span>
 
745
 
 
746
<span class="tok-n">log</span><span class="tok-o">.</span><span class="tok-n">debug</span><span class="tok-p">(</span><span class="tok-s2">&quot;Running deploy-done for OpenStack installation.&quot;</span><span class="tok-p">)</span>
 
747
<span class="tok-n">agent_states</span> <span class="tok-o">=</span> <span class="tok-n">juju</span><span class="tok-o">.</span><span class="tok-n">agent_states</span><span class="tok-p">()</span> <i class="conum" data-value="1"></i><b>(1)</b>
 
748
 
 
749
<span class="tok-n">errored_units</span> <span class="tok-o">=</span> <span class="tok-p">[(</span><span class="tok-n">unit_name</span><span class="tok-p">,</span> <span class="tok-n">message</span><span class="tok-p">)</span> <span class="tok-k">for</span> <span class="tok-n">unit_name</span><span class="tok-p">,</span> <span class="tok-n">state</span><span class="tok-p">,</span> <span class="tok-n">message</span>
 
750
                 <span class="tok-ow">in</span> <span class="tok-n">agent_states</span> <span class="tok-k">if</span> <span class="tok-n">state</span> <span class="tok-o">==</span> <span class="tok-s2">&quot;error&quot;</span><span class="tok-p">]</span> <i class="conum" data-value="2"></i><b>(2)</b>
 
751
<span class="tok-k">if</span> <span class="tok-nb">len</span><span class="tok-p">(</span><span class="tok-n">errored_units</span><span class="tok-p">)</span> <span class="tok-o">&gt;</span> <span class="tok-mi">0</span><span class="tok-p">:</span>
 
752
    <span class="tok-n">errs</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;</span><span class="tok-se">\n</span><span class="tok-s2">&quot;</span><span class="tok-o">.</span><span class="tok-n">join</span><span class="tok-p">([</span><span class="tok-s2">&quot;{}: {}&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">n</span><span class="tok-p">,</span> <span class="tok-n">m</span><span class="tok-p">)</span> <span class="tok-k">for</span> <span class="tok-n">n</span><span class="tok-p">,</span> <span class="tok-n">m</span> <span class="tok-ow">in</span> <span class="tok-n">errored_units</span><span class="tok-p">])</span>
 
753
    <span class="tok-n">error</span><span class="tok-p">(</span><span class="tok-s1">&#39;Deployment errors:</span><span class="tok-se">\n</span><span class="tok-s1">{}&#39;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">errs</span><span class="tok-p">))</span>
 
754
 
 
755
<span class="tok-n">machines</span> <span class="tok-o">=</span> <span class="tok-n">juju</span><span class="tok-o">.</span><span class="tok-n">machine_states</span><span class="tok-p">()</span>
 
756
<span class="tok-n">errored_machines</span> <span class="tok-o">=</span> <span class="tok-p">[(</span><span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-n">err</span><span class="tok-p">)</span> <span class="tok-k">for</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-n">status</span><span class="tok-p">,</span> <span class="tok-n">err</span> <span class="tok-ow">in</span> <span class="tok-n">machines</span>
 
757
                    <span class="tok-k">if</span> <span class="tok-n">status</span> <span class="tok-o">==</span> <span class="tok-s2">&quot;error&quot;</span><span class="tok-p">]</span> <i class="conum" data-value="3"></i><b>(3)</b>
 
758
<span class="tok-k">if</span> <span class="tok-nb">len</span><span class="tok-p">(</span><span class="tok-n">errored_machines</span><span class="tok-p">)</span> <span class="tok-o">&gt;</span> <span class="tok-mi">0</span><span class="tok-p">:</span>
 
759
    <span class="tok-n">errs</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;</span><span class="tok-se">\n</span><span class="tok-s2">&quot;</span><span class="tok-o">.</span><span class="tok-n">join</span><span class="tok-p">([</span><span class="tok-s2">&quot;{}: {}&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">n</span><span class="tok-p">,</span> <span class="tok-n">m</span><span class="tok-p">)</span> <span class="tok-k">for</span> <span class="tok-n">n</span><span class="tok-p">,</span> <span class="tok-n">m</span> <span class="tok-ow">in</span> <span class="tok-n">errored_machines</span><span class="tok-p">])</span>
 
760
    <span class="tok-n">error</span><span class="tok-p">(</span><span class="tok-s2">&quot;Machine creation errors:</span><span class="tok-se">\n</span><span class="tok-s2">{}&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">errs</span><span class="tok-p">))</span>
 
761
 
 
762
<span class="tok-k">if</span> <span class="tok-nb">len</span><span class="tok-p">(</span><span class="tok-n">agent_states</span><span class="tok-p">)</span> <span class="tok-o">==</span> <span class="tok-mi">0</span><span class="tok-p">:</span>
 
763
    <span class="tok-n">fail</span><span class="tok-p">(</span><span class="tok-s1">&#39;Applications are still deploying&#39;</span><span class="tok-p">)</span> <i class="conum" data-value="4"></i><b>(4)</b>
 
764
 
 
765
<span class="tok-k">if</span> <span class="tok-nb">all</span><span class="tok-p">([</span><span class="tok-n">state</span> <span class="tok-o">==</span> <span class="tok-s1">&#39;active&#39;</span> <span class="tok-k">for</span> <span class="tok-n">_</span><span class="tok-p">,</span> <span class="tok-n">state</span><span class="tok-p">,</span> <span class="tok-n">_</span> <span class="tok-ow">in</span> <span class="tok-n">agent_states</span><span class="tok-p">]):</span>
 
766
    <span class="tok-n">success</span><span class="tok-p">(</span><span class="tok-s1">&#39;Applications are ready&#39;</span><span class="tok-p">)</span> <i class="conum" data-value="5"></i><b>(5)</b>
 
767
 
 
768
<span class="tok-n">fail</span><span class="tok-p">(</span><span class="tok-s1">&#39;Applications not ready yet&#39;</span><span class="tok-p">)</span></code></pre>
 
769
</div>
 
770
</div>
 
771
<div class="colist arabic">
 
772
<table>
 
773
<tr>
 
774
<td><i class="conum" data-value="1"></i><b>1</b></td>
 
775
<td>Part of the conjure-up hooklib for grabbing the status output from Juju. This is similar to running <code>juju status --format yaml</code></td>
 
776
</tr>
 
777
<tr>
 
778
<td><i class="conum" data-value="2"></i><b>2</b></td>
 
779
<td>Check for any Application units that have errored and trigger a failure in conjure-up to be seen by the user.</td>
 
780
</tr>
 
781
<tr>
 
782
<td><i class="conum" data-value="3"></i><b>3</b></td>
 
783
<td>Check for any Machines that have errored and trigger a failure in conjure-up to be seen by the user.</td>
 
784
</tr>
 
785
<tr>
 
786
<td><i class="conum" data-value="4"></i><b>4</b></td>
 
787
<td>This triggers a non fatal failure which lets conjure-up know that at least 1 or more applications are still pending.</td>
 
788
</tr>
 
789
<tr>
 
790
<td><i class="conum" data-value="5"></i><b>5</b></td>
 
791
<td>All applications, units, and machines are in a successful state and which triggers conjure-up to move on to the <a href="#post-processing-steps">Post processing</a></td>
 
792
</tr>
 
793
</table>
 
794
</div>
 
795
</div>
 
796
<div class="sect3">
 
797
<h4 id="post-processing-steps">Post processing</h4>
 
798
<div class="paragraph">
 
799
<p>There are 2 sections to post processing. The first section is the <strong>step
 
800
metadata</strong>, this metadata provides conjure-up some context about what to display
 
801
to the user for configuration and how to pass that information to the processing
 
802
script.</p>
 
803
</div>
 
804
<div class="paragraph">
 
805
<p>Steps are created alpha numerically and have 2 files associated. The first file
 
806
being the step script named <strong>step-01_keypair</strong>. The second file is the metadata
 
807
for that step named <strong>step-01_keypair.yaml</strong>.</p>
 
808
</div>
 
809
<div class="paragraph">
 
810
<p>The metadata for a step consists of:</p>
 
811
</div>
 
812
<div class="dlist">
 
813
<dl>
 
814
<dt class="hdlist1">title</dt>
 
815
<dd>
 
816
<p>A short title of the step</p>
 
817
</dd>
 
818
<dt class="hdlist1">description</dt>
 
819
<dd>
 
820
<p>A summary of what this steps does</p>
 
821
</dd>
 
822
<dt class="hdlist1">viewable</dt>
 
823
<dd>
 
824
<p>Boolean to indicate if this steps summary and actions are seen within conjure-up</p>
 
825
</dd>
 
826
<dt class="hdlist1">required</dt>
 
827
<dd>
 
828
<p>Boolean to indicate that this step is a requirement and has to be run</p>
 
829
</dd>
 
830
<dt class="hdlist1">additional-input</dt>
 
831
<dd>
 
832
<p>Additional configuration variables that can be changed by the user within conjure-up <a href="#additional-input">[additional-input]</a></p>
 
833
</dd>
 
834
</dl>
 
835
</div>
 
836
<div class="sect4">
 
837
<h5 id="_additional_input">Additional Input</h5>
 
838
<div class="paragraph">
 
839
<p>This section of the step describes the configuration object and how it is to be
 
840
displayed to the user within conjure-up and how a step would utilize the result
 
841
from the user input.</p>
 
842
</div>
 
843
<div class="paragraph">
 
844
<p>The additional input has the following properties:</p>
 
845
</div>
 
846
<div class="dlist">
 
847
<dl>
 
848
<dt class="hdlist1">label</dt>
 
849
<dd>
 
850
<p>Rendered label describing the input</p>
 
851
</dd>
 
852
<dt class="hdlist1">key</dt>
 
853
<dd>
 
854
<p>The result of input is stored in this key which is exposed via environment variables</p>
 
855
</dd>
 
856
<dt class="hdlist1">type</dt>
 
857
<dd>
 
858
<p>Type of input</p>
 
859
</dd>
 
860
<dt class="hdlist1">default</dt>
 
861
<dd>
 
862
<p>Default value for input</p>
 
863
</dd>
 
864
</dl>
 
865
</div>
 
866
<div class="listingblock">
 
867
<div class="title">A full example of step-01_keypair.yaml</div>
 
868
<div class="content">
 
869
<pre class="pygments highlight"><code data-lang="yaml"><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">title</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">SSH</span>
 
870
<span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">description</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-p tok-p-Indicator">|</span>
 
871
  <span class="tok-no">Import SSH keypairs into OpenStack. This allows you to access the newly deployed instances via SSH with your current user. If you are not sure about the location of a ssh key leave it as is and we will create one automatically.</span>
 
872
<span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">viewable</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">True</span>
 
873
<span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">required</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">True</span>
 
874
<span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">additional-input</span><span class="tok-p tok-p-Indicator">:</span>
 
875
  <span class="tok-p tok-p-Indicator">-</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">label</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">SSH public key path</span>
 
876
    <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">key</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">SSHPUBLICKEY</span>
 
877
    <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">type</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">text</span>
 
878
    <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">default</span><span class="tok-p tok-p-Indicator">:</span> <span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">~/.ssh/id_rsa.pub</span></code></pre>
 
879
</div>
 
880
</div>
 
881
<div class="listingblock">
 
882
<div class="title">An example the step script</div>
 
883
<div class="content">
 
884
<pre class="pygments highlight"><code data-lang="python"><span class="tok-ch">#!/usr/bin/env python3</span>
 
885
 
 
886
<span class="tok-c1"># Global imports</span>
 
887
<span class="tok-kn">import</span> <span class="tok-nn">os</span>
 
888
<span class="tok-kn">import</span> <span class="tok-nn">os.path</span> <span class="tok-kn">as</span> <span class="tok-nn">path</span>
 
889
<span class="tok-kn">from</span> <span class="tok-nn">subprocess</span> <span class="tok-kn">import</span> <span class="tok-n">run</span><span class="tok-p">,</span> <span class="tok-n">DEVNULL</span><span class="tok-p">,</span> <span class="tok-n">PIPE</span>
 
890
<span class="tok-kn">from</span> <span class="tok-nn">conjureup.hooklib.writer</span> <span class="tok-kn">import</span> <span class="tok-n">success</span><span class="tok-p">,</span> <span class="tok-n">fail</span><span class="tok-p">,</span> <span class="tok-n">log</span>
 
891
<span class="tok-kn">import</span> <span class="tok-nn">utils</span>
 
892
 
 
893
<span class="tok-n">SCRIPTPATH</span> <span class="tok-o">=</span> <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">dirname</span><span class="tok-p">(</span><span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">abspath</span><span class="tok-p">(</span><span class="tok-n">__file__</span><span class="tok-p">))</span>
 
894
<span class="tok-n">NOVARC</span> <span class="tok-o">=</span> <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">join</span><span class="tok-p">(</span><span class="tok-n">SCRIPTPATH</span><span class="tok-p">,</span> <span class="tok-s1">&#39;novarc&#39;</span><span class="tok-p">)</span>
 
895
 
 
896
 
 
897
<span class="tok-k">def</span> <span class="tok-nf">ssh_genkey</span><span class="tok-p">(</span><span class="tok-n">ssh_privkey</span><span class="tok-p">):</span>
 
898
    <span class="tok-sd">&quot;&quot;&quot; Generates sshkey</span>
 
899
<span class="tok-sd">    &quot;&quot;&quot;</span>
 
900
    <span class="tok-n">cmd</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;ssh-keygen -N &#39;&#39; -f {0}&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">ssh_privkey</span><span class="tok-p">)</span>
 
901
    <span class="tok-n">out</span> <span class="tok-o">=</span> <span class="tok-n">run</span><span class="tok-p">(</span><span class="tok-n">cmd</span><span class="tok-p">,</span> <span class="tok-n">shell</span><span class="tok-o">=</span><span class="tok-bp">True</span><span class="tok-p">,</span> <span class="tok-n">stdout</span><span class="tok-o">=</span><span class="tok-n">DEVNULL</span><span class="tok-p">,</span> <span class="tok-n">stderr</span><span class="tok-o">=</span><span class="tok-n">PIPE</span><span class="tok-p">)</span>
 
902
    <span class="tok-k">if</span> <span class="tok-n">out</span><span class="tok-o">.</span><span class="tok-n">returncode</span> <span class="tok-o">!=</span> <span class="tok-mi">0</span><span class="tok-p">:</span>
 
903
        <span class="tok-n">fail</span><span class="tok-p">(</span><span class="tok-s2">&quot;Unable to generate key: {0}&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">out</span><span class="tok-o">.</span><span class="tok-n">stderr</span><span class="tok-o">.</span><span class="tok-n">decode</span><span class="tok-p">()))</span>
 
904
 
 
905
 
 
906
<span class="tok-n">credentials</span> <span class="tok-o">=</span> <span class="tok-n">utils</span><span class="tok-o">.</span><span class="tok-n">parse_openstack_creds</span><span class="tok-p">(</span><span class="tok-n">NOVARC</span><span class="tok-p">)</span>
 
907
 
 
908
<span class="tok-n">ssh_pubkey</span> <span class="tok-o">=</span> <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">expanduser</span><span class="tok-p">(</span><span class="tok-n">os</span><span class="tok-o">.</span><span class="tok-n">environ</span><span class="tok-o">.</span><span class="tok-n">get</span><span class="tok-p">(</span>
 
909
    <span class="tok-s1">&#39;SSHPUBLICKEY&#39;</span><span class="tok-p">,</span>
 
910
    <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">expanduser</span><span class="tok-p">(</span><span class="tok-s1">&#39;~/.ssh/id_rsa.pub&#39;</span><span class="tok-p">)))</span> <i class="conum" data-value="1"></i><b>(1)</b>
 
911
<span class="tok-n">ssh_privkey</span> <span class="tok-o">=</span> <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">join</span><span class="tok-p">(</span><span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">expanduser</span><span class="tok-p">(</span><span class="tok-s1">&#39;~/.ssh&#39;</span><span class="tok-p">),</span>
 
912
                        <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">splitext</span><span class="tok-p">(</span><span class="tok-n">ssh_pubkey</span><span class="tok-p">)[</span><span class="tok-mi">0</span><span class="tok-p">])</span>
 
913
 
 
914
<span class="tok-k">if</span> <span class="tok-ow">not</span> <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">isfile</span><span class="tok-p">(</span><span class="tok-n">ssh_privkey</span><span class="tok-p">):</span>
 
915
    <span class="tok-n">log</span><span class="tok-o">.</span><span class="tok-n">debug</span><span class="tok-p">(</span><span class="tok-s2">&quot;No ssh private key found, generating our own.&quot;</span><span class="tok-p">)</span>
 
916
    <span class="tok-n">ssh_genkey</span><span class="tok-p">(</span><span class="tok-n">ssh_privkey</span><span class="tok-p">)</span>
 
917
 
 
918
<span class="tok-n">log</span><span class="tok-o">.</span><span class="tok-n">debug</span><span class="tok-p">(</span><span class="tok-s2">&quot;Checking for ssh public key: {}&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">ssh_pubkey</span><span class="tok-p">))</span>
 
919
<span class="tok-k">if</span> <span class="tok-n">path</span><span class="tok-o">.</span><span class="tok-n">isfile</span><span class="tok-p">(</span><span class="tok-n">ssh_pubkey</span><span class="tok-p">):</span>
 
920
    <span class="tok-n">cmd</span> <span class="tok-o">=</span> <span class="tok-p">(</span><span class="tok-s2">&quot;openstack keypair show ubuntu-keypair&quot;</span><span class="tok-p">)</span>
 
921
    <span class="tok-n">ret</span> <span class="tok-o">=</span> <span class="tok-n">run</span><span class="tok-p">(</span><span class="tok-n">cmd</span><span class="tok-p">,</span> <span class="tok-n">shell</span><span class="tok-o">=</span><span class="tok-bp">True</span><span class="tok-p">,</span>
 
922
              <span class="tok-n">stdout</span><span class="tok-o">=</span><span class="tok-n">DEVNULL</span><span class="tok-p">,</span>
 
923
              <span class="tok-n">stderr</span><span class="tok-o">=</span><span class="tok-n">PIPE</span><span class="tok-p">,</span>
 
924
              <span class="tok-n">env</span><span class="tok-o">=</span><span class="tok-n">credentials</span><span class="tok-p">)</span>
 
925
    <span class="tok-k">if</span> <span class="tok-n">ret</span><span class="tok-o">.</span><span class="tok-n">returncode</span> <span class="tok-o">==</span> <span class="tok-mi">0</span><span class="tok-p">:</span>
 
926
        <span class="tok-n">success</span><span class="tok-p">(</span><span class="tok-s2">&quot;SSH keypair already available to &quot;</span>
 
927
                <span class="tok-s2">&quot;you in your OpenStack cloud.&quot;</span><span class="tok-p">)</span>
 
928
 
 
929
    <span class="tok-n">cmd</span> <span class="tok-o">=</span> <span class="tok-p">(</span><span class="tok-s2">&quot;openstack keypair create --public-key {} &quot;</span>
 
930
           <span class="tok-s2">&quot;ubuntu-keypair&quot;</span><span class="tok-o">.</span><span class="tok-n">format</span><span class="tok-p">(</span><span class="tok-n">ssh_pubkey</span><span class="tok-p">))</span>
 
931
    <span class="tok-n">ret</span> <span class="tok-o">=</span> <span class="tok-n">run</span><span class="tok-p">(</span><span class="tok-n">cmd</span><span class="tok-p">,</span> <span class="tok-n">shell</span><span class="tok-o">=</span><span class="tok-bp">True</span><span class="tok-p">,</span>
 
932
              <span class="tok-n">stdout</span><span class="tok-o">=</span><span class="tok-n">DEVNULL</span><span class="tok-p">,</span>
 
933
              <span class="tok-n">stderr</span><span class="tok-o">=</span><span class="tok-n">PIPE</span><span class="tok-p">,</span>
 
934
              <span class="tok-n">env</span><span class="tok-o">=</span><span class="tok-n">credentials</span><span class="tok-p">)</span>
 
935
    <span class="tok-k">if</span> <span class="tok-n">ret</span><span class="tok-o">.</span><span class="tok-n">returncode</span> <span class="tok-o">&gt;</span> <span class="tok-mi">0</span><span class="tok-p">:</span>
 
936
        <span class="tok-n">fail</span><span class="tok-p">(</span><span class="tok-s2">&quot;Unable to add public ssh key, maybe &quot;</span>
 
937
             <span class="tok-s2">&quot;ssh-keygen needs to be run&quot;</span><span class="tok-p">)</span>
 
938
    <span class="tok-n">success</span><span class="tok-p">(</span><span class="tok-s2">&quot;SSH Keypair is now imported and accessible &quot;</span>
 
939
            <span class="tok-s2">&quot;when creating compute nodes.&quot;</span><span class="tok-p">)</span>
 
940
 
 
941
<span class="tok-n">fail</span><span class="tok-p">(</span><span class="tok-s2">&quot;Could not find any ssh keys to import, please run &quot;</span>
 
942
     <span class="tok-s2">&quot;ssh-keygen in another terminal before re-executing this step.&quot;</span><span class="tok-p">)</span></code></pre>
 
943
</div>
 
944
</div>
 
945
<div class="colist arabic">
 
946
<table>
 
947
<tr>
 
948
<td><i class="conum" data-value="1"></i><b>1</b></td>
 
949
<td>This is the environment variable that was defined in the <strong>key</strong> section of <strong>step-01_keypair.yaml</strong></td>
 
950
</tr>
 
951
</table>
 
952
</div>
 
953
</div>
 
954
</div>
 
955
</div>
 
956
</div>
 
957
</div>
 
958
</div>
 
959
<div id="footer">
 
960
<div id="footer-text">
 
961
Version 2.0.1~beta1<br>
 
962
Last updated 2016-09-13 05:34:52 EDT
 
963
</div>
 
964
</div>
 
965
</body>
 
966
</html>
 
 
b'\\ No newline at end of file'