summaryrefslogtreecommitdiff
path: root/heatclient
diff options
context:
space:
mode:
authorSteve Baker <sbaker@redhat.com>2012-11-28 11:55:23 +1300
committerSteve Baker <sbaker@redhat.com>2012-11-28 11:58:11 +1300
commit23478147aa0c29d8c1bf86b76551b2bd6f3e108a (patch)
tree4cb05ddf2f21f4d7a8281929427bcf150da203e1 /heatclient
parent97b24ccb279a4cb554b092589794e6b0902bccca (diff)
downloadpython-heatclient-23478147aa0c29d8c1bf86b76551b2bd6f3e108a.tar.gz
Support for events list and details
This also replaces resource_id with resource_name in the resources API. Change-Id: Ia5ccec5d94fb8106be2dfe89976db0fceeb73b58
Diffstat (limited to 'heatclient')
-rw-r--r--heatclient/v1/client.py4
-rw-r--r--heatclient/v1/events.py64
-rw-r--r--heatclient/v1/resources.py40
-rw-r--r--heatclient/v1/shell.py62
-rw-r--r--heatclient/v1/stacks.py14
5 files changed, 146 insertions, 38 deletions
diff --git a/heatclient/v1/client.py b/heatclient/v1/client.py
index 22ad382..2742728 100644
--- a/heatclient/v1/client.py
+++ b/heatclient/v1/client.py
@@ -14,8 +14,9 @@
# under the License.
from heatclient.common import http
-from heatclient.v1 import stacks
+from heatclient.v1 import events
from heatclient.v1 import resources
+from heatclient.v1 import stacks
class Client(http.HTTPClient):
@@ -33,3 +34,4 @@ class Client(http.HTTPClient):
super(Client, self).__init__(*args, **kwargs)
self.stacks = stacks.StackManager(self)
self.resources = resources.ResourceManager(self)
+ self.events = events.EventManager(self)
diff --git a/heatclient/v1/events.py b/heatclient/v1/events.py
new file mode 100644
index 0000000..07d9f5c
--- /dev/null
+++ b/heatclient/v1/events.py
@@ -0,0 +1,64 @@
+# Copyright 2012 OpenStack LLC.
+# All Rights Reserved.
+#
+# 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.
+
+from heatclient.common import base
+from heatclient.v1 import stacks
+import heatclient.exc as exc
+
+DEFAULT_PAGE_SIZE = 20
+
+
+class Event(base.Resource):
+ def __repr__(self):
+ return "<Event %s>" % self._info
+
+ def update(self, **fields):
+ self.manager.update(self, **fields)
+
+ def delete(self):
+ return self.manager.delete(self)
+
+ def data(self, **kwargs):
+ return self.manager.data(self, **kwargs)
+
+
+class EventManager(stacks.StackChildManager):
+ resource_class = Event
+
+ def list(self, stack_id, resource_name=None):
+ """Get a list of events.
+ :param stack_id: ID of stack the events belong to
+ :param resource_name: Optional name of resources to filter events by
+ :rtype: list of :class:`Event`
+ """
+ if resource_name == None:
+ url = '/stacks/%s/events' % stack_id
+ else:
+ stack_id = self._resolve_stack_id(stack_id)
+ url = '/stacks/%s/resources/%s/events' % (stack_id, resource_name)
+ return self._list(url, "events")
+
+ def get(self, stack_id, resource_name, event_id):
+ """Get the details for a specific event.
+
+ :param stack_id: ID of stack containing the event
+ :param resource_name: ID of resource the event belongs to
+ :param event_id: ID of event to get the details for
+ """
+ stack_id = self._resolve_stack_id(stack_id)
+ resp, body = self.api.json_request('GET',
+ '/stacks/%s/resources/%s/events/%s' %
+ (stack_id, resource_name, event_id))
+ return Event(self, body['event'])
diff --git a/heatclient/v1/resources.py b/heatclient/v1/resources.py
index 3afd00c..f00e65f 100644
--- a/heatclient/v1/resources.py
+++ b/heatclient/v1/resources.py
@@ -14,6 +14,7 @@
# under the License.
from heatclient.common import base
+from heatclient.v1 import stacks
import heatclient.exc as exc
DEFAULT_PAGE_SIZE = 20
@@ -33,7 +34,7 @@ class Resource(base.Resource):
return self.manager.data(self, **kwargs)
-class ResourceManager(base.Manager):
+class ResourceManager(stacks.StackChildManager):
resource_class = Resource
def list(self, stack_id):
@@ -43,38 +44,27 @@ class ResourceManager(base.Manager):
url = '/stacks/%s/resources' % stack_id
return self._list(url, "resources")
- def get(self, stack_id, resource_id):
+ def get(self, stack_id, resource_name):
"""Get the details for a specific resource.
:param stack_id: ID of stack containing the resource
- :param resource_id: ID of resource to get the details for
+ :param resource_name: ID of resource to get the details for
"""
- resp, body = self._get_resolve_fallback(stack_id, resource_id,
- '/stacks/%s/resources/%s')
+ stack_id = self._resolve_stack_id(stack_id)
+ resp, body = self.api.json_request('GET',
+ '/stacks/%s/resources/%s' %
+ (stack_id, resource_name))
+
return Resource(self, body['resource'])
- def metadata(self, stack_id, resource_id):
+ def metadata(self, stack_id, resource_name):
"""Get the metadata for a specific resource.
:param stack_id: ID of stack containing the resource
- :param resource_id: ID of resource to get metadata for
+ :param resource_name: ID of resource to get metadata for
"""
- resp, body = self._get_resolve_fallback(stack_id, resource_id,
- '/stacks/%s/resources/%s/metadata')
- return Resource(self, body['metadata'])
-
- def _get_resolve_fallback(self, stack_id, resource_id, path_pattern):
- try:
- resp, body = self.api.json_request('GET',
- path_pattern % (stack_id, resource_id))
- except exc.HTTPNotFound:
- stack_id = self._resolve_stack_id(stack_id)
- resp, body = self.api.json_request('GET',
- path_pattern % (stack_id, resource_id))
- return (resp, body)
-
- def _resolve_stack_id(self, stack_id):
+ stack_id = self._resolve_stack_id(stack_id)
resp, body = self.api.json_request('GET',
- '/stacks/%s' % stack_id)
- stack = body['stack']
- return '%s/%s' % (stack['stack_name'], stack['id'])
+ '/stacks/%s/resources/%s/metadata' %
+ (stack_id, resource_name))
+ return Resource(self, body['metadata'])
diff --git a/heatclient/v1/shell.py b/heatclient/v1/shell.py
index 8502c9a..de64c96 100644
--- a/heatclient/v1/shell.py
+++ b/heatclient/v1/shell.py
@@ -176,12 +176,12 @@ def do_resource_list(hc, args):
@utils.arg('id', metavar='<NAME or ID>',
help='Name or ID of stack to show the resource for.')
-@utils.arg('resource', metavar='<RESOURCE NAME or ID>',
- help='Name or ID of the resource to show the details for.')
+@utils.arg('resource', metavar='<RESOURCE>',
+ help='Name of the resource to show the details for.')
def do_resource(hc, args):
'''Describe the resource'''
fields = {'stack_id': args.id,
- 'resource_id': args.resource}
+ 'resource_name': args.resource}
try:
resource = hc.resources.get(**fields)
except exc.HTTPNotFound:
@@ -198,12 +198,12 @@ def do_resource(hc, args):
@utils.arg('id', metavar='<NAME or ID>',
help='Name or ID of stack to show the resource metadata for.')
-@utils.arg('resource', metavar='<RESOURCE NAME or ID>',
- help='Name or ID of the resource to show the metadata for.')
+@utils.arg('resource', metavar='<RESOURCE>',
+ help='Name of the resource to show the metadata for.')
def do_resource_metadata(hc, args):
'''List resource metadata'''
fields = {'stack_id': args.id,
- 'resource_id': args.resource}
+ 'resource_name': args.resource}
try:
resource = hc.resources.metadata(**fields)
except exc.HTTPNotFound:
@@ -213,9 +213,47 @@ def do_resource_metadata(hc, args):
formatters = {}
utils.print_dict(resource.to_dict(), formatters=formatters)
-# TODO only need to implement this once the server supports it
-#@utils.arg('id', metavar='<NAME or ID>',
-# help='Name or ID of stack to show the events for.')
-#def do_event_list(hc, args):
-# '''List events for a stack'''
-# pass
+
+@utils.arg('id', metavar='<NAME or ID>',
+ help='Name or ID of stack to show the events for.')
+@utils.arg('-r', '--resource', metavar='<RESOURCE>',
+ help='Name of the resource to filter events by')
+def do_event_list(hc, args):
+ '''List events for a stack'''
+ fields = {'stack_id': args.id,
+ 'resource_name': args.resource}
+ try:
+ events = hc.events.list(**fields)
+ except exc.HTTPNotFound:
+ raise exc.CommandError('Stack not found: %s' % args.id)
+ else:
+ field_labels = ['Resource', 'ID', 'Reason',
+ 'Status', 'Event time']
+ fields = ['logical_resource_id', 'id', 'resource_status_reason',
+ 'resource_status', 'event_time']
+ utils.print_list(events, fields, field_labels, sortby=4)
+
+
+@utils.arg('id', metavar='<NAME or ID>',
+ help='Name or ID of stack to show the events for.')
+@utils.arg('resource', metavar='<RESOURCE>',
+ help='Name of the resource the event belongs to.')
+@utils.arg('event', metavar='<EVENT>',
+ help='ID of event to display details for')
+def do_event(hc, args):
+ '''Describe the event'''
+ fields = {'stack_id': args.id,
+ 'resource_name': args.resource,
+ 'event_id': args.event}
+ try:
+ event = hc.events.get(**fields)
+ except exc.HTTPNotFound:
+ raise exc.CommandError('Stack not found: %s' % args.id)
+ else:
+ link_format = lambda links: '\n'.join([l['href'] for l in links])
+ json_format = lambda js: json.dumps(js, indent=2)
+ formatters = {
+ 'links': link_format,
+ 'resource_properties': json_format
+ }
+ utils.print_dict(event.to_dict(), formatters=formatters)
diff --git a/heatclient/v1/stacks.py b/heatclient/v1/stacks.py
index 75114d5..f9980a4 100644
--- a/heatclient/v1/stacks.py
+++ b/heatclient/v1/stacks.py
@@ -16,6 +16,7 @@
import urllib
from heatclient.common import base
+import heatclient.exc as exc
DEFAULT_PAGE_SIZE = 20
@@ -118,3 +119,16 @@ class StackManager(base.Manager):
resp, body = self.api.json_request(
'POST', '/validate', body=kwargs)
return body
+
+
+class StackChildManager(base.Manager):
+
+ def _resolve_stack_id(self, stack_id):
+ # if the id already has a slash in it,
+ # then it is already {stack_name}/{stack_id}
+ if stack_id.find('/') > 0:
+ return stack_id
+ resp, body = self.api.json_request('GET',
+ '/stacks/%s' % stack_id)
+ stack = body['stack']
+ return '%s/%s' % (stack['stack_name'], stack['id'])