diff --git a/openstack_dashboard/dashboards/project/stacks/tabs.py b/openstack_dashboard/dashboards/project/stacks/tabs.py
index 53c698e9f0..f21ff12bd5 100644
--- a/openstack_dashboard/dashboards/project/stacks/tabs.py
+++ b/openstack_dashboard/dashboards/project/stacks/tabs.py
@@ -139,10 +139,24 @@ class StackResourcesTab(tabs.Tab):
request, data=resources, stack=stack), }
+class StackTemplateTab(tabs.Tab):
+ name = _("Template")
+ slug = "stack_template"
+ template_name = "project/stacks/_stack_template.html"
+
+ def allowed(self, request):
+ return policy.check(
+ (("orchestration", "cloudformation:DescribeStacks"),),
+ request)
+
+ def get_context_data(self, request):
+ return {"stack_template": self.tab_group.kwargs['stack_template']}
+
+
class StackDetailTabs(tabs.TabGroup):
slug = "stack_details"
tabs = (StackTopologyTab, StackOverviewTab, StackResourcesTab,
- StackEventsTab)
+ StackEventsTab, StackTemplateTab)
sticky = True
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_template.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_template.html
new file mode 100644
index 0000000000..085c75fe7a
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_template.html
@@ -0,0 +1,8 @@
+{% load i18n sizeformat %}
+
+
{% trans "Stack Template" %}
+
+
+
{{ stack_template }}
+
+
diff --git a/openstack_dashboard/dashboards/project/stacks/views.py b/openstack_dashboard/dashboards/project/stacks/views.py
index 53b9bc598c..729aa7010e 100644
--- a/openstack_dashboard/dashboards/project/stacks/views.py
+++ b/openstack_dashboard/dashboards/project/stacks/views.py
@@ -14,6 +14,8 @@ import json
import logging
from operator import attrgetter
+import yaml
+
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.http import HttpResponse # noqa
@@ -216,9 +218,22 @@ class DetailView(tabs.TabView):
msg = _("Unable to retrieve stack.")
exceptions.handle(request, msg, redirect=self.get_redirect_url())
+ @memoized.memoized_method
+ def get_template(self, request, **kwargs):
+ try:
+ stack_template = api.heat.template_get(
+ request,
+ kwargs['stack_id'])
+ return yaml.safe_dump(stack_template, indent=2)
+ except Exception:
+ msg = _("Unable to retrieve stack template.")
+ exceptions.handle(request, msg, redirect=self.get_redirect_url())
+
def get_tabs(self, request, **kwargs):
stack = self.get_data(request, **kwargs)
- return self.tab_group_class(request, stack=stack, **kwargs)
+ stack_template = self.get_template(request, **kwargs)
+ return self.tab_group_class(
+ request, stack=stack, stack_template=stack_template, **kwargs)
@staticmethod
def get_redirect_url():
diff --git a/requirements.txt b/requirements.txt
index f69ca45300..8076b5be48 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -38,6 +38,7 @@ python-saharaclient>=0.7.5
python-swiftclient>=2.2.0
python-troveclient>=1.0.7
pytz
+PyYAML>=3.1.0
six>=1.7.0
xstatic>=1.0.0 # MIT License
xstatic-angular>=1.2.1.1 # MIT License