Merge "Submit generated template file directly"
This commit is contained in:
commit
cb74de0857
@ -112,7 +112,7 @@ def _ignore_if(key, value):
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def get_template_files(template_data=None, template_url=None):
|
||||
def get_template_files(template_data=None, template_url=None, files=None):
|
||||
if template_data:
|
||||
tpl = template_data
|
||||
elif template_url:
|
||||
@ -125,6 +125,7 @@ def get_template_files(template_data=None, template_url=None):
|
||||
if isinstance(tpl, six.binary_type):
|
||||
tpl = tpl.decode('utf-8')
|
||||
template = template_format.parse(tpl)
|
||||
if files is None:
|
||||
files = {}
|
||||
_get_file_contents(template, files)
|
||||
return files, template
|
||||
@ -138,6 +139,8 @@ def _get_file_contents(from_data, files):
|
||||
for key, value in from_data.items():
|
||||
if _ignore_if(key, value):
|
||||
continue
|
||||
if value in files:
|
||||
continue
|
||||
if not value.startswith(('http://', 'https://')):
|
||||
raise exceptions.GetFileError(value, 'get_file')
|
||||
if value not in files:
|
||||
|
@ -127,6 +127,10 @@ class TemplateForm(forms.SelfHandlingForm):
|
||||
widget=forms.widgets.Textarea(attrs=attributes),
|
||||
required=False)
|
||||
|
||||
referenced_files = forms.CharField(label=_('Referenced Files'),
|
||||
widget=forms.widgets.HiddenInput,
|
||||
required=False)
|
||||
|
||||
if django.VERSION >= (1, 9):
|
||||
# Note(Itxaka): On django>=1.9 Charfield has an strip option that
|
||||
# we need to set to False as to not hit
|
||||
@ -146,6 +150,12 @@ class TemplateForm(forms.SelfHandlingForm):
|
||||
self.clean_uploaded_files('environment', _('environment'), cleaned,
|
||||
files)
|
||||
|
||||
referenced_files = cleaned.get('referenced_files')
|
||||
if referenced_files:
|
||||
referenced_files = json.loads(referenced_files)
|
||||
elif referenced_files == '':
|
||||
referenced_files = {}
|
||||
|
||||
# Validate the template and get back the params.
|
||||
kwargs = {}
|
||||
if cleaned['environment_data']:
|
||||
@ -153,7 +163,8 @@ class TemplateForm(forms.SelfHandlingForm):
|
||||
try:
|
||||
files, tpl =\
|
||||
api.heat.get_template_files(cleaned.get('template_data'),
|
||||
cleaned.get('template_url'))
|
||||
cleaned.get('template_url'),
|
||||
referenced_files)
|
||||
kwargs['files'] = files
|
||||
kwargs['template'] = tpl
|
||||
validated = api.heat.template_validate(self.request, **kwargs)
|
||||
@ -181,7 +192,6 @@ class TemplateForm(forms.SelfHandlingForm):
|
||||
:rtype: dict
|
||||
:return: cleaned dict including environment & template data
|
||||
"""
|
||||
|
||||
upload_str = prefix + "_upload"
|
||||
data_str = prefix + "_data"
|
||||
url = cleaned.get(prefix + '_url')
|
||||
|
@ -4,4 +4,15 @@
|
||||
{% block modal-body-right %}
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Use one of the available template source options to specify the template to be used in creating this stack." %}</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
if (window.sessionStorage.generated == 'true'){
|
||||
$("#id_template_data").val(window.sessionStorage.getItem("template"));
|
||||
$("#id_referenced_files").val(window.sessionStorage.getItem("files"));
|
||||
}
|
||||
window.sessionStorage.setItem('generated', false);
|
||||
// window.sessionStorage.removeItem('template');
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
18
heat_dashboard/content/stacks/templates/stacks/index.html
Normal file
18
heat_dashboard/content/stacks/templates/stacks/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{{ page_title }}{% endblock %}
|
||||
{% block main %}{{ table.render }}{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{% include "horizon/_scripts.html" %}
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
var session = window.sessionStorage;
|
||||
if (session.getItem('generated') == 'true'){
|
||||
$("#stacks__action_launch").attr('href', window.location.pathname+'select_template?template_source=raw');
|
||||
$("#stacks__action_launch").click();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
@ -39,6 +39,7 @@ from horizon import views
|
||||
class IndexView(tables.DataTableView):
|
||||
table_class = project_tables.StacksTable
|
||||
page_title = _("Stacks")
|
||||
template_name = 'project/stacks/index.html'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(IndexView, self).__init__(*args, **kwargs)
|
||||
|
@ -12,23 +12,29 @@
|
||||
|
||||
import json
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard import api as dashboard_api
|
||||
from openstack_dashboard.api.neutron import neutronclient
|
||||
|
||||
from heat_dashboard import api
|
||||
|
||||
|
||||
def get_resources(request):
|
||||
|
||||
volumes = [vol.to_dict() for vol in api.cinder.volume_list(request)]
|
||||
volumes = [
|
||||
vol.to_dict() for vol in dashboard_api.cinder.volume_list(request)]
|
||||
volume_snapshots = [
|
||||
volsnap.to_dict()
|
||||
for volsnap in api.cinder.volume_snapshot_list(request)]
|
||||
volume_types = [voltype.to_dict()
|
||||
for voltype in api.cinder.volume_type_list(request)]
|
||||
volume_backups = [volbackup.to_dict()
|
||||
for volbackup in api.cinder.volume_backup_list(request)]
|
||||
for volsnap in dashboard_api.cinder.volume_snapshot_list(request)]
|
||||
volume_types = [
|
||||
voltype.to_dict()
|
||||
for voltype in dashboard_api.cinder.volume_type_list(request)]
|
||||
volume_backups = [
|
||||
volbackup.to_dict()
|
||||
for volbackup in dashboard_api.cinder.volume_backup_list(request)]
|
||||
|
||||
images = [img.to_dict()
|
||||
for img in api.glance.image_list_detailed(request)[0]]
|
||||
images = [
|
||||
img.to_dict()
|
||||
for img in dashboard_api.glance.image_list_detailed(request)[0]]
|
||||
|
||||
neutron_client = neutronclient(request)
|
||||
floatingips = neutron_client.list_floatingips().get('floatingips')
|
||||
@ -41,13 +47,17 @@ def get_resources(request):
|
||||
# qos_policies = neutron_client.list_security_groups().get('ports')
|
||||
|
||||
availability_zones = \
|
||||
[az.to_dict() for az in api.nova.availability_zone_list(request)]
|
||||
[az.to_dict()
|
||||
for az in dashboard_api.nova.availability_zone_list(request)]
|
||||
flavors = \
|
||||
[flavor.to_dict() for flavor in api.nova.flavor_list(request)]
|
||||
[flavor.to_dict()
|
||||
for flavor in dashboard_api.nova.flavor_list(request)]
|
||||
instances = \
|
||||
[server.to_dict() for server in api.nova.server_list(request)[0]]
|
||||
[server.to_dict()
|
||||
for server in dashboard_api.nova.server_list(request)[0]]
|
||||
keypairs = \
|
||||
[keypair.to_dict() for keypair in api.nova.keypair_list(request)]
|
||||
[keypair.to_dict()
|
||||
for keypair in dashboard_api.nova.keypair_list(request)]
|
||||
|
||||
opts = {
|
||||
'user_roles': request.user.roles,
|
||||
@ -76,28 +86,31 @@ def get_resource_options(request):
|
||||
|
||||
volumes = [{'id': vol.id,
|
||||
'name': vol.name if vol.name else '(%s)' % vol.id}
|
||||
for vol in api.cinder.volume_list(request)]
|
||||
for vol in dashboard_api.cinder.volume_list(request)]
|
||||
volume_snapshots = [
|
||||
{'id': volsnap.id,
|
||||
'name': volsnap.name if volsnap.name else '(%s)' % volsnap.id[:6]}
|
||||
for volsnap in api.cinder.volume_snapshot_list(request)]
|
||||
for volsnap in dashboard_api.cinder.volume_snapshot_list(request)]
|
||||
volume_types = [{
|
||||
'id': voltype.id,
|
||||
'name': voltype.name if voltype.name else '(%s)' % voltype.id[:6]}
|
||||
for voltype in api.cinder.volume_type_list(request)]
|
||||
volume_backups = [{'id': volbackup.id,
|
||||
for voltype in dashboard_api.cinder.volume_type_list(request)]
|
||||
volume_backups = [
|
||||
{'id': volbackup.id,
|
||||
'name': volbackup.name
|
||||
if volbackup.name else '(%s)' % volbackup.id[:6]}
|
||||
for volbackup in api.cinder.volume_backup_list(request)]
|
||||
for volbackup in dashboard_api.cinder.volume_backup_list(request)]
|
||||
|
||||
images = [{'id': img.id,
|
||||
images = [
|
||||
{'id': img.id,
|
||||
'name': img.name if img.name else '(%s)' % img.id[:6]}
|
||||
for img in api.glance.image_list_detailed(request)[0]]
|
||||
for img in dashboard_api.glance.image_list_detailed(request)[0]]
|
||||
|
||||
floatingips = [
|
||||
{'id': fip.id, 'name': fip.floating_ip_address}
|
||||
for fip in api.neutron.tenant_floating_ip_list(request, True)]
|
||||
all_networks = api.neutron.network_list(request)
|
||||
for fip in dashboard_api.neutron.tenant_floating_ip_list(
|
||||
request, True)]
|
||||
all_networks = dashboard_api.neutron.network_list(request)
|
||||
networks = [{'id': nw.id,
|
||||
'name': nw.name if nw.name else '(%s)' % nw.id[:6]}
|
||||
for nw in all_networks if not nw['router:external']]
|
||||
@ -108,14 +121,15 @@ def get_resource_options(request):
|
||||
|
||||
ports = [{'id': port.id,
|
||||
'name': port.name if port.name else '(%s)' % port.id[:6]}
|
||||
for port in api.neutron.port_list(request)]
|
||||
for port in dashboard_api.neutron.port_list(request)]
|
||||
security_groups = [
|
||||
{'id': secgroup.id,
|
||||
'name': secgroup.name
|
||||
if secgroup.name else '(%s)' % secgroup.id[:6]}
|
||||
for secgroup in api.neutron.security_group_list(request)]
|
||||
all_subnets = api.neutron.subnet_list(request)
|
||||
subnets = [{'id': subnet.id,
|
||||
for secgroup in dashboard_api.neutron.security_group_list(request)]
|
||||
all_subnets = dashboard_api.neutron.subnet_list(request)
|
||||
subnets = [
|
||||
{'id': subnet.id,
|
||||
'name': subnet.name if subnet.name else '(%s)' % subnet.id[:6]}
|
||||
for subnet in all_subnets]
|
||||
|
||||
@ -123,27 +137,31 @@ def get_resource_options(request):
|
||||
for subnet in all_subnets
|
||||
if subnet.network_id in floating_network_ids]
|
||||
|
||||
routers = [{'id': router.id,
|
||||
routers = [
|
||||
{'id': router.id,
|
||||
'name': router.name if router.name else '(%s)' % router.id[:6]}
|
||||
for router in api.neutron.router_list(request)]
|
||||
for router in dashboard_api.neutron.router_list(request)]
|
||||
qos_policies = []
|
||||
# qos_policies = [{'id': policy.id,
|
||||
# qos_policies = [
|
||||
# {'id': policy.id,
|
||||
# 'name': policy.name
|
||||
# if policy.name else '(%s)' % policy.id[:6]}
|
||||
# for policy in api.neutron.policy_list(request)]
|
||||
# for policy in dashboard_api.neutron.policy_list(request)]
|
||||
|
||||
availability_zones = [{'id': az.zoneName, 'name': az.zoneName}
|
||||
for az in api.nova.availability_zone_list(request)]
|
||||
availability_zones = [
|
||||
{'id': az.zoneName, 'name': az.zoneName}
|
||||
for az in dashboard_api.nova.availability_zone_list(request)]
|
||||
flavors = [{'id': flavor.name, 'name': flavor.name}
|
||||
for flavor in api.nova.flavor_list(request)]
|
||||
for flavor in dashboard_api.nova.flavor_list(request)]
|
||||
instances = [{'id': server.id,
|
||||
'name': server.name
|
||||
if server.name else '(%s)' % server.id[:6]}
|
||||
for server in api.nova.server_list(request)[0]]
|
||||
for server in dashboard_api.nova.server_list(request)[0]]
|
||||
keypairs = [{'name': keypair.name}
|
||||
for keypair in api.nova.keypair_list(request)]
|
||||
for keypair in dashboard_api.nova.keypair_list(request)]
|
||||
|
||||
template_versions = [{'name': version.version, 'id': version.version}
|
||||
template_versions = [
|
||||
{'name': version.version, 'id': version.version}
|
||||
for version in api.heat.template_version_list(request)
|
||||
if version.type == 'hot']
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
resource_options: {'auth': {'admin': false}},
|
||||
template_version: null,
|
||||
resource_outputs: {},
|
||||
reference_file: {},
|
||||
reference_files: {},
|
||||
};
|
||||
|
||||
return {
|
||||
@ -79,10 +79,13 @@
|
||||
return Object.keys(globals.resource_icons);
|
||||
},
|
||||
set_reference_file: function(key, value){
|
||||
globals.reference_file[key] = value;
|
||||
globals.reference_files[key] = value;
|
||||
},
|
||||
get_reference_file: function(key){
|
||||
return globals.reference_file[key];
|
||||
return globals.reference_files[key];
|
||||
},
|
||||
get_reference_files: function(key){
|
||||
return globals.reference_files;
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -5,8 +5,10 @@
|
||||
.controller('horizon.dashboard.project.heat_dashboard.template_generator.TempModalController', ['$scope',
|
||||
'$mdDialog', 'hotgenNotify', 'hotgenUtils', 'hotgenStates', 'hotgenGlobals',
|
||||
'horizon.dashboard.project.heat_dashboard.template_generator.basePath',
|
||||
function($scope, $mdDialog, hotgenNotify, hotgenUtils, hotgenStates, hotgenGlobals, basePath){
|
||||
'horizon.dashboard.project.heat_dashboard.template_generator.projectPath',
|
||||
function($scope, $mdDialog, hotgenNotify, hotgenUtils, hotgenStates, hotgenGlobals, basePath, projectPath){
|
||||
$scope.basePath = basePath;
|
||||
$scope.projectPath = projectPath;
|
||||
$scope.dialogController = function ($scope, $mdDialog, hotgenStates, hotgenGlobals, hotgenNotify) {
|
||||
$scope.all_saved = false;
|
||||
$scope.cancel = function() {
|
||||
@ -22,11 +24,20 @@
|
||||
|
||||
hotgenNotify.show_success('Template is downloaded.');
|
||||
};
|
||||
$scope.save = function() {
|
||||
hotgenNotify.show_warning('Not implemented yet. To submit to create a stack.')
|
||||
$mdDialog.cancel();
|
||||
|
||||
$scope.redirect = function(){
|
||||
var redirect = window.location.origin + projectPath + 'stacks/';
|
||||
window.location.href = redirect;
|
||||
};
|
||||
|
||||
$scope.save = function() {
|
||||
var files = hotgenGlobals.get_reference_files();
|
||||
sessionStorage.setItem('files', JSON.stringify(files));
|
||||
sessionStorage.setItem('generated', true);
|
||||
sessionStorage.setItem('template', $scope.template_contents);
|
||||
$scope.redirect();
|
||||
// $mdDialog.cancel();
|
||||
};
|
||||
$scope.extract_properties = function(resource_data){
|
||||
for (var property in resource_data){
|
||||
var func = null;
|
||||
|
@ -7,12 +7,13 @@
|
||||
|
||||
beforeEach(module('appTemplates'));
|
||||
|
||||
var hotgenGlobals, hotgenStates, hotgenNotify, basePath;
|
||||
var hotgenGlobals, hotgenStates, hotgenNotify, basePath, projectPath;
|
||||
beforeEach(inject(function($injector){
|
||||
hotgenGlobals = $injector.get('hotgenGlobals');
|
||||
hotgenStates = $injector.get('hotgenStates');
|
||||
hotgenNotify = $injector.get('hotgenNotify');
|
||||
basePath = $injector.get('horizon.dashboard.project.heat_dashboard.template_generator.basePath');
|
||||
projectPath = $injector.get('horizon.dashboard.project.heat_dashboard.template_generator.projectPath');
|
||||
}));
|
||||
|
||||
var $controller, controller, $scope, $rootScope, $mdDialog;
|
||||
@ -83,9 +84,13 @@
|
||||
|
||||
it('$scope.dialogController save', function(){
|
||||
$scope.dialogController($scope, $mdDialog, hotgenStates, hotgenGlobals, hotgenNotify);
|
||||
|
||||
$scope.redirect = jasmine.createSpy().and.callFake(function() {
|
||||
return function(){return true};
|
||||
});
|
||||
$scope.save();
|
||||
|
||||
expect($mdDialog.cancel).toHaveBeenCalled();
|
||||
expect($scope.redirect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('$scope.dialogController extract_properties', function(){
|
||||
|
@ -20,8 +20,11 @@
|
||||
});
|
||||
}])
|
||||
.config(['$provide', '$windowProvider', function($provide, $windowProvider){
|
||||
var path = $windowProvider.$get().STATIC_URL + 'dashboard/project/heat_dashboard/template_generator/';
|
||||
$provide.constant('horizon.dashboard.project.heat_dashboard.template_generator.basePath', path);
|
||||
var project_window = $windowProvider.$get();
|
||||
var staticPath = project_window.STATIC_URL + 'dashboard/project/heat_dashboard/template_generator/';
|
||||
var projectPath = project_window.WEBROOT+'project/';
|
||||
$provide.constant('horizon.dashboard.project.heat_dashboard.template_generator.basePath', staticPath);
|
||||
$provide.constant('horizon.dashboard.project.heat_dashboard.template_generator.projectPath', projectPath);
|
||||
|
||||
}])
|
||||
.constant('horizon.dashboard.project.heat_dashboard.template_generator.validationRules', {
|
||||
|
@ -35,7 +35,7 @@ from heat_dashboard.content.stacks import mappings
|
||||
from heat_dashboard.content.stacks import tables
|
||||
|
||||
|
||||
INDEX_TEMPLATE = 'horizon/common/_data_table_view.html'
|
||||
INDEX_TEMPLATE = 'project/stacks/index.html'
|
||||
INDEX_URL = reverse('horizon:project:stacks:index')
|
||||
DETAIL_URL = 'horizon:project:stacks:detail'
|
||||
|
||||
@ -270,6 +270,7 @@ class StackTests(test.TestCase):
|
||||
|
||||
form_data = {'template_source': 'raw',
|
||||
'template_data': template.data,
|
||||
'referenced_files': {},
|
||||
'method': forms.TemplateForm.__name__}
|
||||
res = self.client.post(url, form_data)
|
||||
self.assertTemplateUsed(res, 'project/stacks/create.html')
|
||||
|
Loading…
Reference in New Issue
Block a user