Add --json option to swift capabilities / swift info

This lets us do things like:

    $ swift info --json | jq '[.swift.policies[].name]'
    [
      "Standard-Replica",
      "EC"
    ]

Also, escape more dashes in the man page, so they won't be
misinterpreted as hyphens.

Change-Id: Ic7690bdbcfc55f55e5dde9bc11bb0644085973ce
This commit is contained in:
Tim Burke 2016-02-04 10:25:15 -08:00
parent 5be9b7e310
commit 335570e511
3 changed files with 55 additions and 20 deletions
doc/manpages
swiftclient
tests/unit

@ -61,8 +61,8 @@ of container or objects being listed. With the \-t or \-\-total option they only
.RS 4
Uploads to the given container the files and directories specified by the
remaining args. The \-c or \-\-changed is an option that will only upload files
that have changed since the last upload. The \-\-object-name <object\-name> is
an option that will upload file and name object to <object-name> or upload dir
that have changed since the last upload. The \-\-object\-name <object\-name> is
an option that will upload file and name object to <object\-name> or upload dir
and use <object\-name> as object prefix. The \-S <size> or \-\-segment\-size <size>
and \-\-leave\-segments and others are options as well (see swift upload \-\-help for more).
.RE
@ -86,7 +86,7 @@ container, or a list of objects depending on the args given. For a single
object download, you may use the \-o [\-\-output] <filename> option to
redirect the output to a specific file or if "-" then just redirect to stdout or
with \-\-no-download actually not to write anything to disk.
The \-\-ignore-checksum is an option that turn off checksum validation.
The \-\-ignore-checksum is an option that turns off checksum validation.
You can specify optional headers with the repeatable cURL-like option
\-H [\-\-header]. For more details and options see swift download \-\-help.
.RE
@ -100,23 +100,31 @@ will be deleted as well, unless you specify the \-\-leave\-segments option.
For more details and options see swift delete \-\-help.
.RE
\fBcapabilities\fR [\fIproxy-url\fR]
\fBcapabilities\fR [\fIcommand-options\fR] [\fIproxy-url\fR]
.RS 4
Displays cluster capabilities. The output includes the list of the activated
Swift middlewares as well as relevant options for each one. Additionally the
command displays relevant options for the Swift core. If the proxy-url option
is not provided the storage-url retrieved after authentication is used as
proxy-url.
Displays cluster capabilities. If the proxy-url option is not provided the
storage-url retrieved after authentication is used as proxy-url.
By default, the output includes the list of the activated Swift middlewares as
well as relevant options for each one. Additionally the command displays
relevant options for the Swift core.
The \-\-json option will print a json representation of the cluster
capabilities. This is typically more suitable for consumption by other
programs, such as jq.
\fBExample\fR: capabilities https://swift.example.com
capabilities \-\-json
.RE
\fBtempurl\fR [\fIcommand-option\fR] \fImethod\fR \fIseconds\fR \fIpath\fR \fIkey\fR
.RS 4
Generates a temporary URL allowing unauthenticated access to the Swift object
at the given path, using the given HTTP method, for the given number of
seconds, using the given TempURL key. If optional --absolute argument is
seconds, using the given TempURL key. If optional \-\-absolute argument is
provided, seconds is instead interpreted as a Unix timestamp at which the URL
should expire. \fBExample\fR: tempurl GET $(date -d "Jan 1 2016" +%s)
/v1/AUTH_foo/bar_container/quux.md my_secret_tempurl_key --absolute
should expire. \fBExample\fR: tempurl GET $(date \-d "Jan 1 2016" +%s)
/v1/AUTH_foo/bar_container/quux.md my_secret_tempurl_key \-\-absolute
.RE
\fBauth\fR
@ -140,7 +148,7 @@ For examples see swift auth \-\-help.
.IP "--os-help Show all OpenStack authentication options"
.PD
.RS 4
For more options see swift \-\-help and swift \-\-os-help.
For more options see swift \-\-help and swift \-\-os\-help.
.RE

@ -17,6 +17,7 @@
from __future__ import print_function, unicode_literals
import argparse
import json
import logging
import signal
import socket
@ -248,7 +249,7 @@ Optional arguments:
-H, --header <header:value>
Adds a customized request header to the query, like
"Range" or "If-Match". This option may be repeated.
Example --header "content-type:text/plain"
Example: --header "content-type:text/plain"
--skip-identical Skip downloading files that are identical on both
sides.
--ignore-checksum Turn off checksum validation for downloads.
@ -789,7 +790,7 @@ Optional arguments:
Default is 10.
-H, --header <header:value>
Adds a customized request header. This option may be
repeated. Example -H "content-type:text/plain"
repeated. Example: -H "content-type:text/plain"
-H "Content-Length: 4000".
--use-slo When used in conjunction with --segment-size it will
create a Static Large Object instead of the default
@ -840,7 +841,7 @@ def st_upload(parser, args, output_manager):
parser.add_argument(
'-H', '--header', action='append', dest='header',
default=[], help='Set request headers with the syntax header:value. '
' This option may be repeated. Example -H "content-type:text/plain" '
' This option may be repeated. Example: -H "content-type:text/plain" '
'-H "Content-Length: 4000"')
parser.add_argument(
'--use-slo', action='store_true', default=False,
@ -995,13 +996,16 @@ def st_upload(parser, args, output_manager):
output_manager.error(e.value)
st_capabilities_options = "[<proxy_url>]"
st_capabilities_options = "[--json] [<proxy_url>]"
st_info_options = st_capabilities_options
st_capabilities_help = '''
Retrieve capability of the proxy.
Optional positional arguments:
<proxy_url> Proxy URL of the cluster to retrieve capabilities.
Optional arguments:
--json Print the cluster capabilities in JSON format.
'''.strip('\n')
st_info_help = st_capabilities_help
@ -1017,6 +1021,8 @@ def st_capabilities(parser, args, output_manager):
key=lambda x: x[0]):
output_manager.print_msg(" %s: %s" % (key, value))
parser.add_argument('--json', action='store_true',
help='print capability information in json')
(options, args) = parse_args(parser, args)
if args and len(args) > 2:
output_manager.error('Usage: %s capabilities %s\n%s',
@ -1034,9 +1040,14 @@ def st_capabilities(parser, args, output_manager):
capabilities_result = swift.capabilities()
capabilities = capabilities_result['capabilities']
_print_compo_cap('Core', {'swift': capabilities['swift']})
del capabilities['swift']
_print_compo_cap('Additional middleware', capabilities)
if options['json']:
output_manager.print_msg(
json.dumps(capabilities, sort_keys=True, indent=2))
else:
capabilities = dict(capabilities)
_print_compo_cap('Core', {'swift': capabilities['swift']})
del capabilities['swift']
_print_compo_cap('Additional middleware', capabilities)
except SwiftError as e:
output_manager.error(e.value)

@ -16,6 +16,7 @@ from __future__ import unicode_literals
from genericpath import getmtime
import hashlib
import json
import logging
import mock
import os
@ -1285,6 +1286,21 @@ class TestShell(unittest.TestCase):
swiftclient.shell.main(argv)
connection.return_value.get_capabilities.assert_called_with(None)
@mock.patch('swiftclient.service.Connection')
def test_capabilities_json(self, connection):
capabilities = {
'slo': {'min_segment_size': 1000000},
'some': [{'arbitrary': 'nested'}, {'crazy': 'structure'}],
'swift': {'version': '2.5.0'}}
connection.return_value.get_capabilities.return_value = capabilities
argv = ["", "capabilities", "--json"]
with CaptureOutput(suppress_systemexit=True) as output:
swiftclient.shell.main(argv)
expected = json.dumps(capabilities, sort_keys=True, indent=2) + '\n'
self.assertEqual(expected, output.out)
connection.return_value.get_capabilities.assert_called_with(None)
def test_human_readable_upload_segment_size(self):
def _check_expected(x, expected):
actual = x.call_args_list[-1][1]["options"]["segment_size"]