]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
heat cli : Align resource-list-details usage with other commands
authorSteven Hardy <shardy@redhat.com>
Tue, 10 Jul 2012 12:56:41 +0000 (13:56 +0100)
committerSteven Hardy <shardy@redhat.com>
Tue, 10 Jul 2012 14:17:02 +0000 (15:17 +0100)
Align resource-list-details usage with the other heat commands,
and provide better usage info on failure
Fixes #156

Change-Id: Id80b377151eca64e5f7dbfb436f5a5da5213c8b3
Signed-off-by: Steven Hardy <shardy@redhat.com>
bin/heat
bin/heat-boto

index 99ca84be0c41151b92b9ba344f55c8eabc7719a7..4aa5638c279c3d67c22da40076cd55cba8cdf3ff 100755 (executable)
--- a/bin/heat
+++ b/bin/heat
@@ -50,6 +50,8 @@ else:
         if os.access(jeos_path, os.R_OK):
             break
 
+scriptname = os.path.basename(sys.argv[0])
+
 gettext.install('heat', unicode=1)
 
 from heat import client as heat_client
@@ -334,20 +336,74 @@ def stack_resources_list(options, arguments):
     print result
 
 
+def _resources_list_details(options, lookup_key='StackName',
+                            lookup_value=None, log_resid=None):
+    '''
+    Helper function to reduce duplication in stack_resources_list_details
+    Looks up resource details based on StackName or PhysicalResourceId
+    '''
+    c = get_client(options)
+    parameters = {}
+
+    if lookup_key in ['StackName', 'PhysicalResourceId']:
+        parameters[lookup_key] = lookup_value
+    else:
+        logging.error("Unexpected key %s" % lookup_key)
+        return
+
+    if log_resid:
+        parameters['LogicalResourceId'] = log_resid
+
+    try:
+        result = c.describe_stack_resources(**parameters)
+    except:
+        logging.debug("Failed to lookup resource details with key %s:%s" %
+            (lookup_key, lookup_value))
+        return
+
+    return result
+
+
 @utils.catch_error('resource-list-details')
 def stack_resources_list_details(options, arguments):
     '''
-    Display details of all resources in the specified stack.
+    Display details of resources in the specified stack.
+
+    - If stack name is specified, all associated resources are returned
+    - If physical resource ID is specified, all associated resources of the
+    stack the resource belongs to are returned
+    - You must specify stack name *or* physical resource ID
+    - You may optionally specify a Logical resource ID to filter the result
     '''
-    c = get_client(options)
+    usage = ('''Usage:
+%s resource-list-details stack_name [logical_resource_id]
+%s resource-list-details physical_resource_id [logical_resource_id]''' %
+        (scriptname, scriptname))
+
+    try:
+        name_or_pid = arguments.pop(0)
+    except IndexError:
+        logging.error("No valid stack_name or physical_resource_id")
+        print usage
+        return
+
     logical_resource_id = arguments.pop(0) if arguments else None
-    parameters = {
-        'StackName': options.stack_name,
-        'PhysicalResourceId': options.physical_resource_id,
-        'LogicalResourceId': logical_resource_id,
-    }
-    result = c.describe_stack_resources(**parameters)
-    print result
+
+    # Try StackName first as it seems the most likely..
+    lookup_keys = ['StackName', 'PhysicalResourceId']
+    for key in lookup_keys:
+        logging.debug("Looking up resources for %s:%s" % (key, name_or_pid))
+        result = _resources_list_details(options, lookup_key=key,
+                                         lookup_value=name_or_pid,
+                                         log_resid=logical_resource_id)
+        if result:
+            break
+
+    if result:
+        print result
+    else:
+        logging.error("No valid stack_name or physical_resource_id")
+        print usage
 
 
 @utils.catch_error('list')
@@ -450,10 +506,6 @@ def create_options(parser):
 
     parser.add_option('-P', '--parameters', metavar="parameters", default=None,
                       help="Parameter values used to create the stack.")
-    parser.add_option('-n', '--stack-name', default=None,
-                      help="Name of the queried stack")
-    parser.add_option('-c', '--physical-resource-id', default=None,
-                      help="Physical ID of the queried resource")
 
 
 def credentials_from_env():
index 40a06ea1c63618a58286a4b54872d91f031d510d..91f15188de057bcfca24529170b955f075111848 100755 (executable)
@@ -39,6 +39,8 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
 if os.path.exists(os.path.join(possible_topdir, 'heat', '__init__.py')):
     sys.path.insert(0, possible_topdir)
 
+scriptname = os.path.basename(sys.argv[0])
+
 gettext.install('heat', unicode=1)
 
 import boto
@@ -406,18 +408,55 @@ def stack_resources_list(options, arguments):
 @utils.catch_error('resource-list-details')
 def stack_resources_list_details(options, arguments):
     '''
-    Display details of all resources in the specified stack.
+    Display details of resources in the specified stack.
+
+    - If stack name is specified, all associated resources are returned
+    - If physical resource ID is specified, all associated resources of the
+    stack the resource belongs to are returned
+    - You must specify stack name *or* physical resource ID
+    - You may optionally specify a Logical resource ID to filter the result
     '''
-    c = get_client(options)
-    logical_resource_id = arguments.pop(0) if arguments else None
-    if not options.stack_name and not options.physical_resource_id:
-        logging.error(
-            "Must specify either stack-name physical-resource-id")
+    usage = ('''Usage:
+%s resource-list-details stack_name [logical_resource_id]
+%s resource-list-details physical_resource_id [logical_resource_id]''' %
+        (scriptname, scriptname))
+
+    try:
+        name_or_pid = arguments.pop(0)
+    except IndexError:
+        logging.error("Must pass a stack_name or physical_resource_id")
+        print usage
         return
-    result = c.describe_stack_resources(options.stack_name,
-        logical_resource_id, options.physical_resource_id)
-    for r in result:
-        print_stack_resource(r)
+
+    logical_resource_id = arguments.pop(0) if arguments else None
+
+    c = get_client(options)
+
+    # Check if this is a StackName, if not assume it's a physical res ID
+    # Note this is slower (for the common case, which is probably StackName)
+    # than just doing a try/catch over the StackName case then retrying
+    # on failure with name_or_pid as the physical resource ID, however
+    # boto spews errors when raising an exception so we can't do that
+    list_stacks = c.list_stacks()
+    stack_names = [s.stack_name for s in list_stacks]
+    if name_or_pid in stack_names:
+        logging.debug("Looking up resources for StackName:%s" % name_or_pid)
+        result = c.describe_stack_resources(stack_name_or_id=name_or_pid,
+            logical_resource_id=logical_resource_id)
+    else:
+        logging.debug("Looking up resources for PhysicalResourceId:%s" %
+            name_or_pid)
+        result = c.describe_stack_resources(stack_name_or_id=None,
+            logical_resource_id=logical_resource_id,
+            physical_resource_id=name_or_pid)
+
+    if result:
+        for r in result:
+            print_stack_resource(r)
+    else:
+        logging.error("Invalid stack_name, physical_resource_id " +
+                      "or logical_resource_id")
+        print usage
 
 
 @utils.catch_error('list')
@@ -525,10 +564,6 @@ def create_options(parser):
 
     parser.add_option('-P', '--parameters', metavar="parameters", default=None,
                       help="Parameter values used to create the stack.")
-    parser.add_option('-n', '--stack-name', default=None,
-                      help="Name of the queried stack")
-    parser.add_option('-c', '--physical-resource-id', default=None,
-                      help="Physical ID of the queried resource")
 
 
 def credentials_from_env():