diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e2a2ae..ef64b7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## 4.0.0 (2015-11-30) + ## 3.0.0 (2014-09-16) New package version "3.0.0" includes the following features: diff --git a/examples/fuel_plugin_example_v2/metadata.yaml b/examples/fuel_plugin_example_v2/metadata.yaml index d895add..62cfd19 100644 --- a/examples/fuel_plugin_example_v2/metadata.yaml +++ b/examples/fuel_plugin_example_v2/metadata.yaml @@ -5,7 +5,7 @@ title: Title for fuel_plugin_example plugin # Plugin version version: '2.0.0' # Description -description: Enable to use plugin X for Neutron +description: Please describe your plugin here # Required fuel version fuel_version: ['6.1'] # Specify license of your plugin diff --git a/examples/fuel_plugin_example_v2_update/metadata.yaml b/examples/fuel_plugin_example_v2_update/metadata.yaml index ee13b5f..eee53c9 100644 --- a/examples/fuel_plugin_example_v2_update/metadata.yaml +++ b/examples/fuel_plugin_example_v2_update/metadata.yaml @@ -5,7 +5,7 @@ title: Title for fuel_plugin_example plugin # Plugin version version: '2.0.2' # Description -description: Enable to use plugin X for Neutron +description: Please describe your plugin here # Required fuel version fuel_version: ['6.1'] # Specify license of your plugin diff --git a/examples/fuel_plugin_example_v3/metadata.yaml b/examples/fuel_plugin_example_v3/metadata.yaml index 7b329d4..e02dff5 100644 --- a/examples/fuel_plugin_example_v3/metadata.yaml +++ b/examples/fuel_plugin_example_v3/metadata.yaml @@ -5,7 +5,7 @@ title: Title for fuel_plugin_example_v3 plugin # Plugin version version: '3.0.0' # Description -description: Enable to use plugin X for Neutron +description: Please describe your plugin here # Required fuel version fuel_version: ['7.0'] # Specify license of your plugin diff --git a/examples/fuel_plugin_example_v4/.gitignore b/examples/fuel_plugin_example_v4/.gitignore new file mode 100644 index 0000000..daedd39 --- /dev/null +++ b/examples/fuel_plugin_example_v4/.gitignore @@ -0,0 +1,3 @@ +.tox +.build +*.pyc diff --git a/examples/fuel_plugin_example_v4/LICENSE b/examples/fuel_plugin_example_v4/LICENSE new file mode 100644 index 0000000..e06d208 --- /dev/null +++ b/examples/fuel_plugin_example_v4/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/examples/fuel_plugin_example_v4/README.md b/examples/fuel_plugin_example_v4/README.md new file mode 100644 index 0000000..3d0e9c9 --- /dev/null +++ b/examples/fuel_plugin_example_v4/README.md @@ -0,0 +1,4 @@ +fuel_plugin_example_v4 +====================== + +Plugin description diff --git a/examples/fuel_plugin_example_v4/deployment_scripts/deploy.pp b/examples/fuel_plugin_example_v4/deployment_scripts/deploy.pp new file mode 100644 index 0000000..73ca6f1 --- /dev/null +++ b/examples/fuel_plugin_example_v4/deployment_scripts/deploy.pp @@ -0,0 +1,12 @@ +notice('PLUGIN: fuel_plugin_example_v4 - deploy.pp') + +class fuel_plugin_example_v4 { + file { '/tmp/fuel_plugin_example_v4_puppet': + owner => 'root', + group => 'root', + mode => 0644, + content => "fuel_plugin_example_v4\n", + } +} + +class {'fuel_plugin_example_v4': } diff --git a/examples/fuel_plugin_example_v4/deployment_scripts/deploy.sh b/examples/fuel_plugin_example_v4/deployment_scripts/deploy.sh new file mode 100755 index 0000000..b2a92d9 --- /dev/null +++ b/examples/fuel_plugin_example_v4/deployment_scripts/deploy.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -eux + +# It's a script which deploys your plugin +echo fuel_plugin_example_v4 > /tmp/fuel_plugin_example_v4_sh + +OS_NAME='' +if grep -i CentOS /etc/issue.net >/dev/null; then + OS_NAME='centos'; +elif grep -i Ubuntu /etc/issue.net >/dev/null; then + OS_NAME='ubuntu'; +fi + +function install_package { + if [ $OS_NAME == 'ubuntu' ]; then + apt-get install -y fuel-simple-service + elif [ $OS_NAME == 'centos' ]; then + yum install -y fuel-simple-service + fi +} + +install_package +fuel-simple-service.py & \ No newline at end of file diff --git a/examples/fuel_plugin_example_v4/deployment_tasks.yaml b/examples/fuel_plugin_example_v4/deployment_tasks.yaml new file mode 100644 index 0000000..e8d52e3 --- /dev/null +++ b/examples/fuel_plugin_example_v4/deployment_tasks.yaml @@ -0,0 +1,43 @@ +- id: fuel_plugin_example_v4 + type: group + role: [fuel_plugin_example_v4] + tasks: + - hiera + - globals + required_for: [deploy_end] + requires: [deploy_start] + parameters: + strategy: + type: parallel + +- id: fuel_plugin_example_v4-controller-deployment + type: puppet + groups: [primary-controller, controller] + required_for: [connectivity_tests, deploy_end] + requires: [netconfig, deploy_start] + parameters: + puppet_manifest: "deploy.pp" + puppet_modules: "." + timeout: 3600 + +- id: fuel_plugin_example_v4-deployment + type: puppet + groups: [fuel_plugin_example_v4] + required_for: [deploy_end] + requires: [deploy_start] + parameters: + puppet_manifest: "deploy.pp" + puppet_modules: "." + timeout: 3600 + retries: 10 + +- id: fuel_plugin_example_v4-post-deployment-sh + type: shell + role: [fuel_plugin_example_v4] + required_for: [post_deployment_end] + requires: [post_deployment_start] + parameters: + cmd: bash deploy.sh + retries: 3 + interval: 20 + timeout: 180 diff --git a/examples/fuel_plugin_example_v4/environment_config.yaml b/examples/fuel_plugin_example_v4/environment_config.yaml new file mode 100644 index 0000000..63b1e69 --- /dev/null +++ b/examples/fuel_plugin_example_v4/environment_config.yaml @@ -0,0 +1,7 @@ +attributes: + fuel_plugin_example_v4_text: + value: 'Set default value' + label: 'Text field' + description: 'Description for text field' + weight: 25 + type: "text" diff --git a/examples/fuel_plugin_example_v4/fuel-simple-service.py b/examples/fuel_plugin_example_v4/fuel-simple-service.py new file mode 100755 index 0000000..247a2d6 --- /dev/null +++ b/examples/fuel_plugin_example_v4/fuel-simple-service.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- + +from wsgiref.simple_server import make_server + +def web_app(environ, start_response): + status = '200 OK' + headers = [('Content-type', 'text/plain')] + + start_response(status, headers) + + return open('/etc/astute.yaml').read() + + +def start_server(host, port): + httpd = make_server(host, port, web_app) + print 'Started server 8234' + httpd.serve_forever() + + +def main(): + start_server('', 8234) + + +if __name__ == '__main__': + main() diff --git a/examples/fuel_plugin_example_v4/metadata.yaml b/examples/fuel_plugin_example_v4/metadata.yaml new file mode 100644 index 0000000..6169f59 --- /dev/null +++ b/examples/fuel_plugin_example_v4/metadata.yaml @@ -0,0 +1,30 @@ +# Plugin name +name: fuel_plugin_example_v4 +# Human-readable name for your plugin +title: Title for fuel_plugin_example_v4 plugin +# Plugin version +version: '4.0.0' +# Description +description: Please describe your plugin here +# Required fuel version +fuel_version: ['8.0'] +# Specify license of your plugin +licenses: ['Apache License Version 2.0'] +# Specify author or company name +authors: ['Specify author or company name'] +# A link to the plugin's page +homepage: 'https://github.com/openstack/fuel-plugins' +# Specify a group which your plugin implements, possible options: +# network, storage, storage::cinder, storage::glance, hypervisor +groups: [] + +# The plugin is compatible with releases in the list +releases: + - os: ubuntu + version: 2015.1-8.0 + mode: ['ha'] + deployment_scripts_path: deployment_scripts/ + repository_path: repositories/ubuntu + +# Version of plugin package +package_version: '4.0.0' diff --git a/examples/fuel_plugin_example_v4/network_roles.yaml b/examples/fuel_plugin_example_v4/network_roles.yaml new file mode 100644 index 0000000..067957a --- /dev/null +++ b/examples/fuel_plugin_example_v4/network_roles.yaml @@ -0,0 +1,21 @@ +# Unique network role name +- id: "fuel_plugin_example_v4" + # Role mapping to network + default_mapping: "public" + properties: + # Should be true if network role requires subnet being set + subnet: true + # Should be true if network role requires gateway being set + gateway: false + # List of VIPs to be allocated + vip: + # Unique VIP name + - name: "vip_name" + # Optional linux namespace for VIP + namespace: "haproxy" + # Optional alias so VIP can be queried via API + alias: "vip_name" + # Optional node role list to map VIP to (defaults to + # primary-controller and controller) + node_roles: + - "fuel_plugin_example_v4" diff --git a/examples/fuel_plugin_example_v4/node_roles.yaml b/examples/fuel_plugin_example_v4/node_roles.yaml new file mode 100644 index 0000000..607fccd --- /dev/null +++ b/examples/fuel_plugin_example_v4/node_roles.yaml @@ -0,0 +1,6 @@ +fuel_plugin_example_v4: + name: "Set here the name for the role. This name will be displayed in the Fuel web UI." + description: "Write description for your role" + has_primary: false # whether has primary role or not + public_ip_required: false # whether requires public net or not + weight: 100 # weight that will be used for ordering on fuel ui diff --git a/examples/fuel_plugin_example_v4/pre_build_hook b/examples/fuel_plugin_example_v4/pre_build_hook new file mode 100755 index 0000000..db14c50 --- /dev/null +++ b/examples/fuel_plugin_example_v4/pre_build_hook @@ -0,0 +1,17 @@ +#!/bin/bash +set -eux + +command -v fpm >/dev/null 2>&1 || { + echo >&2 "Install 'fpm' to build this plugin. Aborting."; exit 1; +} + +ROOT=$(dirname `readlink -f $0`) + +UBUNTU_REPO_PATH=$ROOT/repositories/ubuntu +CENTOS_REPO_PATH=$ROOT/repositories/centos + +rm -f $UBUNTU_REPO_PATH/*.deb +rm -f $CENTOS_REPO_PATH/*.rpm + +fpm -t deb -p $UBUNTU_REPO_PATH -n fuel-simple-service -v 4.0.0 -s dir $ROOT/fuel-simple-service.py=/usr/bin/fuel-simple-service.py +fpm -t rpm -p $CENTOS_REPO_PATH -n fuel-simple-service -v 4.0.0 -s dir $ROOT/fuel-simple-service.py=/usr/bin/fuel-simple-service.py diff --git a/examples/fuel_plugin_example_v4/repositories/centos/.gitkeep b/examples/fuel_plugin_example_v4/repositories/centos/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/examples/fuel_plugin_example_v4/repositories/ubuntu/.gitkeep b/examples/fuel_plugin_example_v4/repositories/ubuntu/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/examples/fuel_plugin_example_v4/tasks.yaml b/examples/fuel_plugin_example_v4/tasks.yaml new file mode 100644 index 0000000..e8b40e3 --- /dev/null +++ b/examples/fuel_plugin_example_v4/tasks.yaml @@ -0,0 +1,43 @@ +# This tasks will be applied on controller nodes +- role: ['primary-controller', 'controller'] + stage: post_deployment + type: shell + parameters: + cmd: bash deploy.sh + timeout: 42 + +- role: '*' + stage: pre_deployment/100 + type: shell + parameters: + cmd: echo all > /tmp/plugin+100.all + timeout: 42 + +- role: '*' + stage: pre_deployment/+101.0 + type: shell + parameters: + cmd: echo all > /tmp/plugin+100.0.all + timeout: 42 + +- role: '*' + stage: pre_deployment/-100 + type: shell + parameters: + cmd: echo all > /tmp/plugin-100.all + timeout: 42 + +- role: [compute] + stage: pre_deployment/-101 + type: puppet + parameters: + puppet_manifest: "deploy.pp" + puppet_modules: "." + timeout: 3600 + retries: 2 + +- role: '*' + stage: pre_deployment + type: reboot + parameters: + timeout: 600 diff --git a/examples/fuel_plugin_example_v4/volumes.yaml b/examples/fuel_plugin_example_v4/volumes.yaml new file mode 100644 index 0000000..217b0dc --- /dev/null +++ b/examples/fuel_plugin_example_v4/volumes.yaml @@ -0,0 +1,6 @@ +# Set here new volumes for your role +volumes: [] +volumes_roles_mapping: + fuel_plugin_example_v4: + # Default role mapping + - {allocate_size: "min", id: "os"} diff --git a/fuel_plugin_builder/actions/__init__.py b/fuel_plugin_builder/actions/__init__.py index 4b38144..d1d5949 100644 --- a/fuel_plugin_builder/actions/__init__.py +++ b/fuel_plugin_builder/actions/__init__.py @@ -17,4 +17,6 @@ from fuel_plugin_builder.actions.base import BaseAction from fuel_plugin_builder.actions.create import CreatePlugin from fuel_plugin_builder.actions.build import BuildPluginV1 from fuel_plugin_builder.actions.build import BuildPluginV2 +from fuel_plugin_builder.actions.build import BuildPluginV3 +from fuel_plugin_builder.actions.build import BuildPluginV4 from fuel_plugin_builder.actions.build import make_builder diff --git a/fuel_plugin_builder/actions/build.py b/fuel_plugin_builder/actions/build.py index 61bb496..99ccc19 100644 --- a/fuel_plugin_builder/actions/build.py +++ b/fuel_plugin_builder/actions/build.py @@ -263,8 +263,12 @@ class BuildPluginV3(BuildPluginV2): return data +class BuildPluginV4(BuildPluginV3): + pass + + def make_builder(plugin_path): - """Creates build object + """Creates build object. :param str plugin_path: path to the plugin :returns: specific version of builder object diff --git a/fuel_plugin_builder/templates/v1/metadata.yaml.mako b/fuel_plugin_builder/templates/v1/metadata.yaml.mako index cf231ba..df9b788 100644 --- a/fuel_plugin_builder/templates/v1/metadata.yaml.mako +++ b/fuel_plugin_builder/templates/v1/metadata.yaml.mako @@ -5,7 +5,7 @@ title: Title for ${plugin_name} plugin # Plugin version version: '1.0.0' # Description -description: Enable to use plugin X for Neutron +description: Please describe your plugin here # Required fuel version fuel_version: ['6.0'] diff --git a/fuel_plugin_builder/templates/v2/plugin_data/metadata.yaml.mako b/fuel_plugin_builder/templates/v2/plugin_data/metadata.yaml.mako index 204ce9a..29d889f 100644 --- a/fuel_plugin_builder/templates/v2/plugin_data/metadata.yaml.mako +++ b/fuel_plugin_builder/templates/v2/plugin_data/metadata.yaml.mako @@ -5,7 +5,7 @@ title: Title for ${plugin_name} plugin # Plugin version version: '1.0.0' # Description -description: Enable to use plugin X for Neutron +description: Please describe your plugin here # Required fuel version fuel_version: ['6.1'] # Specify license of your plugin diff --git a/fuel_plugin_builder/templates/v3/plugin_data/metadata.yaml.mako b/fuel_plugin_builder/templates/v3/plugin_data/metadata.yaml.mako index 9c494d0..ee0b095 100644 --- a/fuel_plugin_builder/templates/v3/plugin_data/metadata.yaml.mako +++ b/fuel_plugin_builder/templates/v3/plugin_data/metadata.yaml.mako @@ -5,7 +5,7 @@ title: Title for ${plugin_name} plugin # Plugin version version: '1.0.0' # Description -description: Enable to use plugin X for Neutron +description: Please describe your plugin here # Required fuel version fuel_version: ['7.0', '8.0'] # Specify license of your plugin diff --git a/fuel_plugin_builder/templates/v4/plugin_data/metadata.yaml.mako b/fuel_plugin_builder/templates/v4/plugin_data/metadata.yaml.mako new file mode 100644 index 0000000..0ca855d --- /dev/null +++ b/fuel_plugin_builder/templates/v4/plugin_data/metadata.yaml.mako @@ -0,0 +1,30 @@ +# Plugin name +name: ${plugin_name} +# Human-readable name for your plugin +title: Title for ${plugin_name} plugin +# Plugin version +version: '1.0.0' +# Description +description: Please describe your plugin here +# Required fuel version +fuel_version: ['8.0'] +# Specify license of your plugin +licenses: ['Apache License Version 2.0'] +# Specify author or company name +authors: ['Specify author or company name'] +# A link to the plugin's page +homepage: 'https://github.com/openstack/fuel-plugins' +# Specify a group which your plugin implements, possible options: +# network, storage, storage::cinder, storage::glance, hypervisor +groups: [] + +# The plugin is compatible with releases in the list +releases: + - os: ubuntu + version: 2015.1-8.0 + mode: ['ha'] + deployment_scripts_path: deployment_scripts/ + repository_path: repositories/ubuntu + +# Version of plugin package +package_version: '4.0.0' diff --git a/fuel_plugin_builder/tests/base.py b/fuel_plugin_builder/tests/base.py index 3580f29..815650f 100644 --- a/fuel_plugin_builder/tests/base.py +++ b/fuel_plugin_builder/tests/base.py @@ -220,3 +220,19 @@ class BaseValidator(BaseTestCase): "of type 'string', value path " "'attributes -> key1 -> restrictions -> 1 -> condition"): self.validator.check_env_config_attrs() + + def check_raised_exception(self, utils_mock, mock_data, + err_msg, executed_method, + err_type=errors.ValidationError): + """Check if the given error with given type was raised. + + :param obj utils_mock: fuel_plugin_builder.utils mock + :param List[dict] mock_data: mock data + :param str err_msg: what error message is expected + :param function executed_method: what method should be executed + :param Exception err_type: what error type is expected + """ + utils_mock.parse_yaml.return_value = mock_data + + with self.assertRaisesRegexp(err_type, err_msg): + executed_method() diff --git a/fuel_plugin_builder/tests/test_validator_v3.py b/fuel_plugin_builder/tests/test_validator_v3.py index d9e28c8..93811cd 100644 --- a/fuel_plugin_builder/tests/test_validator_v3.py +++ b/fuel_plugin_builder/tests/test_validator_v3.py @@ -280,7 +280,7 @@ class TestValidatorV3(BaseValidator): ' Please remove {0} version from metadata.yaml file or' \ ' downgrade package_version.'.format(fuel_version[0]) - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_compatibility) @@ -303,7 +303,7 @@ class TestValidatorV3(BaseValidator): 'type': task_type}] err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml', " \ "'role' is a required property, value path '0'" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -319,7 +319,7 @@ class TestValidatorV3(BaseValidator): 'role': '*'}] err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml', " \ "'parameters' is a required property, value path '0'" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -334,7 +334,7 @@ class TestValidatorV3(BaseValidator): err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml', " \ "'files' is a required property, value path '0 " \ "-> parameters'" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -348,7 +348,7 @@ class TestValidatorV3(BaseValidator): 'parameters': {'files': []}}] err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml', " \ "\[\] is too short, value path '0 -> parameters -> files'" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -375,7 +375,7 @@ class TestValidatorV3(BaseValidator): err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml', " \ "'{0}' is a required property, value path '0 " \ "-> parameters -> files -> 0'".format(key) - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -400,7 +400,7 @@ class TestValidatorV3(BaseValidator): err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml', " \ "'{0}' is a required property, value path '0 " \ "-> parameters'".format(key) - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -425,7 +425,7 @@ class TestValidatorV3(BaseValidator): err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml', " \ "'{0}' is a required property, value path '0 " \ "-> parameters'".format(key) - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -448,7 +448,7 @@ class TestValidatorV3(BaseValidator): 'role': ['plugin_n@me']}] err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml'," \ " 'plugin_n@me' does not match" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks) @@ -501,7 +501,7 @@ class TestValidatorV3(BaseValidator): 'role': ['plugin_name']}] err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml'," \ " 'plugin_n@me' does not match" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks_schema) @@ -524,7 +524,7 @@ class TestValidatorV3(BaseValidator): 'requires': ['dependency_1', 'dependency_#']}] err_msg = "File '/tmp/plugin_path/deployment_tasks.yaml'," \ " 'dependency_#' does not match" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_deployment_tasks_schema) @@ -536,7 +536,7 @@ class TestValidatorV3(BaseValidator): 'description': 'test plugin'}} err_msg = "File '/tmp/plugin_path/node_roles.yaml', Additional" \ " properties are not allowed" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_node_roles_schema) @@ -547,7 +547,7 @@ class TestValidatorV3(BaseValidator): 'description': 'test plugin'}} err_msg = "File '/tmp/plugin_path/node_roles.yaml', 'name' is" \ " a required property, value path 'plugin_name'" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_node_roles_schema) @@ -568,7 +568,7 @@ class TestValidatorV3(BaseValidator): 'volumes': []} err_msg = "File '/tmp/plugin_path/volumes.yaml', Additional" \ " properties are not allowed" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_volumes_schema) @@ -599,7 +599,7 @@ class TestValidatorV3(BaseValidator): "namespace": "haproxy"}]}}] err_msg = "File '/tmp/plugin_path/network_roles.yaml'," \ " 'vip@name' does not match" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_network_roles_schema) @@ -616,14 +616,6 @@ class TestValidatorV3(BaseValidator): "namespace": "hap roxy"}]}}] err_msg = "File '/tmp/plugin_path/network_roles.yaml'," \ " 'hap roxy' does not match" - self._check_raised_exception( + self.check_raised_exception( utils_mock, mock_data, err_msg, self.validator.check_network_roles_schema) - - def _check_raised_exception(self, mock_obj, mock_data, - err_msg, executed_method, - err_type=errors.ValidationError): - mock_obj.parse_yaml.return_value = mock_data - - with self.assertRaisesRegexp(err_type, err_msg): - executed_method() diff --git a/fuel_plugin_builder/tests/test_validator_v4.py b/fuel_plugin_builder/tests/test_validator_v4.py new file mode 100644 index 0000000..5c044ac --- /dev/null +++ b/fuel_plugin_builder/tests/test_validator_v4.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- + +# Copyright 2015 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. + +import mock + +from fuel_plugin_builder.tests.base import BaseValidator +from fuel_plugin_builder.validators.schemas import SchemaV4 +from fuel_plugin_builder.validators.validator_v4 import ValidatorV4 + + +class TestValidatorV4(BaseValidator): + + __test__ = True + validator_class = ValidatorV4 + schema_class = SchemaV4 + + def test_validate(self): + mocked_methods = ['check_deployment_tasks'] + super(TestValidatorV4, self).test_validate( + additional_mocked_methods=mocked_methods) + + self.validator.check_deployment_tasks.assert_called_once_with() + + # copy-pasted from tests v3 to + # - override invalid base validator + # - make additional validator class integrity smoke-test + + def test_check_schemas(self): + mocked_methods = [ + 'check_env_config_attrs', + 'validate_file_by_schema', + 'check_deployment_tasks_schema', + 'check_network_roles_schema', + 'check_node_roles_schema', + 'check_volumes_schema' + ] + self.mock_methods(self.validator, mocked_methods) + self.validator.check_schemas() + + self.assertEqual( + [mock.call(self.schema_class().metadata_schema, + self.validator.meta_path), + mock.call(self.schema_class().tasks_schema, + self.validator.tasks_path, check_file_exists=False)], + self.validator.validate_file_by_schema.call_args_list) + + self.validator.check_env_config_attrs.assert_called_once_with() + self.validator.check_deployment_tasks_schema.assert_called_once_with() + self.validator.check_network_roles_schema.assert_called_once_with() + self.validator.check_node_roles_schema.assert_called_once_with() + self.validator.check_volumes_schema.assert_called_once_with() + + @mock.patch('fuel_plugin_builder.validators.base.utils') + def test_check_compatibility_failed(self, utils_mock): + fuel_version_checks = ( + (['6.0', '6.1', '7.0', '8.0']), + (['6.1', '7.0', '8.0']), + (['6.0', '6.1', '7.0']), + (['6.1', '7.0']), + ) + + for fuel_version in fuel_version_checks: + mock_data = { + 'fuel_version': fuel_version, + 'package_version': '4.0.0'} + err_msg = 'Current plugin format 4.0.0 is not compatible with ' \ + '{0} Fuel release. Fuel version must be 8.0 or higher.' \ + ' Please remove {0} version from metadata.yaml file or' \ + ' downgrade package_version.'.format(fuel_version[0]) + + self.check_raised_exception( + utils_mock, mock_data, + err_msg, self.validator.check_compatibility) + + @mock.patch('fuel_plugin_builder.validators.base.utils') + def test_check_compatibility_passed(self, utils_mock): + utils_mock.parse_yaml.return_value = { + 'fuel_version': ['8.0'], + 'package_version': '4.0.0'} + self.validator.check_compatibility() diff --git a/fuel_plugin_builder/tests/test_version_mapping.py b/fuel_plugin_builder/tests/test_version_mapping.py index 19a744c..561dc90 100644 --- a/fuel_plugin_builder/tests/test_version_mapping.py +++ b/fuel_plugin_builder/tests/test_version_mapping.py @@ -19,6 +19,7 @@ from fuel_plugin_builder.tests.base import BaseTestCase from fuel_plugin_builder.validators import ValidatorV1 from fuel_plugin_builder.validators import ValidatorV2 from fuel_plugin_builder.validators import ValidatorV3 +from fuel_plugin_builder.validators import ValidatorV4 from fuel_plugin_builder.version_mapping import get_plugin_for_version @@ -48,6 +49,17 @@ class TestVersionMapping(BaseTestCase): ['templates/base', 'templates/v3/plugin_data/']) self.assertEqual(result['validator'], ValidatorV3) + def test_get_plugin_for_version_4(self): + result = get_plugin_for_version('4.0.0') + self.assertEqual(result['version'], '4.0.0') + self.assertEqual( + result['templates'], + [ + 'templates/base', + 'templates/v3/plugin_data/', + 'templates/v4/plugin_data/']) + self.assertEqual(result['validator'], ValidatorV4) + def test_get_plugin_for_version_raises_error(self): with self.assertRaisesRegexp(errors.WrongPackageVersionError, 'Wrong package version "2999"'): diff --git a/fuel_plugin_builder/validators/__init__.py b/fuel_plugin_builder/validators/__init__.py index 6742cf3..07bd8f6 100644 --- a/fuel_plugin_builder/validators/__init__.py +++ b/fuel_plugin_builder/validators/__init__.py @@ -18,4 +18,5 @@ from fuel_plugin_builder.validators.manager import ValidatorManager from fuel_plugin_builder.validators.validator_v1 import ValidatorV1 from fuel_plugin_builder.validators.validator_v2 import ValidatorV2 from fuel_plugin_builder.validators.validator_v3 import ValidatorV3 +from fuel_plugin_builder.validators.validator_v4 import ValidatorV4 from fuel_plugin_builder.validators.base import BaseValidator diff --git a/fuel_plugin_builder/validators/schemas/__init__.py b/fuel_plugin_builder/validators/schemas/__init__.py index bf16739..2ff0393 100644 --- a/fuel_plugin_builder/validators/schemas/__init__.py +++ b/fuel_plugin_builder/validators/schemas/__init__.py @@ -19,3 +19,4 @@ from fuel_plugin_builder.validators.schemas.base import BaseSchema from fuel_plugin_builder.validators.schemas.v1 import SchemaV1 from fuel_plugin_builder.validators.schemas.v2 import SchemaV2 from fuel_plugin_builder.validators.schemas.v3 import SchemaV3 +from fuel_plugin_builder.validators.schemas.v4 import SchemaV4 diff --git a/fuel_plugin_builder/validators/schemas/v4.py b/fuel_plugin_builder/validators/schemas/v4.py new file mode 100644 index 0000000..630a159 --- /dev/null +++ b/fuel_plugin_builder/validators/schemas/v4.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +# Copyright 2015 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. + +from fuel_plugin_builder.validators.schemas import SchemaV3 + + +class SchemaV4(SchemaV3): + + @property + def package_version(self): + return {'enum': ['4.0.0']} diff --git a/fuel_plugin_builder/validators/validator_v4.py b/fuel_plugin_builder/validators/validator_v4.py new file mode 100644 index 0000000..988ca85 --- /dev/null +++ b/fuel_plugin_builder/validators/validator_v4.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +# Copyright 2015 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. + +from fuel_plugin_builder.validators.schemas import SchemaV4 +from fuel_plugin_builder.validators import ValidatorV3 + + +class ValidatorV4(ValidatorV3): + + schema = SchemaV4() + + @property + def basic_version(self): + return '8.0' diff --git a/fuel_plugin_builder/version_mapping.py b/fuel_plugin_builder/version_mapping.py index 468ab63..175539b 100644 --- a/fuel_plugin_builder/version_mapping.py +++ b/fuel_plugin_builder/version_mapping.py @@ -20,7 +20,7 @@ from fuel_plugin_builder import errors from fuel_plugin_builder import utils -latest_version = '3.0.0' +latest_version = '4.0.0' def get_mapping(): @@ -40,7 +40,14 @@ def get_mapping(): {'version': '3.0.0', 'templates': ['templates/base', 'templates/v3/plugin_data/'], 'validator': validators.ValidatorV3, - 'builder': build.BuildPluginV3}] + 'builder': build.BuildPluginV3}, + {'version': '4.0.0', + 'templates': [ + 'templates/base', + 'templates/v3/plugin_data/', + 'templates/v4/plugin_data/'], + 'validator': validators.ValidatorV4, + 'builder': build.BuildPluginV4}] def get_plugin_for_version(version): diff --git a/setup.py b/setup.py index c72c76f..edeb9e0 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ def find_requires(): setup( name='fuel-plugin-builder', - version='3.0.0', + version='4.0.0.dev', description='Helps to create and build fuel plugins', long_description="""Helps to create and build fuel plugins""", classifiers=[