diff --git a/openstack_dashboard/api/rest/__init__.py b/openstack_dashboard/api/rest/__init__.py index 1bf1dd8369..6d34350329 100644 --- a/openstack_dashboard/api/rest/__init__.py +++ b/openstack_dashboard/api/rest/__init__.py @@ -25,6 +25,7 @@ in https://wiki.openstack.org/wiki/APIChangeGuidelines. from . import cinder #flake8: noqa from . import config #flake8: noqa from . import glance #flake8: noqa +from . import heat #flake8: noqa from . import keystone #flake8: noqa from . import network #flake8: noqa from . import neutron #flake8: noqa diff --git a/openstack_dashboard/api/rest/heat.py b/openstack_dashboard/api/rest/heat.py new file mode 100644 index 0000000000..338e758567 --- /dev/null +++ b/openstack_dashboard/api/rest/heat.py @@ -0,0 +1,39 @@ + +# 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. +"""API for the heat service. +""" + +from django.views import generic + +from openstack_dashboard import api +from openstack_dashboard.api.rest import urls +from openstack_dashboard.api.rest import utils as rest_utils + + +@urls.register +class Validate(generic.View): + """API for validating a template + """ + url_regex = r'heat/validate/$' + + @rest_utils.ajax() + def post(self, request): + """Validate a template + + The following parameters may be passed in the POST + application/json object. The parameters are: + request: + + :param template_url: The template to validate + """ + return api.heat.template_validate(request, **(request.DATA)) diff --git a/openstack_dashboard/static/app/core/openstack-service-api/heat.service.js b/openstack_dashboard/static/app/core/openstack-service-api/heat.service.js new file mode 100644 index 0000000000..d35112a7d5 --- /dev/null +++ b/openstack_dashboard/static/app/core/openstack-service-api/heat.service.js @@ -0,0 +1,61 @@ +/* + * 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. + */ +(function () { + 'use strict'; + + angular + .module('horizon.app.core.openstack-service-api') + .service('horizon.app.core.openstack-service-api.heat', HeatAPI); + + HeatAPI.$inject = [ + 'horizon.framework.util.http.service', + 'horizon.framework.widgets.toast.service' + ]; + + /** + * @ngdoc service + * @name horizon.app.core.openstack-service-api.heat + * @description Provides direct pass through to Heat with NO abstraction. + */ + function HeatAPI(apiService, toastService) { + var service = { + validate: validate + }; + + return service; + + /** + * @name horizon.app.core.openstack-service-api.heat.validate + * @description + * Validate a template. + * + * The result is an object. + * + * @param {string} params.template_url + * Specifies the template to validate. + * + * @param {boolean} suppressError + * If passed in, this will not show the default error handling + * (horizon alert). + */ + function validate(params, suppressError) { + var promise = apiService.post('/api/heat/validate/', params); + return suppressError ? promise : promise.error(function() { + toastService.add('error', gettext('Unable to validate the template.')); + }); + } + + } + +}()); diff --git a/openstack_dashboard/static/app/core/openstack-service-api/heat.service.spec.js b/openstack_dashboard/static/app/core/openstack-service-api/heat.service.spec.js new file mode 100644 index 0000000000..782dbe6e0d --- /dev/null +++ b/openstack_dashboard/static/app/core/openstack-service-api/heat.service.spec.js @@ -0,0 +1,67 @@ +/* + * 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. + */ + +(function() { + 'use strict'; + + describe('Heat API', function() { + var testCall, service; + var apiService = {}; + var toastService = {}; + + beforeEach( + module('horizon.mock.openstack-service-api', + function($provide, initServices) { + testCall = initServices($provide, apiService, toastService); + }) + ); + + beforeEach(module('horizon.app.core.openstack-service-api')); + + beforeEach(inject(['horizon.app.core.openstack-service-api.heat', function(heatAPI) { + service = heatAPI; + }])); + + it('defines the service', function() { + expect(service).toBeDefined(); + }); + + var tests = [ + { + 'func': 'validate', + 'method': 'post', + 'path': '/api/heat/validate/', + 'data': { + 'template_url':'http://localhost/test.template' + }, + 'error': 'Unable to validate the template.', + 'testInput': [ + { + 'template_url':'http://localhost/test.template' + } + ] + } + ]; + + // Iterate through the defined tests and apply as Jasmine specs. + angular.forEach(tests, function(params) { + it('defines the ' + params.func + ' call properly', function() { + var callParams = [apiService, service, toastService, params]; + testCall.apply(this, callParams); + }); + }); + + }); + +})(); diff --git a/openstack_dashboard/test/api_tests/heat_rest_tests.py b/openstack_dashboard/test/api_tests/heat_rest_tests.py new file mode 100644 index 0000000000..45f6911d23 --- /dev/null +++ b/openstack_dashboard/test/api_tests/heat_rest_tests.py @@ -0,0 +1,29 @@ +# 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. +import json +import mock + +from openstack_dashboard.api.rest import heat +from openstack_dashboard.test import helpers as test + + +class ValidateRestTestCase(test.TestCase): + @mock.patch.object(heat.api, 'heat') + def test_validate_post(self, hc): + body = '''{"template_url":"http://localhost/template.yaml"}''' + request = self.mock_rest_request(body=body) + hc.template_validate.return_value = ({'Description': 'foo'}) + response = heat.Validate().post(request) + self.assertStatusCode(response, 200) + self.assertEqual(response.content, '{"Description": "foo"}') + kwargs = json.loads(body) + hc.template_validate.assert_called_once_with(request, **kwargs)