summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--heatclient/osc/v1/stack.py28
-rw-r--r--heatclient/tests/inline_templates.py78
-rw-r--r--heatclient/tests/unit/osc/v1/test_stack.py45
-rw-r--r--setup.cfg1
4 files changed, 152 insertions, 0 deletions
diff --git a/heatclient/osc/v1/stack.py b/heatclient/osc/v1/stack.py
index dc1c9d3..c0b988c 100644
--- a/heatclient/osc/v1/stack.py
+++ b/heatclient/osc/v1/stack.py
@@ -807,3 +807,31 @@ class OutputListStack(lister.Lister):
columns,
(utils.get_dict_properties(s, columns) for s in outputs)
)
+
+
+class TemplateShowStack(format_utils.YamlFormat):
+ """Display stack template."""
+
+ log = logging.getLogger(__name__ + '.TemplateShowStack')
+
+ def get_parser(self, prog_name):
+ parser = super(TemplateShowStack, self).get_parser(prog_name)
+ parser.add_argument(
+ 'stack',
+ metavar='<NAME or ID>',
+ help=_('Name or ID of stack to query')
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ self.log.debug('take_action(%s)', parsed_args)
+
+ client = self.app.client_manager.orchestration
+
+ try:
+ template = client.stacks.template(stack_id=parsed_args.stack)
+ except heat_exc.HTTPNotFound:
+ msg = _('Stack not found: %s') % parsed_args.stack
+ raise exc.CommandError(msg)
+
+ return self.dict2columns(template)
diff --git a/heatclient/tests/inline_templates.py b/heatclient/tests/inline_templates.py
new file mode 100644
index 0000000..56667ac
--- /dev/null
+++ b/heatclient/tests/inline_templates.py
@@ -0,0 +1,78 @@
+#
+# Copyright 2016 IBM Corp.
+#
+# 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.
+
+FULL_TEMPLATE = '''
+heat_template_version: 2016-04-08
+
+description: a template
+
+parameter_groups:
+ - label: param_group_1
+ description: parameter group 1
+ parameters:
+ - param1
+ - param2
+ - label: param_group_2
+ description: parameter group 2
+ parameters:
+ - param3
+
+parameters:
+ param1:
+ type: string
+ label: parameter 5
+ description: parameter 5
+ default: foo
+ hidden: false
+ constraints:
+ - allowed_values: ['foo', 'bar', 'bax']
+ param2:
+ type: number
+ default: 0
+ constraints:
+ - range: {min: 0, max: 10}
+ description: must be betwen 0 and 10
+ param3:
+ type: boolean
+
+resources:
+ resource1:
+ type: OS::Heat::None
+ properties:
+ prop1: { get_param: param1 }
+ prop2: { get_param: param2 }
+ prop3: value
+ resource2:
+ type: OS::Heat::None
+ properties:
+ prop1: { get_param: param3 }
+ depends_on: resource1
+
+outputs:
+ output1:
+ description: resource 1 prop 3
+ value: { get_attr: [resource1, prop3] }
+ output2:
+ description: resource 2 prop 1
+ value: { get_attr: [resource2, prop1] }
+'''
+
+SHORT_TEMPLATE = '''
+heat_template_version: 2016-04-08
+
+resources:
+ res1:
+ type: OS::Heat::None
+'''
diff --git a/heatclient/tests/unit/osc/v1/test_stack.py b/heatclient/tests/unit/osc/v1/test_stack.py
index 8dd30cb..f74b800 100644
--- a/heatclient/tests/unit/osc/v1/test_stack.py
+++ b/heatclient/tests/unit/osc/v1/test_stack.py
@@ -16,12 +16,15 @@ import io
import mock
import six
import testscenarios
+import yaml
from openstackclient.common import exceptions as exc
from openstackclient.common import utils
+from heatclient.common import template_format
from heatclient import exc as heat_exc
from heatclient.osc.v1 import stack
+from heatclient.tests import inline_templates
from heatclient.tests.unit.osc.v1 import fakes as orchestration_fakes
from heatclient.v1 import stacks
@@ -757,3 +760,45 @@ class TestStackOutputList(TestStack):
error = self.assertRaises(exc.CommandError,
self.cmd.take_action, parsed_args)
self.assertEqual('Stack not found: my_stack', str(error))
+
+
+class TestStackTemplateShow(TestStack):
+
+ fields = ['heat_template_version', 'description', 'parameter_groups',
+ 'parameters', 'resources', 'outputs']
+
+ def setUp(self):
+ super(TestStackTemplateShow, self).setUp()
+ self.cmd = stack.TemplateShowStack(self.app, None)
+
+ def test_stack_template_show_full_template(self):
+ arglist = ['my_stack']
+ self.stack_client.template = mock.MagicMock(
+ return_value=yaml.load(inline_templates.FULL_TEMPLATE,
+ Loader=template_format.yaml_loader))
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ columns, outputs = self.cmd.take_action(parsed_args)
+
+ for f in self.fields:
+ self.assertIn(f, columns)
+
+ def test_stack_template_show_short_template(self):
+ arglist = ['my_stack']
+ self.stack_client.template = mock.MagicMock(
+ return_value=yaml.load(inline_templates.SHORT_TEMPLATE,
+ Loader=template_format.yaml_loader))
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ columns, outputs = self.cmd.take_action(parsed_args)
+
+ for f in ['heat_template_version', 'resources']:
+ self.assertIn(f, columns)
+
+ def test_stack_template_show_not_found(self):
+ arglist = ['my_stack']
+ self.stack_client.template = mock.MagicMock(
+ side_effect=heat_exc.HTTPNotFound)
+ parsed_args = self.check_parser(self.cmd, arglist, [])
+
+ self.assertRaises(exc.CommandError, self.cmd.take_action, parsed_args)
diff --git a/setup.cfg b/setup.cfg
index 1f6fbb0..bdb82d2 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -45,6 +45,7 @@ openstack.orchestration.v1 =
stack_resource_metadata = heatclient.osc.v1.resources:ResourceMetadata
stack_show = heatclient.osc.v1.stack:ShowStack
stack_snapshot_list = heatclient.osc.v1.snapshot:ListSnapshot
+ stack_template_show = heatclient.osc.v1.stack:TemplateShowStack
stack_update = heatclient.osc.v1.stack:UpdateStack
[global]