diff options
author | Steve Baker <sbaker@redhat.com> | 2012-11-28 11:55:23 +1300 |
---|---|---|
committer | Steve Baker <sbaker@redhat.com> | 2012-11-28 11:58:11 +1300 |
commit | 23478147aa0c29d8c1bf86b76551b2bd6f3e108a (patch) | |
tree | 4cb05ddf2f21f4d7a8281929427bcf150da203e1 /heatclient | |
parent | 97b24ccb279a4cb554b092589794e6b0902bccca (diff) | |
download | python-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.py | 4 | ||||
-rw-r--r-- | heatclient/v1/events.py | 64 | ||||
-rw-r--r-- | heatclient/v1/resources.py | 40 | ||||
-rw-r--r-- | heatclient/v1/shell.py | 62 | ||||
-rw-r--r-- | heatclient/v1/stacks.py | 14 |
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']) |