diff --git a/.gitreview b/.gitreview new file mode 100644 index 0000000..ac42f31 --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=review.openstack.org +port=29418 +project=stackforge/murano-repository.git diff --git a/ChangeLog b/ChangeLog index 3006463..3bd941a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +commit d259b6c33a4379c12dd673cb8cabc769545739d0 +Author: efedorova +Date: Thu Oct 17 19:18:08 2013 +0400 + + Refactoring API and Archiver module + + * Set uo manifest.in and tox.ini + * Add test module + + Change-Id: I265401658922c75b50db4d1232af17215ee1b6fc + +commit e4b9fe765e912a13ff02a394b329ecd117a0edb7 +Author: efedorova +Date: Tue Oct 15 19:03:09 2013 +0400 + + Fix buf with manifests listing + +commit b24d260524d16dce96a682fd32629951e2ac17ee +Author: efedorova +Date: Tue Oct 15 18:47:27 2013 +0400 + + Update api + +commit ecb0c93b3077755192929fa8ddf045ef43d43112 +Author: efedorova +Date: Mon Oct 14 16:54:00 2013 +0400 + + Fix typos + +commit c46bfbde86728d689677a2d7d484b2db04893186 +Author: efedorova +Date: Mon Oct 14 16:34:33 2013 +0400 + + Remove service to muranorepository + + Add venv support + Update requirements + commit 28cbd261871038cf1fc4fa67d36c26ae9e9a4747 Author: efedorova Date: Mon Oct 14 13:27:09 2013 +0400 diff --git a/MANIFEST.in b/MANIFEST.in index 0720919..fdf902d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,10 +1,13 @@ -include AUTHORS -include README.rst -include ChangeLog -include LICENSE - recursive-include Services * - +include ChangeLog +include README.rst +include MANIFEST.in +include AUTHORS +include LICENSE +include ChangeLog +include babel.cfg +include tox.ini +include muranorepository/tests/test.conf exclude .gitignore exclude .gitreview diff --git a/etc/murano-repository.conf b/etc/murano-repository.conf index 6b0ea01..8078e89 100644 --- a/etc/murano-repository.conf +++ b/etc/murano-repository.conf @@ -1,6 +1,6 @@ [DEFAULT] # Address to bind the server to -host = 172.18.10.111 +host = localhost #Port the bind the server to port = 5000 diff --git a/muranorepository/__init__.py b/muranorepository/__init__.py index 207fa15..7d93825 100644 --- a/muranorepository/__init__.py +++ b/muranorepository/__init__.py @@ -10,4 +10,4 @@ # 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. \ No newline at end of file +# under the License. diff --git a/muranorepository/api/__init__.py b/muranorepository/api/__init__.py index 207fa15..7d93825 100644 --- a/muranorepository/api/__init__.py +++ b/muranorepository/api/__init__.py @@ -10,4 +10,4 @@ # 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. \ No newline at end of file +# under the License. diff --git a/muranorepository/api/v1.py b/muranorepository/api/v1.py index 5ace695..9ab52df 100644 --- a/muranorepository/api/v1.py +++ b/muranorepository/api/v1.py @@ -1,19 +1,20 @@ # Copyright (c) 2013 Mirantis, Inc. # -# Licensed under the Apache License, Version 2.0 (the "License"); you may +# 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 +# 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 os -from flask import Blueprint, make_response, send_file + +from flask import Blueprint, send_file from flask import jsonify, request, abort from werkzeug import secure_filename @@ -26,116 +27,132 @@ CONF = cfg.CONF v1_api = Blueprint('v1', __name__) -@v1_api.route('/client/ui') -def get_ui_data(): +def get_archive(client): parser = ManifestParser(CONF.manifests) manifests = parser.parse() - archive_name = Archiver().create(manifests, "ui") + if client == 'conductor': + return Archiver().create(manifests, + 'heat', + 'agent', + 'scripts') + else: + return Archiver().create(manifests, client) - return send_file(archive_name) + +def get_locations(data_type, result_path): + locations = [] + if data_type == MANIFEST: + for item in os.listdir(result_path): + if '-manifest' in item and \ + os.path.isfile(os.path.join(result_path, item)): + locations.append(item) + else: + for path, subdirs, files in os.walk(result_path): + for name in files: + if path != result_path: + base, diff = path.rsplit(result_path, 2) + # split base path and remove slash + name = os.path.join(diff[1:], name) + locations.append(name) + return jsonify({data_type: locations}) + + +def save_file(request, result_path): + file_to_upload = request.files.get('file') + if file_to_upload: + filename = secure_filename(file_to_upload.filename) + file_to_upload.save(os.path.join(result_path, filename)) + return jsonify(result='success') + else: + abort(400) + + +def compose_path(data_type, path=None): + if path: + return os.path.join(CONF.manifests, getattr(CONF, data_type), path) + else: + return os.path.join(CONF.manifests, getattr(CONF, data_type)) + + +def check_data_type(data_type): + if data_type not in DATA_TYPES: + abort(404) + + +@v1_api.route('/client/ui') +def get_ui_data(): + return send_file(get_archive('ui')) @v1_api.route('/client/conductor') def get_conductor_data(): - parser = ManifestParser(CONF.manifests) - manifests = parser.parse() - archive_name = Archiver().create(manifests, - "heat", - "agent", - "scripts") - return send_file(archive_name) + return send_file(get_archive('conductor')) -@v1_api.route('/admin/', methods=['GET', 'POST']) +@v1_api.route('/admin/') def get_data_type_locations(data_type): - ####### validation ######## - if data_type not in DATA_TYPES: - abort(404) - result_path = os.path.join(CONF.manifests, getattr(CONF, data_type)) - ####### end validation ######## - if request.method == 'GET': - locations = [] - if data_type == MANIFEST: - for item in os.listdir(result_path): - if '-manifest' in item: - locations.append(item) - else: - for path, subdirs, files in os.walk(result_path): - for name in files: - locations.append(name) - result = {data_type: locations} - return jsonify(result) - - if request.method == 'POST': - try: - file_to_upload = request.files.get('files') - if file_to_upload: - filename = secure_filename(file_to_upload.filename) - file_to_upload.save(os.path.join(result_path, filename)) - return jsonify(result="success") - except: - abort(403) + check_data_type(data_type) + result_path = compose_path(data_type) + return get_locations(data_type, result_path) -@v1_api.route('/admin//', methods=['GET', 'POST']) -def get_data_type_locations_by_path_or_get_file(data_type, path): - if data_type not in DATA_TYPES: - abort(404) - result_path = os.path.join(os.path.join(CONF.manifests, - getattr(CONF, data_type), - path)) +@v1_api.route('/admin/', methods=['POST']) +def upload_file(data_type): + check_data_type(data_type) + result_path = compose_path(data_type) + try: + return save_file(request, result_path) + except: + abort(403) + + +@v1_api.route('/admin//') +def get_locations_in_nested_path_or_get_file(data_type, path): + check_data_type(data_type) + result_path = compose_path(data_type, path) + if os.path.isfile(result_path): + return send_file(result_path) + else: + return get_locations(data_type, result_path) + + +@v1_api.route('/admin//', methods=['POST']) +def upload_file_in_nested_path(data_type, path): + check_data_type(data_type) + result_path = compose_path(data_type, path) + return save_file(request, result_path) + + +@v1_api.route('/admin//', methods=['PUT']) +def create_dirs(data_type, path): + check_data_type(data_type) + result_path = compose_path(data_type, path) + resp = jsonify(result='success') + if os.path.exists(result_path): + return resp + if data_type == MANIFEST: + abort(403) + try: + os.makedirs(result_path) + except Exception: + abort(403) + return resp + + +@v1_api.route('/admin//', methods=['DELETE']) +def delete_dirictory_or_file(data_type, path): + check_data_type(data_type) + result_path = compose_path(data_type, path) if not os.path.exists(result_path): abort(404) - - if request.method == 'GET': - locations = [] - if os.path.isfile(result_path): - return send_file(result_path) - else: - for file in os.listdir(result_path): - locations.append(file) - result = {data_type: locations} - return jsonify(result) - - if request.method == 'POST': - file_to_upload = request.files.get('files') - if file_to_upload: - filename = secure_filename(file_to_upload.filename) - file_to_upload.save(os.path.join(result_path, filename)) - return jsonify(result="success") - else: - abort(403) - - -@v1_api.route('/admin//', methods=['PUT', 'DELETE']) -def create_dirs(data_type, path): - if data_type not in DATA_TYPES: - abort(404) - result_path = os.path.join(CONF.manifests, getattr(CONF, data_type), path) - if request.method == 'PUT': - resp = make_response() - if os.path.exists(result_path): - return resp - if data_type == MANIFEST: - abort(403) + if os.path.isfile(result_path): try: - os.makedirs(result_path) - except Exception as e: - abort(403) - return resp - - if request.method == 'DELETE': - if not os.path.exists(result_path): + os.remove(result_path) + except Exception: abort(404) - if os.path.isfile(result_path): - try: - os.remove(result_path) - except Exception as e: - abort(404) - else: - try: - os.rmdir(result_path) - except Exception as e: - abort(403) - resp = make_response() - return resp + else: + try: + os.rmdir(result_path) + except Exception: + abort(403) + return jsonify(result='success') diff --git a/muranorepository/cmd/__init__.py b/muranorepository/cmd/__init__.py index 207fa15..7d93825 100644 --- a/muranorepository/cmd/__init__.py +++ b/muranorepository/cmd/__init__.py @@ -10,4 +10,4 @@ # 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. \ No newline at end of file +# under the License. diff --git a/muranorepository/cmd/run.py b/muranorepository/cmd/run.py index 761c9de..f31548f 100644 --- a/muranorepository/cmd/run.py +++ b/muranorepository/cmd/run.py @@ -28,8 +28,8 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir, os.pardir)) if os.path.exists(os.path.join(possible_topdir, - 'muranorepository', - '__init__.py')): + 'muranorepository', + '__init__.py')): sys.path.insert(0, possible_topdir) from muranorepository import config @@ -43,7 +43,7 @@ LOG = log.getLogger(__name__) def main(): dev_conf = os.path.join(possible_topdir, 'etc', - 'muranorepository.conf') + 'murano-repository.conf') config_files = None if os.path.exists(dev_conf): config_files = [dev_conf] diff --git a/muranorepository/consts.py b/muranorepository/consts.py index 026e756..a306d29 100644 --- a/muranorepository/consts.py +++ b/muranorepository/consts.py @@ -20,4 +20,4 @@ HEAT = 'heat' AGENT = 'agent' SCRIPTS = 'scripts' -DATA_TYPES = [UI, WORKFLOW, HEAT, AGENT, SCRIPTS, MANIFEST] \ No newline at end of file +DATA_TYPES = [UI, WORKFLOW, HEAT, AGENT, SCRIPTS, MANIFEST] diff --git a/muranorepository/manifest.py b/muranorepository/manifest.py index a6410f3..14d69eb 100644 --- a/muranorepository/manifest.py +++ b/muranorepository/manifest.py @@ -16,4 +16,4 @@ class Manifest(object): def __init__(self, initial_data): for key in initial_data: - setattr(self, key, initial_data[key]) \ No newline at end of file + setattr(self, key, initial_data[key]) diff --git a/muranorepository/openstack/common/eventlet_backdoor.py b/muranorepository/openstack/common/eventlet_backdoor.py index c64b9d0..b141fd8 100644 --- a/muranorepository/openstack/common/eventlet_backdoor.py +++ b/muranorepository/openstack/common/eventlet_backdoor.py @@ -104,8 +104,7 @@ def _listen(host, start_port, end_port, listen_func): try: return listen_func((host, try_port)) except socket.error as exc: - if (exc.errno != errno.EADDRINUSE or - try_port >= end_port): + if (exc.errno != errno.EADDRINUSE or try_port >= end_port): raise try_port += 1 diff --git a/muranorepository/openstack/common/log.py b/muranorepository/openstack/common/log.py index e9f3f4b..d41a86c 100644 --- a/muranorepository/openstack/common/log.py +++ b/muranorepository/openstack/common/log.py @@ -425,7 +425,8 @@ def _setup_logging_from_conf(): if CONF.publish_errors: handler = importutils.import_object( - "muranorepository.openstack.common.log_handler.PublishErrorsHandler", + "muranorepository.openstack.common.log_handler." + "PublishErrorsHandler", logging.ERROR) log_root.addHandler(handler) diff --git a/muranorepository/openstack/common/test.py b/muranorepository/openstack/common/test.py index 955f10b..dfef9a9 100644 --- a/muranorepository/openstack/common/test.py +++ b/muranorepository/openstack/common/test.py @@ -29,7 +29,8 @@ class BaseTestCase(testtools.TestCase): super(BaseTestCase, self).setUp() self._set_timeout() self._fake_output() - self.useFixture(fixtures.FakeLogger('muranorepository.openstack.common')) + self.useFixture( + fixtures.FakeLogger('muranorepository.openstack.common')) self.useFixture(fixtures.NestedTempfile()) def _set_timeout(self): diff --git a/muranorepository/service_metadata.tar b/muranorepository/service_metadata.tar deleted file mode 100644 index 33903f8..0000000 Binary files a/muranorepository/service_metadata.tar and /dev/null differ diff --git "a/muranorepository/config.example\\" b/muranorepository/tests/__init__.py similarity index 100% rename from "muranorepository/config.example\\" rename to muranorepository/tests/__init__.py diff --git a/muranorepository/tests/fixtures/__init__.py b/muranorepository/tests/fixtures/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/muranorepository/tests/fixtures/consts.py b/muranorepository/tests/fixtures/consts.py new file mode 100644 index 0000000..7bb4315 --- /dev/null +++ b/muranorepository/tests/fixtures/consts.py @@ -0,0 +1,42 @@ +# Copyright (c) 2013 Mirantis Inc. +# +# 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. + +MANIFEST_FILE = '' +'version: 0.1' +'service_display_name: Test' + +'description: >-' +' This goes a description' + +'full_service_name: test_service' +'author: Mirantis Inc.' +'service_version: 1.0' +'enabled: True' + +'ui:' +' - test1.yaml' + +'workflows:' +' - test1.xml' + +'heat:' +' - Windows.template' + +'agents:' +' - test1.template' + + +'scripts:' +' - test1.sh' diff --git a/muranorepository/tests/test.conf b/muranorepository/tests/test.conf new file mode 100644 index 0000000..cb76842 --- /dev/null +++ b/muranorepository/tests/test.conf @@ -0,0 +1,28 @@ +[DEFAULT] +# Address to bind the server to +host = localhost +#Port the bind the server to +port = 5000 + + +# Provide information about data types +# absolute path to manifest location(root directory) +#manifests = /home/fervent/Projects/my_repo/muranorepository/tests/var +manifests = /bin/server + +# Parameter name corresponds to section in manifest file +# Parameter value corresponds to relative path to data type +ui = ui +workflows = workflows +heat = heat +agent = agent +scripts = scripts + +# Configure archive structure +# data_type = desired folder +[output] +ui = service_forms +workflows = workflows +heat = templates/cf +agent = templates/agent +scripts = templates/agent/script diff --git a/muranorepository/tests/test_main.py b/muranorepository/tests/test_main.py new file mode 100644 index 0000000..3ba1b6f --- /dev/null +++ b/muranorepository/tests/test_main.py @@ -0,0 +1,87 @@ +import sys +import os +from flask.ext.testing import TestCase as FlaskTestCase +import shutil +from StringIO import StringIO +import mockfs +possible_topdir = os.path.normpath(os.path.join(os.path.abspath(__file__), + os.pardir, + os.pardir, + os.pardir)) +if os.path.exists(os.path.join(possible_topdir, + 'muranorepository', + '__init__.py')): + sys.path.insert(0, possible_topdir) +from muranorepository.consts import MANIFEST +from muranorepository.tests.fixtures.consts import MANIFEST_FILE +from muranorepository import config +from muranorepository.main import make_app + + +class TestAdminAPI(FlaskTestCase): + url = "/v1/admin/{0}" + url_with_path = "/v1/admin/{0}/{1}" + + def create_app(self): + test_app = make_app() + test_app.config['TESTING'] = True + return test_app + + def setUp(self): + config_files = [os.path.join(possible_topdir, + 'muranorepository', + 'tests', + 'test.conf')] + + config.parse_configs(None, config_files) + self.mfs = mockfs.replace_builtins() + self.mfs.add_entries( + { + '/bin/server': { + 'test-manifest.yaml': MANIFEST_FILE, + 'ui': {'test1.yaml': ''}, + 'heat': + {'Windows.template': '', + 'folder_to_delete': {} + } + } + }) + + def tearDown(self): + mockfs.restore_builtins() + + def test_list_manifests(self): + response = self.client.get(self.url.format(MANIFEST)) + expected_result = {MANIFEST: ['test-manifest.yaml']} + self.assert200(response) + self.assertEquals(response.json, expected_result) + + def test_list_ui(self): + response = self.client.get(self.url.format('ui')) + expected_result = {'ui': ['test1.yaml']} + self.assert200(response) + self.assertEquals(response.json, expected_result) + + def test_create_ui_subfolder(self): + response = self.client.put(self.url_with_path.format('ui', 'test')) + expected_result = {'result': 'success'} + self.assert200(response) + self.assertEquals(response.json, expected_result) + shutil.rmtree('bin/server/ui/test') + + def test_delete_heat_subfolder(self): + url = self.url_with_path.format('heat', + 'folder_to_delete') + response = self.client.delete(url) + self.assert200(response) + expected_result = {'result': 'success'} + self.assertEquals(response.json, expected_result) + + def test_upload_ui_file(self): + upload_data = {'file': (StringIO('content'), 'test.yaml')} + response = self.client.post(self.url.format('ui'), + data=upload_data) + 'test.yaml' in os.listdir('bin/server/ui') + self.assert200(response) + expected_result = {'result': 'success'} + self.assertEquals(response.json, expected_result) diff --git a/muranorepository/utils/__init__.py b/muranorepository/utils/__init__.py index 207fa15..7d93825 100644 --- a/muranorepository/utils/__init__.py +++ b/muranorepository/utils/__init__.py @@ -10,4 +10,4 @@ # 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. \ No newline at end of file +# under the License. diff --git a/muranorepository/utils/archiver.py b/muranorepository/utils/archiver.py index 76d0e8a..e893281 100644 --- a/muranorepository/utils/archiver.py +++ b/muranorepository/utils/archiver.py @@ -18,16 +18,44 @@ import shutil import logging as log from oslo.config import cfg from muranorepository.consts import DATA_TYPES -OUTPUT_CONF = cfg.CONF.output CONF = cfg.CONF class Archiver(object): + def _copy_data(self, file_lists, src, dst): + if not os.path.exists(dst): + os.makedirs(dst) + + for path in file_lists: + source = os.path.join(src, path) + destination = os.path.join(dst, path) + base_dir = os.path.dirname(destination) + + if (base_dir != dst) and (not os.path.exists(base_dir)): + os.makedirs(os.path.dirname(destination)) + try: + shutil.copyfile(source, destination) + except IOError: + log.error("Unable to copy file " + "{0}".format(file)) + + def _compose_archive(self, path): + target_archive = "service_metadata.tar" + with tarfile.open(target_archive, "w") as tar: + for item in os.listdir(path): + tar.add(os.path.join(path, item), item) + try: + shutil.rmtree(path, ignore_errors=True) + except Exception as e: + log.error("Unable to delete temp directory: {0}".format(e)) + return os.path.abspath(target_archive) def create(self, manifests, *types): """ manifests -- list of Manifest objects *types - desired data types to be added to archive + + return: absolute path to created archive """ temp_dir = tempfile.mkdtemp() for data_type in types: @@ -38,44 +66,18 @@ class Archiver(object): for manifest in manifests: if not manifest.enabled and not manifest.valid: continue + if hasattr(manifest, data_type): + file_list = getattr(manifest, data_type) dst_directory = os.path.join(temp_dir, - getattr(OUTPUT_CONF, + getattr(CONF.output, data_type)) scr_directory = os.path.join(CONF.manifests, getattr(CONF, data_type)) - - if not os.path.exists(dst_directory): - os.makedirs(dst_directory) - - for path in getattr(manifest, data_type): - source = os.path.join(scr_directory, path) - destination = os.path.join(dst_directory, path) - base_dir = os.path.dirname(destination) - - if (base_dir != dst_directory) \ - and (not os.path.exists(base_dir)): - os.makedirs(os.path.dirname(destination)) - try: - shutil.copyfile(source, destination) - except IOError: - log.error("Unable to copy file " - "{0}".format(file)) + self._copy_data(file_list, scr_directory, dst_directory) else: log.info( "Manifest for {0} service has no file definitions for " "{1}".format(manifest.service_display_name, data_type)) - target_archive = "service_metadata.tar" - with tarfile.open(target_archive, "w") as tar: - for item in os.listdir(temp_dir): - tar.add(os.path.join(temp_dir, item), item) - try: - shutil.rmtree(temp_dir, ignore_errors=True) - except Exception as e: - log.error("Unable to delete temp directory: {0}".format(e)) - return os.path.abspath(target_archive) - - - - + return self._compose_archive(temp_dir) diff --git a/setup.cfg b/setup.cfg index c3ecfbe..1a3825d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,7 +32,8 @@ author-email = openstack-dev@lists.openstack.org home-page = https://launchpad.net/murano [global] -setup-hooks = pbr.hooks.setup_hook +setup-hooks = + pbr.hooks.setup_hook [files] packages = @@ -54,8 +55,9 @@ tag_date = 0 tag_svn_revision = 0 [compile_catalog] -directory = murano-repository/locale -domain = murano-repository +directory = muranorepository/locale +domain = muranorepository + [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext diff --git a/test-requirements.txt b/test-requirements.txt index 67d9663..dd15aa8 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,16 +2,11 @@ pep8==1.4.5 pyflakes>=0.7.2,<0.7.4 flake8==2.0 -hacking>=0.5.6,<0.8 - -coverage>=3.6 +flask-testing docutils==0.9.1 fixtures>=0.3.14 mock>=1.0 -nose -openstack.nose_plugin>=0.7 +mockfs oslo.sphinx pylint==0.25.2 -sphinx>=1.1.2 -sphinxcontrib-httpdomain unittest2 diff --git a/tools/config/generate_sample.sh b/tools/config/generate_sample.sh deleted file mode 100755 index 4c6d101..0000000 --- a/tools/config/generate_sample.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash - -print_hint() { - echo "Try \`${0##*/} --help' for more information." >&2 -} - -PARSED_OPTIONS=$(getopt -n "${0##*/}" -o hb:p:o: \ - --long help,base-dir:,package-name:,output-dir: -- "$@") - -if [ $? != 0 ] ; then print_hint ; exit 1 ; fi - -eval set -- "$PARSED_OPTIONS" - -while true; do - case "$1" in - -h|--help) - echo "${0##*/} [options]" - echo "" - echo "options:" - echo "-h, --help show brief help" - echo "-b, --base-dir=DIR Project base directory (required)" - echo "-p, --package-name=NAME Project package name" - echo "-o, --output-dir=DIR File output directory" - exit 0 - ;; - -b|--base-dir) - shift - BASEDIR=`echo $1 | sed -e 's/\/*$//g'` - shift - ;; - -p|--package-name) - shift - PACKAGENAME=`echo $1` - shift - ;; - -o|--output-dir) - shift - OUTPUTDIR=`echo $1 | sed -e 's/\/*$//g'` - shift - ;; - --) - break - ;; - esac -done - -if [ -z $BASEDIR ] || ! [ -d $BASEDIR ] -then - echo "${0##*/}: missing project base directory" >&2 ; print_hint ; exit 1 -fi - -PACKAGENAME=${PACKAGENAME:-${BASEDIR##*/}} - -OUTPUTDIR=${OUTPUTDIR:-$BASEDIR/etc} -if ! [ -d $OUTPUTDIR ] -then - echo "${0##*/}: cannot access \`$OUTPUTDIR': No such file or directory" >&2 - exit 1 -fi - -BASEDIRESC=`echo $BASEDIR | sed -e 's/\//\\\\\//g'` -FILES=$(find $BASEDIR/$PACKAGENAME -type f -name "*.py" ! -path "*/tests/*" \ - -exec grep -l "Opt(" {} + | sed -e "s/^$BASEDIRESC\///g" | sort -u) - -export EVENTLET_NO_GREENDNS=yes - -MODULEPATH=murano-repository.openstack.common.config.generator -OUTPUTFILE=$OUTPUTDIR/$PACKAGENAME.conf.sample -python -m $MODULEPATH $FILES > $OUTPUTFILE diff --git a/tox.ini b/tox.ini index b6c0ff6..96186f2 100644 --- a/tox.ini +++ b/tox.ini @@ -10,49 +10,29 @@ setenv = VIRTUAL_ENV={envdir} NOSE_OPENSTACK_SHOW_ELAPSED=1 deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt -commands = nosetests [testenv:pep8] deps = pep8==1.3.3 -commands = pep8 --repeat --show-source murano-repository setup.py - -[testenv:venv] -commands = {posargs} - -[testenv:cover] -commands = nosetests --cover-erase --cover-package=murano-repository --with-xcoverage - -[tox:jenkins] -downloadcache = ~/cache/pip - -[testenv:jenkins26] -basepython = python2.6 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkins27] -basepython = python2.7 -setenv = NOSE_WITH_XUNIT=1 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkinscover] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = nosetests --cover-erase --cover-package=muranoapi --with-xcoverage - -[testenv:jenkinsvenv] -deps = file://{toxinidir}/.cache.bundle -setenv = NOSE_WITH_XUNIT=1 -commands = {posargs} +commands = pep8 --repeat --show-source muranorepository setup.py [testenv:pyflakes] deps = flake8 commands = flake8 +[testenv:venv] +commands = {posargs} + +[testenv:cover] +commands = nosetests --cover-erase --cover-package=muranorepository --with-xcoverage + +[tox:jenkins] +downloadcache = ~/cache/pip + [flake8] # H301 one import per line # H302 import only modules -ignore = H301,H302 +# H201 no 'except:' at least use 'except Exception:' +ignore = H301,H302,F403,H201 show-source = true builtins = _ -exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,tools \ No newline at end of file +exclude=.build,.venv,.git,.tox,dist,doc,*/openstack,*lib/python*,*egg,tools