forked from softlayer/softlayer-python
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdev.html
More file actions
347 lines (305 loc) · 20.5 KB
/
dev.html
File metadata and controls
347 lines (305 loc) · 20.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Command-Line Interface Developer Guide — SoftLayer API Python Client 2.3.1 documentation</title>
<link rel="stylesheet" href="../_static/style.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '2.3.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="top" title="SoftLayer API Python Client 2.3.1 documentation" href="../index.html" />
<link rel="prev" title="Working with Cloud Compute Instances" href="cci.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="cci.html" title="Working with Cloud Compute Instances"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">SoftLayer API Python Client 2.3.1 documentation</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="admonition note" id="dev">
<p class="first admonition-title">Note</p>
<p class="last">Full example module available <a class="reference internal" href="example_module.html#example-module"><em>here</em></a></p>
</div>
<div class="section" id="command-line-interface-developer-guide">
<h1>Command-Line Interface Developer Guide<a class="headerlink" href="#command-line-interface-developer-guide" title="Permalink to this headline">¶</a></h1>
<p>A CLI interface is broken into 4 major parts:</p>
<ul class="simple">
<li>module</li>
<li>docblock</li>
<li>action</li>
<li>docblock</li>
<li>docblock</li>
</ul>
<div class="section" id="defining-a-module">
<h2>Defining a module<a class="headerlink" href="#defining-a-module" title="Permalink to this headline">¶</a></h2>
<p>A module is a python module residing in <cite>SoftLayer/CLI/modules/<module>.py</cite>. The filename represented here is what is directly exposed after the <cite>sl</cite> command. I.e. <cite>sl cci</cite> is <cite>SoftLayer/CLI/modules/cci.py</cite>. The module’s docblock is used as the <a class="reference external" href="http://docopt.org/">argument parser</a> and usage the end user will see. <cite>SoftLayer.CLI.helpers</cite> contain all the helper functions and classes used for creating a CLI interface. This is a typical setup and how it maps:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="sd">"""</span>
<span class="sd">usage: sl example [<command>] [<args>...] [options]</span>
<span class="sd">Example implementation of a CLI module</span>
<span class="sd">Available commands are:</span>
<span class="sd"> print print example</span>
<span class="sd"> pretty formatted print example</span>
<span class="sd"> parse parsing args example</span>
<span class="sd">"""</span>
<span class="kn">from</span> <span class="nn">SoftLayer.CLI</span> <span class="kn">import</span> <span class="p">(</span>
<span class="n">CLIRunnable</span><span class="p">,</span> <span class="n">Table</span><span class="p">,</span> <span class="n">no_going_back</span><span class="p">,</span> <span class="n">confirm</span><span class="p">)</span>
</pre></div>
</div>
<div class="highlight-python"><pre>$ sl example
usage: sl example [<command>] [<args>...] [options]
Example implementation of a CLI module
Available commands are:
print print example
pretty formatted print example
parse parsing args example
Standard Options:
-h --help Show this screen</pre>
</div>
</div>
<div class="section" id="action">
<h2>Action<a class="headerlink" href="#action" title="Permalink to this headline">¶</a></h2>
<p>Actions are implemented using classes in the module that subclass <cite>CLIRunnable</cite>. The actual class name is irrelevant for the implementation details as it isn’t used anywhere. The docblock is used as the arguement parser as well. Unlike the modules docblock, additional, common, arguments are added to the end as well; i.e. <cite>–config</cite> and <cite>–format</cite>.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">CLIRunnable</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="n">action</span> <span class="o">=</span> <span class="bp">None</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">add_additional_args</span><span class="p">(</span><span class="n">parser</span><span class="p">):</span>
<span class="k">pass</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>The required interfaces are:</p>
<ul class="simple">
<li>The docblock (__doc__) for docopt</li>
<li>action</li>
<li>def execute(client, args)<ul>
<li>Don’t forget the @staticmethod annotation!</li>
<li>you can also use @classmethod and use execute(cls, client, args) if you plan on dispatching instead of executing a simple task.</li>
</ul>
</li>
</ul>
<p>A minimal implementation for <cite>sl example print</cite> would look like this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">ExampleAction</span><span class="p">(</span><span class="n">CLIRunnable</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd">usage: sl example print [options]</span>
<span class="sd">Print example</span>
<span class="sd">"""</span>
<span class="n">action</span> <span class="o">=</span> <span class="s">'print'</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">print</span> <span class="s">"EXAMPLE!"</span>
</pre></div>
</div>
<p>Which in turn, works like this:</p>
<div class="highlight-python"><pre>$ sl example print
EXAMPLE!
$ sl example print -h
usage: sl example print [options]
Print example
Standard Options:
--format=ARG Output format. [Options: table, raw] [Default: table]
-C FILE --config=FILE Config file location. [Default: ~/.softlayer]
-h --help Show this screen</pre>
</div>
</div>
<div class="section" id="output">
<h2>Output<a class="headerlink" href="#output" title="Permalink to this headline">¶</a></h2>
<p>The <cite>execute()</cite> method is expected to return either <cite>None</cite> or an instance of <cite>SoftLayer.CLI.helpers.Table</cite>. When <cite>None</cite> is returned, it assumes all output is handled inside of <cite>execute</cite>. <cite>SoftLayer.CLI.modules.dns.DumpZone</cite> is a great example of when handling your own output is ideal as the data is already coming back preformatted from the API. 99% of the time though, data will be raw and unformatted. As an example, we create <cite>sl example pretty</cite> as such:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">ExamplePretty</span><span class="p">(</span><span class="n">CLIRunnable</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd">usage: sl example pretty [options]</span>
<span class="sd">Pretty output example</span>
<span class="sd">"""</span>
<span class="n">action</span> <span class="o">=</span> <span class="s">'pretty'</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="c"># create a table with two columns: col1, col2</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">Table</span><span class="p">([</span><span class="s">'col1'</span><span class="p">,</span> <span class="s">'col2'</span><span class="p">])</span>
<span class="c"># align the data facing each other</span>
<span class="c"># valid values are r, c, l for right, center, left</span>
<span class="c"># note, these are suggestions based on the format chosen by the user</span>
<span class="n">t</span><span class="o">.</span><span class="n">align</span><span class="p">[</span><span class="s">'col1'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'r'</span>
<span class="n">t</span><span class="o">.</span><span class="n">align</span><span class="p">[</span><span class="s">'col2'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'l'</span>
<span class="c"># add rows</span>
<span class="n">t</span><span class="o">.</span><span class="n">add_row</span><span class="p">([</span><span class="s">'test'</span><span class="p">,</span> <span class="s">'test'</span><span class="p">])</span>
<span class="n">t</span><span class="o">.</span><span class="n">add_row</span><span class="p">([</span><span class="s">'test2'</span><span class="p">,</span> <span class="s">'test2'</span><span class="p">])</span>
<span class="k">return</span> <span class="n">t</span>
</pre></div>
</div>
<p>Which gives us</p>
<div class="highlight-python"><pre>$ sl example pretty
:.......:.......:
: col1 : col2 :
:.......:.......:
: test : test :
: test2 : test2 :
:.......:.......:
$ sl example pretty --format raw
test test
test2 test2</pre>
</div>
<p>Formatting of the data represented in the table is actually controlled upstream from the CLIRunnable’s making supporting more data formats in the future easier.</p>
</div>
<div class="section" id="adding-arguments">
<h2>Adding arguments<a class="headerlink" href="#adding-arguments" title="Permalink to this headline">¶</a></h2>
<p>Refer to docopt for more complete documentation</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">ExampleArgs</span><span class="p">(</span><span class="n">CLIRunnable</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd">usage: sl example parse [--test] [--this=THIS|--that=THAT]</span>
<span class="sd"> (--one|--two) [options]</span>
<span class="sd">Argument parsing example</span>
<span class="sd">Options:</span>
<span class="sd"> --test Print different output</span>
<span class="sd">"""</span>
<span class="n">action</span> <span class="o">=</span> <span class="s">'parse'</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'--test'</span><span class="p">):</span>
<span class="k">print</span> <span class="s">"Just testing, move along..."</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"This is fo'realz!"</span>
<span class="k">if</span> <span class="n">args</span><span class="p">[</span><span class="s">'--one'</span><span class="p">]:</span>
<span class="k">print</span> <span class="mi">1</span>
<span class="k">elif</span> <span class="n">args</span><span class="p">[</span><span class="s">'--two'</span><span class="p">]:</span>
<span class="k">print</span> <span class="mi">2</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'--this'</span><span class="p">):</span>
<span class="k">print</span> <span class="s">"I gots"</span><span class="p">,</span> <span class="n">args</span><span class="p">[</span><span class="s">'--this'</span><span class="p">]</span>
<span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'--that'</span><span class="p">):</span>
<span class="k">print</span> <span class="s">"you dont have"</span><span class="p">,</span> <span class="n">args</span><span class="p">[</span><span class="s">'--that'</span><span class="p">]</span>
</pre></div>
</div>
</div>
<div class="section" id="accessing-the-api">
<h2>Accessing the API<a class="headerlink" href="#accessing-the-api" title="Permalink to this headline">¶</a></h2>
<p>API access is available via the first argument of <cite>execute</cite> which will be an initialized copy of <cite>SoftLayer.API.Client</cite>. Please refer to [using the api](API-Usage) for further details on howto use the <cite>Client</cite> object.</p>
</div>
<div class="section" id="confirmations">
<h2>Confirmations<a class="headerlink" href="#confirmations" title="Permalink to this headline">¶</a></h2>
<p>All confirmations should be easily bypassed by checking for <cite>args[‘–really’]</cite>. To inject <cite>–really</cite> add <cite>options = [‘confirm’]</cite> to the class definition, typically just below <cite>action</cite>. This ensures that <cite>–really</cite> is consistent throughout the CLI.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">ExampleArgs</span><span class="p">(</span><span class="n">CLIRunnable</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd">usage: sl example parse [--test] [--this=THIS|--that=THAT]</span>
<span class="sd"> (--one|--two) [options]</span>
<span class="sd">Argument parsing example</span>
<span class="sd">Options:</span>
<span class="sd"> --test Print different output</span>
<span class="sd">"""</span>
<span class="n">action</span> <span class="o">=</span> <span class="s">'parse'</span>
<span class="n">options</span> <span class="o">=</span> <span class="p">[</span><span class="s">'confirm'</span><span class="p">]</span> <span class="c"># confirm adds the '-y|--really' options and help</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="n">client</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>There are two primary confirmation prompts that both leverage <cite>SoftLayer.CLI.valid_response</cite>:</p>
<ul class="simple">
<li><cite>SoftLayer.CLI.helpers.confirm</cite></li>
<li><cite>SoftLayer.CLI.helpers.no_going_back</cite></li>
</ul>
<p><cite>no_going_back</cite> accepts a single confirmation parameter that is generally unique to that action. This is similar to typing in the hostname of a machine you are canceling or some other string that isn’t reactionary such as “yes”, “just do it”. Some good examples would be the ID of the object, a phrase “I know what I am doing” or anything of the like. It returns True, False, or None. The prompt string is pre-defined.</p>
<p><cite>confirm</cite> is a lot more flexible in that you can set the prompt string, allowing default values, and such. But it’s limited to ‘yes’ or ‘no’ values. Returns True, False, or None.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">confirmation</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'--really'</span><span class="p">)</span> <span class="ow">or</span> <span class="n">no_going_back</span><span class="p">(</span><span class="s">'YES'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">confirmation</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
</div>
<div class="section" id="aborting-execution">
<h2>Aborting execution<a class="headerlink" href="#aborting-execution" title="Permalink to this headline">¶</a></h2>
<p>When a confirmation fails, you will need to bail out of <cite>execute()</cite>. Raise a <cite>SoftLayer.CLI.helpers.CLIAbort</cite> with the message for the user as the first parameter. This will prevent any further execution and properly return the right error code.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">if</span> <span class="ow">not</span> <span class="n">confirmation</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">CLIAbort</span><span class="p">(</span><span class="s">"Aborting. Failed confirmation"</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="../index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Command-Line Interface Developer Guide</a><ul>
<li><a class="reference internal" href="#defining-a-module">Defining a module</a></li>
<li><a class="reference internal" href="#action">Action</a></li>
<li><a class="reference internal" href="#output">Output</a></li>
<li><a class="reference internal" href="#adding-arguments">Adding arguments</a></li>
<li><a class="reference internal" href="#accessing-the-api">Accessing the API</a></li>
<li><a class="reference internal" href="#confirmations">Confirmations</a></li>
<li><a class="reference internal" href="#aborting-execution">Aborting execution</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="cci.html"
title="previous chapter">Working with Cloud Compute Instances</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cli/dev.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="cci.html" title="Working with Cloud Compute Instances"
>previous</a> |</li>
<li><a href="../index.html">SoftLayer API Python Client 2.3.1 documentation</a> »</li>
</ul>
</div>
<div class="footer">
© Copyright 2013, SoftLayer Technologies, Inc..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2b1.
</div>
</body>
</html>