Write the base of the documentation
This commit is contained in:
parent
38bc513414
commit
0d180c360d
3
.gitignore
vendored
3
.gitignore
vendored
@ -52,3 +52,6 @@ ChangeLog
|
|||||||
*~
|
*~
|
||||||
.*.swp
|
.*.swp
|
||||||
.*sw?
|
.*sw?
|
||||||
|
|
||||||
|
# generated docs
|
||||||
|
doc/source/ref/
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
python-gnocchiclient
|
python-gnocchiclient
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
Python client library for Gnocchi
|
Python bindings to the OpenStack Gnocchi API
|
||||||
|
|
||||||
Please feel here a long description which must be at least 3 lines wrapped on
|
This is a client for OpenStack gnocchi API. There's :doc:`a Python API
|
||||||
80 cols, so that distribution package maintainers can use it in their packages.
|
<api>` (the :mod:`gnocchiclient` module), and a :doc:`command-line script
|
||||||
Note that this is a hard requirement.
|
<shell>` (installed as :program:`gnocchi`). Each implements the entire
|
||||||
|
OpenStack Gnocchi API.
|
||||||
|
|
||||||
* Free software: Apache license
|
* Free software: Apache license
|
||||||
* Documentation: http://docs.openstack.org/developer/python-gnocchiclient
|
* Documentation: http://docs.openstack.org/developer/python-gnocchiclient
|
||||||
|
27
doc/source/api.rst
Normal file
27
doc/source/api.rst
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
The :mod:`gnocchiclient` Python API
|
||||||
|
===================================
|
||||||
|
|
||||||
|
.. module:: gnocchiclient
|
||||||
|
:synopsis: A client for the Gnocchi API.
|
||||||
|
|
||||||
|
.. currentmodule:: gnocchiclient
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
To use python-gnocchiclient in a project::
|
||||||
|
|
||||||
|
>>> from gnocchiclient.v1 import client
|
||||||
|
>>> gnocchi = client.Client(...)
|
||||||
|
>>> gnocchi.resource.list("instance")
|
||||||
|
|
||||||
|
Reference
|
||||||
|
---------
|
||||||
|
|
||||||
|
For more information, see the reference:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
ref/v1/index
|
||||||
|
|
@ -15,7 +15,47 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.insert(0, os.path.abspath('../..'))
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
ROOT = os.path.abspath(os.path.join(BASE_DIR, "..", ".."))
|
||||||
|
|
||||||
|
sys.path.insert(0, ROOT)
|
||||||
|
sys.path.insert(0, BASE_DIR)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_ref(ver, title, names):
|
||||||
|
refdir = os.path.join(BASE_DIR, "ref")
|
||||||
|
pkg = "gnocchiclient"
|
||||||
|
if ver:
|
||||||
|
pkg = "%s.%s" % (pkg, ver)
|
||||||
|
refdir = os.path.join(refdir, ver)
|
||||||
|
if not os.path.exists(refdir):
|
||||||
|
os.makedirs(refdir)
|
||||||
|
idxpath = os.path.join(refdir, "index.rst")
|
||||||
|
with open(idxpath, "w") as idx:
|
||||||
|
idx.write(("%(title)s\n"
|
||||||
|
"%(signs)s\n"
|
||||||
|
"\n"
|
||||||
|
".. toctree::\n"
|
||||||
|
" :maxdepth: 1\n"
|
||||||
|
"\n") % {"title": title, "signs": "=" * len(title)})
|
||||||
|
for name in names:
|
||||||
|
idx.write(" %s\n" % name)
|
||||||
|
rstpath = os.path.join(refdir, "%s.rst" % name)
|
||||||
|
with open(rstpath, "w") as rst:
|
||||||
|
rst.write(("%(title)s\n"
|
||||||
|
"%(signs)s\n"
|
||||||
|
"\n"
|
||||||
|
".. automodule:: %(pkg)s.%(name)s\n"
|
||||||
|
" :members:\n"
|
||||||
|
" :undoc-members:\n"
|
||||||
|
" :show-inheritance:\n"
|
||||||
|
" :noindex:\n")
|
||||||
|
% {"title": name.capitalize(),
|
||||||
|
"signs": "=" * len(name),
|
||||||
|
"pkg": pkg, "name": name})
|
||||||
|
|
||||||
|
gen_ref("v1", "Version 1 API", ["client", "resource"])
|
||||||
|
|
||||||
# -- General configuration ----------------------------------------------------
|
# -- General configuration ----------------------------------------------------
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
@ -3,17 +3,31 @@
|
|||||||
You can adapt this file completely to your liking, but it should at least
|
You can adapt this file completely to your liking, but it should at least
|
||||||
contain the root `toctree` directive.
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
Welcome to python-gnocchiclient's documentation!
|
Python bindings to the Gnocchi API
|
||||||
========================================================
|
========================================================
|
||||||
|
|
||||||
|
This is a client for gnocchi API. There's :doc:`a Python API
|
||||||
|
<api>` (the :mod:`gnocchiclient` module), and a :doc:`command-line script
|
||||||
|
<shell>` (installed as :program:`gnocchi`). Each implements the entire
|
||||||
|
Gnocchi API.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
You may want to read the `Gnocchi Developer Guide`__ -- the overview, at
|
||||||
|
least -- to get an idea of the concepts. By understanding the concepts
|
||||||
|
this library should make more sense.
|
||||||
|
|
||||||
|
__ http://docs.openstack.org/developer/gnocchi/
|
||||||
|
|
||||||
|
|
||||||
Contents:
|
Contents:
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
readme
|
|
||||||
installation
|
installation
|
||||||
usage
|
shell
|
||||||
|
api
|
||||||
contributing
|
contributing
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
@ -1 +0,0 @@
|
|||||||
.. include:: ../../README.rst
|
|
67
doc/source/shell.rst
Normal file
67
doc/source/shell.rst
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
The :program:`gnocchi` shell utility
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
.. program:: gnocchi
|
||||||
|
.. highlight:: bash
|
||||||
|
|
||||||
|
The :program:`gnocchi` shell utility interacts with Gnocchi API
|
||||||
|
from the command line. It supports the entirety of the Gnocchi API.
|
||||||
|
|
||||||
|
You'll need to provide :program:`gnocchi` with your OpenStack credentials.
|
||||||
|
You can do this with the :option:`--os-username`, :option:`--os-password`,
|
||||||
|
:option:`--os-tenant-id` and :option:`--os-auth-url` options, but it's easier to
|
||||||
|
just set them as environment variables:
|
||||||
|
|
||||||
|
.. envvar:: OS_USERNAME
|
||||||
|
|
||||||
|
Your OpenStack username.
|
||||||
|
|
||||||
|
.. envvar:: OS_PASSWORD
|
||||||
|
|
||||||
|
Your password.
|
||||||
|
|
||||||
|
.. envvar:: OS_TENANT_NAME
|
||||||
|
|
||||||
|
Project to work on.
|
||||||
|
|
||||||
|
.. envvar:: OS_AUTH_URL
|
||||||
|
|
||||||
|
The OpenStack auth server URL (keystone).
|
||||||
|
|
||||||
|
For example, in Bash you would use::
|
||||||
|
|
||||||
|
export OS_USERNAME=user
|
||||||
|
export OS_PASSWORD=pass
|
||||||
|
export OS_TENANT_NAME=myproject
|
||||||
|
export OS_AUTH_URL=http://auth.example.com:5000/v2.0
|
||||||
|
|
||||||
|
The command line tool will attempt to reauthenticate using your provided credentials
|
||||||
|
for every request. You can override this behavior by manually supplying an auth
|
||||||
|
token using :option:`--os-gnocchi-url` and :option:`--os-auth-token`. You can alternatively
|
||||||
|
set these environment variables::
|
||||||
|
|
||||||
|
export GNOCCHI_ENDPOINT=http://gnocchi.example.org:8041
|
||||||
|
export OS_AUTH_TOKEN=3bcc3d3a03f44e3d8377f9247b0ad155
|
||||||
|
|
||||||
|
From there, all shell commands take the form::
|
||||||
|
|
||||||
|
gnocchi <command> [arguments...]
|
||||||
|
|
||||||
|
Run :program:`gnocchi help` to get a full list of all possible commands,
|
||||||
|
and run :program:`gnocchi help <command>` to get detailed help for that
|
||||||
|
command.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Create a resource::
|
||||||
|
|
||||||
|
gnocch resource create instance --attribute id:5a301761-f78b-46e2-8900-8b4f6fe6675a --attribute project_id:eba5c38f-c3dd-4d9c-9235-32d430471f94 --metric temperature:high
|
||||||
|
|
||||||
|
List resources::
|
||||||
|
|
||||||
|
gnocchi resource list instance
|
||||||
|
|
||||||
|
Search of resources::
|
||||||
|
|
||||||
|
gnocchi resource search -q "project_id=5a301761-f78b-46e2-8900-8b4f6fe6675a and not (name like '%foobar%' or name='my_resource')"
|
@ -1,7 +0,0 @@
|
|||||||
========
|
|
||||||
Usage
|
|
||||||
========
|
|
||||||
|
|
||||||
To use python-gnocchiclient in a project::
|
|
||||||
|
|
||||||
import gnocchiclient
|
|
@ -21,12 +21,21 @@ from gnocchiclient.v1 import resource
|
|||||||
class Client(object):
|
class Client(object):
|
||||||
"""Client for the Gnocchi v1 API.
|
"""Client for the Gnocchi v1 API.
|
||||||
|
|
||||||
:param string auth: An keystoneclient authentication plugin to
|
:param string auth: An optional keystoneclient authentication plugin
|
||||||
authenticate the session with
|
to authenticate the session with
|
||||||
:type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin`
|
:type auth: :py:class:`keystoneclient.auth.base.BaseAuthPlugin`
|
||||||
|
:param endpoint: The optional Gnocchi API endpoint
|
||||||
|
:type endpoint: str
|
||||||
|
:param interface: The endpoint interface ('public', 'internal', 'admin')
|
||||||
|
:type interface: str
|
||||||
|
:param region_name: The keystone region name
|
||||||
|
:type region_name: str
|
||||||
|
:param \*\*kwargs: Any option supported by
|
||||||
|
:py:class:`keystoneclient.session.Session`
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "v1"
|
_VERSION = "v1"
|
||||||
|
|
||||||
def __init__(self, auth=None, endpoint=None, interface=None,
|
def __init__(self, auth=None, endpoint=None, interface=None,
|
||||||
region_name=None, **kwargs):
|
region_name=None, **kwargs):
|
||||||
@ -45,7 +54,7 @@ class Client(object):
|
|||||||
region_name=self.region_name)
|
region_name=self.region_name)
|
||||||
return self._endpoint
|
return self._endpoint
|
||||||
|
|
||||||
def url(self, url_suffix):
|
def _build_url(self, url_suffix):
|
||||||
return "%s/%s/%s" % (self.endpoint.rstrip("/"),
|
return "%s/%s/%s" % (self.endpoint.rstrip("/"),
|
||||||
self.VERSION,
|
self._VERSION,
|
||||||
url_suffix)
|
url_suffix)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# Copyright 2012 OpenStack Foundation
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -13,203 +11,103 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
from cliff import command
|
|
||||||
from cliff import lister
|
|
||||||
from cliff import show
|
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
from gnocchiclient import utils
|
|
||||||
from gnocchiclient.v1 import base
|
from gnocchiclient.v1 import base
|
||||||
|
|
||||||
|
|
||||||
class ResourceManager(base.Manager):
|
class ResourceManager(base.Manager):
|
||||||
def list(self, resource_type="generic", details=False, history=False):
|
def list(self, resource_type="generic", details=False, history=False):
|
||||||
|
"""List resources
|
||||||
|
|
||||||
|
:param resource_type: Type of the resource
|
||||||
|
:type resource_type: str
|
||||||
|
:param details: Show all attributes of resources
|
||||||
|
:type details: bool
|
||||||
|
:param history: Show the history of resources
|
||||||
|
:type history: bool
|
||||||
|
"""
|
||||||
details = "true" if details else "false"
|
details = "true" if details else "false"
|
||||||
history = "true" if history else "false"
|
history = "true" if history else "false"
|
||||||
url = self.client.url("resource/%s?details=%s&history=%s" % (
|
url = self.client._build_url("resource/%s?details=%s&history=%s" % (
|
||||||
resource_type, details, history))
|
resource_type, details, history))
|
||||||
return self.client.api.get(url).json()
|
return self.client.api.get(url).json()
|
||||||
|
|
||||||
def get(self, resource_type, resource_id):
|
def get(self, resource_type, resource_id):
|
||||||
url = self.client.url("resource/%s/%s" % (
|
"""Get a resource
|
||||||
|
|
||||||
|
:param resource_type: Type of the resource
|
||||||
|
:type resource_type: str
|
||||||
|
:param resource_id: ID of the resource
|
||||||
|
:type resource_id: str
|
||||||
|
"""
|
||||||
|
url = self.client._build_url("resource/%s/%s" % (
|
||||||
resource_type, resource_id))
|
resource_type, resource_id))
|
||||||
return self.client.api.get(url).json()
|
return self.client.api.get(url).json()
|
||||||
|
|
||||||
def create(self, resource_type, resource):
|
def create(self, resource_type, resource):
|
||||||
url = self.client.url("resource/%s" % resource_type)
|
"""Create a resource
|
||||||
|
|
||||||
|
:param resource_type: Type of the resource
|
||||||
|
:type resource_type: str
|
||||||
|
:param resource: Attribute of the resource
|
||||||
|
:type resource: dict
|
||||||
|
"""
|
||||||
|
url = self.client._build_url("resource/%s" % resource_type)
|
||||||
return self.client.api.post(
|
return self.client.api.post(
|
||||||
url, headers={'Content-Type': "application/json"},
|
url, headers={'Content-Type': "application/json"},
|
||||||
data=jsonutils.dumps(resource)).json()
|
data=jsonutils.dumps(resource)).json()
|
||||||
|
|
||||||
def update(self, resource_type, resource_id, resource):
|
def update(self, resource_type, resource_id, resource):
|
||||||
url = self.client.url("resource/%s/%s" % (resource_type, resource_id))
|
"""Update a resource
|
||||||
|
|
||||||
|
:param resource_type: Type of the resource
|
||||||
|
:type resource_type: str
|
||||||
|
:param resource_id: ID of the resource
|
||||||
|
:type resource_id: str
|
||||||
|
:param resource: Attribute of the resource
|
||||||
|
:type resource: dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = self.client._build_url("resource/%s/%s" % (resource_type,
|
||||||
|
resource_id))
|
||||||
return self.client.api.patch(
|
return self.client.api.patch(
|
||||||
url, headers={'Content-Type': "application/json"},
|
url, headers={'Content-Type': "application/json"},
|
||||||
data=jsonutils.dumps(resource)).json()
|
data=jsonutils.dumps(resource)).json()
|
||||||
|
|
||||||
def delete(self, resource_id):
|
def delete(self, resource_id):
|
||||||
url = self.client.url("resource/generic/%s" % (resource_id))
|
"""Delete a resource
|
||||||
|
|
||||||
|
:param resource_id: ID of the resource
|
||||||
|
:type resource_id: str
|
||||||
|
"""
|
||||||
|
url = self.client._build_url("resource/generic/%s" % (resource_id))
|
||||||
self.client.api.delete(url)
|
self.client.api.delete(url)
|
||||||
|
|
||||||
def search(self, resource_type="generic", details=False, history=False,
|
def search(self, resource_type="generic", request=None, details=False,
|
||||||
request=None):
|
history=False):
|
||||||
|
"""List resources
|
||||||
|
|
||||||
|
:param resource_type: Type of the resource
|
||||||
|
:param resource_type: str
|
||||||
|
:param request: The search request dictionary
|
||||||
|
:type resource_type: dict
|
||||||
|
:param details: Show all attributes of resources
|
||||||
|
:type details: bool
|
||||||
|
:param history: Show the history of resources
|
||||||
|
:type history: bool
|
||||||
|
|
||||||
|
See Gnocchi REST API documentation for the format
|
||||||
|
of *request dictionary*
|
||||||
|
http://docs.openstack.org/developer/gnocchi/rest.html#searching-for-resources
|
||||||
|
"""
|
||||||
|
|
||||||
request = request or {}
|
request = request or {}
|
||||||
details = "true" if details else "false"
|
details = "true" if details else "false"
|
||||||
history = "true" if history else "false"
|
history = "true" if history else "false"
|
||||||
url = self.client.url("/search/resource/%s?details=%s&history=%s" % (
|
url = self.client._build_url(
|
||||||
resource_type, details, history))
|
"/search/resource/%s?details=%s&history=%s" % (
|
||||||
|
resource_type, details, history))
|
||||||
return self.client.api.post(
|
return self.client.api.post(
|
||||||
url, headers={'Content-Type': "application/json"},
|
url, headers={'Content-Type': "application/json"},
|
||||||
data=jsonutils.dumps(request)).json()
|
data=jsonutils.dumps(request)).json()
|
||||||
|
|
||||||
|
|
||||||
class CliResourceList(lister.Lister):
|
|
||||||
COLS = ('id', 'type',
|
|
||||||
'project_id', 'user_id',
|
|
||||||
'started_at', 'ended_at',
|
|
||||||
'revision_start', 'revision_end')
|
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(CliResourceList, self).get_parser(prog_name)
|
|
||||||
parser.add_argument("--details", action='store_true',
|
|
||||||
help="Show all attributes of generic resources"),
|
|
||||||
parser.add_argument("--history", action='store_true',
|
|
||||||
help="Show history of the resources"),
|
|
||||||
parser.add_argument("resource_type",
|
|
||||||
default="generic",
|
|
||||||
nargs='?',
|
|
||||||
help="Type of resource")
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
resources = self.app.client.resource.list(
|
|
||||||
resource_type=parsed_args.resource_type,
|
|
||||||
details=parsed_args.details,
|
|
||||||
history=parsed_args.history)
|
|
||||||
return self.COLS, [self._resource2tuple(r) for r in resources]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _resource2tuple(cls, resource):
|
|
||||||
return tuple([resource[k] for k in cls.COLS])
|
|
||||||
|
|
||||||
|
|
||||||
class CliResourceSearch(CliResourceList):
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(CliResourceSearch, self).get_parser(prog_name)
|
|
||||||
parser.add_argument("-q", "--query",
|
|
||||||
help="Query"),
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
resources = self.app.client.resource.search(
|
|
||||||
resource_type=parsed_args.resource_type,
|
|
||||||
details=parsed_args.details,
|
|
||||||
history=parsed_args.history,
|
|
||||||
request=utils.search_query_builder(parsed_args.query))
|
|
||||||
return self.COLS, [self._resource2tuple(r) for r in resources]
|
|
||||||
|
|
||||||
|
|
||||||
def normalize_metrics(res):
|
|
||||||
res['metrics'] = "\n".join(sorted(
|
|
||||||
["%s: %s" % (name, _id)
|
|
||||||
for name, _id in res['metrics'].items()]))
|
|
||||||
|
|
||||||
|
|
||||||
class CliResourceShow(show.ShowOne):
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(CliResourceShow, self).get_parser(prog_name)
|
|
||||||
parser.add_argument("resource_type",
|
|
||||||
default="generic",
|
|
||||||
nargs='?',
|
|
||||||
help="Type of resource")
|
|
||||||
parser.add_argument("resource_id",
|
|
||||||
help="ID of a resource")
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
res = self.app.client.resource.get(
|
|
||||||
resource_type=parsed_args.resource_type,
|
|
||||||
resource_id=parsed_args.resource_id)
|
|
||||||
normalize_metrics(res)
|
|
||||||
return self.dict2columns(res)
|
|
||||||
|
|
||||||
|
|
||||||
class CliResourceCreate(show.ShowOne):
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(CliResourceCreate, self).get_parser(prog_name)
|
|
||||||
parser.add_argument("resource_type",
|
|
||||||
default="generic",
|
|
||||||
nargs='?',
|
|
||||||
help="Type of resource")
|
|
||||||
parser.add_argument("-a", "--attribute", action='append',
|
|
||||||
help=("name and value of a attribute "
|
|
||||||
"separated with a ':'"))
|
|
||||||
parser.add_argument("-m", "--metric", action='append',
|
|
||||||
help=("To add a metric use 'name:id' or "
|
|
||||||
"'name:archive_policy_name'. "
|
|
||||||
"To remove a metric use 'name:-'."))
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def _resource_from_args(self, parsed_args):
|
|
||||||
resource = {}
|
|
||||||
if parsed_args.attribute:
|
|
||||||
for attr in parsed_args.attribute:
|
|
||||||
attr, __, value = attr.partition(":")
|
|
||||||
resource[attr] = value
|
|
||||||
if parsed_args.metric:
|
|
||||||
rid = getattr(parsed_args, 'resource_id', None)
|
|
||||||
if rid:
|
|
||||||
r = self.app.client.resource.get(parsed_args.resource_type,
|
|
||||||
parsed_args.resource_id)
|
|
||||||
default = r['metrics']
|
|
||||||
else:
|
|
||||||
default = {}
|
|
||||||
resource['metrics'] = default
|
|
||||||
for metric in parsed_args.metric:
|
|
||||||
name, __, value = metric.partition(":")
|
|
||||||
if value == '-' or not value:
|
|
||||||
resource['metrics'].pop(name, None)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
value = uuid.UUID(value)
|
|
||||||
except ValueError:
|
|
||||||
value = {'archive_policy_name': value}
|
|
||||||
resource['metrics'][name] = value
|
|
||||||
return resource
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
resource = self._resource_from_args(parsed_args)
|
|
||||||
res = self.app.client.resource.create(
|
|
||||||
resource_type=parsed_args.resource_type, resource=resource)
|
|
||||||
normalize_metrics(res)
|
|
||||||
return self.dict2columns(res)
|
|
||||||
|
|
||||||
|
|
||||||
class CliResourceUpdate(CliResourceCreate):
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(CliResourceUpdate, self).get_parser(prog_name)
|
|
||||||
parser.add_argument("resource_id",
|
|
||||||
help="ID of the resource")
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
resource = self._resource_from_args(parsed_args)
|
|
||||||
res = self.app.client.resource.update(
|
|
||||||
resource_type=parsed_args.resource_type,
|
|
||||||
resource_id=parsed_args.resource_id,
|
|
||||||
resource=resource)
|
|
||||||
normalize_metrics(res)
|
|
||||||
return self.dict2columns(res)
|
|
||||||
|
|
||||||
|
|
||||||
class CliResourceDelete(command.Command):
|
|
||||||
def get_parser(self, prog_name):
|
|
||||||
parser = super(CliResourceDelete, self).get_parser(prog_name)
|
|
||||||
parser.add_argument("resource_id",
|
|
||||||
help="ID of the resource")
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
self.app.client.resource.delete(parsed_args.resource_id)
|
|
||||||
|
170
gnocchiclient/v1/resourcecli.py
Normal file
170
gnocchiclient/v1/resourcecli.py
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from cliff import command
|
||||||
|
from cliff import lister
|
||||||
|
from cliff import show
|
||||||
|
|
||||||
|
from gnocchiclient import utils
|
||||||
|
|
||||||
|
|
||||||
|
class CliResourceList(lister.Lister):
|
||||||
|
COLS = ('id', 'type',
|
||||||
|
'project_id', 'user_id',
|
||||||
|
'started_at', 'ended_at',
|
||||||
|
'revision_start', 'revision_end')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CliResourceList, self).get_parser(prog_name)
|
||||||
|
parser.add_argument("--details", action='store_true',
|
||||||
|
help="Show all attributes of generic resources"),
|
||||||
|
parser.add_argument("--history", action='store_true',
|
||||||
|
help="Show history of the resources"),
|
||||||
|
parser.add_argument("resource_type",
|
||||||
|
default="generic",
|
||||||
|
nargs='?',
|
||||||
|
help="Type of resource")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
resources = self.app.client.resource.list(
|
||||||
|
resource_type=parsed_args.resource_type,
|
||||||
|
details=parsed_args.details,
|
||||||
|
history=parsed_args.history)
|
||||||
|
return self.COLS, [self._resource2tuple(r) for r in resources]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _resource2tuple(cls, resource):
|
||||||
|
return tuple([resource[k] for k in cls.COLS])
|
||||||
|
|
||||||
|
|
||||||
|
class CliResourceSearch(CliResourceList):
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CliResourceSearch, self).get_parser(prog_name)
|
||||||
|
parser.add_argument("-q", "--query",
|
||||||
|
help="Query"),
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
resources = self.app.client.resource.search(
|
||||||
|
resource_type=parsed_args.resource_type,
|
||||||
|
details=parsed_args.details,
|
||||||
|
history=parsed_args.history,
|
||||||
|
request=utils.search_query_builder(parsed_args.query))
|
||||||
|
return self.COLS, [self._resource2tuple(r) for r in resources]
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_metrics(res):
|
||||||
|
res['metrics'] = "\n".join(sorted(
|
||||||
|
["%s: %s" % (name, _id)
|
||||||
|
for name, _id in res['metrics'].items()]))
|
||||||
|
|
||||||
|
|
||||||
|
class CliResourceShow(show.ShowOne):
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CliResourceShow, self).get_parser(prog_name)
|
||||||
|
parser.add_argument("resource_type",
|
||||||
|
default="generic",
|
||||||
|
nargs='?',
|
||||||
|
help="Type of resource")
|
||||||
|
parser.add_argument("resource_id",
|
||||||
|
help="ID of a resource")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
res = self.app.client.resource.get(
|
||||||
|
resource_type=parsed_args.resource_type,
|
||||||
|
resource_id=parsed_args.resource_id)
|
||||||
|
normalize_metrics(res)
|
||||||
|
return self.dict2columns(res)
|
||||||
|
|
||||||
|
|
||||||
|
class CliResourceCreate(show.ShowOne):
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CliResourceCreate, self).get_parser(prog_name)
|
||||||
|
parser.add_argument("resource_type",
|
||||||
|
default="generic",
|
||||||
|
nargs='?',
|
||||||
|
help="Type of resource")
|
||||||
|
parser.add_argument("-a", "--attribute", action='append',
|
||||||
|
help=("name and value of a attribute "
|
||||||
|
"separated with a ':'"))
|
||||||
|
parser.add_argument("-m", "--metric", action='append',
|
||||||
|
help=("To add a metric use 'name:id' or "
|
||||||
|
"'name:archive_policy_name'. "
|
||||||
|
"To remove a metric use 'name:-'."))
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def _resource_from_args(self, parsed_args):
|
||||||
|
resource = {}
|
||||||
|
if parsed_args.attribute:
|
||||||
|
for attr in parsed_args.attribute:
|
||||||
|
attr, __, value = attr.partition(":")
|
||||||
|
resource[attr] = value
|
||||||
|
if parsed_args.metric:
|
||||||
|
rid = getattr(parsed_args, 'resource_id', None)
|
||||||
|
if rid:
|
||||||
|
r = self.app.client.resource.get(parsed_args.resource_type,
|
||||||
|
parsed_args.resource_id)
|
||||||
|
default = r['metrics']
|
||||||
|
else:
|
||||||
|
default = {}
|
||||||
|
resource['metrics'] = default
|
||||||
|
for metric in parsed_args.metric:
|
||||||
|
name, __, value = metric.partition(":")
|
||||||
|
if value == '-' or not value:
|
||||||
|
resource['metrics'].pop(name, None)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
value = uuid.UUID(value)
|
||||||
|
except ValueError:
|
||||||
|
value = {'archive_policy_name': value}
|
||||||
|
resource['metrics'][name] = value
|
||||||
|
return resource
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
resource = self._resource_from_args(parsed_args)
|
||||||
|
res = self.app.client.resource.create(
|
||||||
|
resource_type=parsed_args.resource_type, resource=resource)
|
||||||
|
normalize_metrics(res)
|
||||||
|
return self.dict2columns(res)
|
||||||
|
|
||||||
|
|
||||||
|
class CliResourceUpdate(CliResourceCreate):
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CliResourceUpdate, self).get_parser(prog_name)
|
||||||
|
parser.add_argument("resource_id",
|
||||||
|
help="ID of the resource")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
resource = self._resource_from_args(parsed_args)
|
||||||
|
res = self.app.client.resource.update(
|
||||||
|
resource_type=parsed_args.resource_type,
|
||||||
|
resource_id=parsed_args.resource_id,
|
||||||
|
resource=resource)
|
||||||
|
normalize_metrics(res)
|
||||||
|
return self.dict2columns(res)
|
||||||
|
|
||||||
|
|
||||||
|
class CliResourceDelete(command.Command):
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CliResourceDelete, self).get_parser(prog_name)
|
||||||
|
parser.add_argument("resource_id",
|
||||||
|
help="ID of the resource")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.client.resource.delete(parsed_args.resource_id)
|
12
setup.cfg
12
setup.cfg
@ -28,12 +28,12 @@ console_scripts =
|
|||||||
gnocchi = gnocchiclient.shell:main
|
gnocchi = gnocchiclient.shell:main
|
||||||
|
|
||||||
gnocchi.cli.v1 =
|
gnocchi.cli.v1 =
|
||||||
resource_list = gnocchiclient.v1.resource:CliResourceList
|
resource_list = gnocchiclient.v1.resourcecli:CliResourceList
|
||||||
resource_show = gnocchiclient.v1.resource:CliResourceShow
|
resource_show = gnocchiclient.v1.resourcecli:CliResourceShow
|
||||||
resource_search = gnocchiclient.v1.resource:CliResourceSearch
|
resource_search = gnocchiclient.v1.resourcecli:CliResourceSearch
|
||||||
resource_create = gnocchiclient.v1.resource:CliResourceCreate
|
resource_create = gnocchiclient.v1.resourcecli:CliResourceCreate
|
||||||
resource_update = gnocchiclient.v1.resource:CliResourceUpdate
|
resource_update = gnocchiclient.v1.resourcecli:CliResourceUpdate
|
||||||
resource_delete = gnocchiclient.v1.resource:CliResourceDelete
|
resource_delete = gnocchiclient.v1.resourcecli:CliResourceDelete
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
|
Loading…
Reference in New Issue
Block a user