ARIA-99 Straightforward end-to-end tests for parser and built-in workflow
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/d35d09a3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/d35d09a3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/d35d09a3 Branch: refs/heads/ARIA-79-concurrent-storage-modifications Commit: d35d09a35422add7c3ee34053add05f41b8de1ba Parents: e282f23 Author: Tal Liron <tal.li...@gmail.com> Authored: Fri Feb 3 13:32:46 2017 -0600 Committer: Tal Liron <tal.li...@gmail.com> Committed: Wed Feb 8 11:32:52 2017 -0600 ---------------------------------------------------------------------- aria/cli/cli.py | 4 +- aria/parser/loading/request.py | 9 +- aria/parser/loading/uri.py | 5 +- aria/storage/filesystem_rapi.py | 2 +- aria/utils/uris.py | 22 +- tests/conftest.py | 23 ++ tests/end2end/test_orchestrator.py | 60 ++++ tests/end2end/test_parser.py | 40 +++ tests/orchestrator/conftest.py | 23 -- tests/parser/__init__.py | 14 + tests/parser/service_templates.py | 30 ++ tests/parser/utils.py | 78 +++++ .../service_templates/node-cellar/inputs.yaml | 3 + .../node-cellar/node-cellar.yaml | 299 +++++++++++++++++++ .../node-cellar/types/aria.yaml | 93 ++++++ .../node-cellar/types/mongodb.yaml | 73 +++++ .../node-cellar/types/nginx.yaml | 27 ++ .../node-cellar/types/nodejs.yaml | 69 +++++ .../node-cellar/types/openstack.yaml | 201 +++++++++++++ .../service_templates/node-cellar/types/os.yaml | 75 +++++ .../service_templates/node-cellar/workflows.py | 19 ++ 21 files changed, 1137 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/aria/cli/cli.py ---------------------------------------------------------------------- diff --git a/aria/cli/cli.py b/aria/cli/cli.py index 20ace2c..8d014b3 100644 --- a/aria/cli/cli.py +++ b/aria/cli/cli.py @@ -17,7 +17,9 @@ CLI Entry point """ +import os import logging +import tempfile from .. import install_aria_extensions from ..logger import ( @@ -100,7 +102,7 @@ def main(): create_logger( handlers=[ create_console_log_handler(), - create_file_log_handler(file_path='/tmp/aria_cli.log'), + create_file_log_handler(file_path=os.path.join(tempfile.gettempdir(), 'aria_cli.log')), ], level=logging.INFO) with AriaCli() as aria: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/aria/parser/loading/request.py ---------------------------------------------------------------------- diff --git a/aria/parser/loading/request.py b/aria/parser/loading/request.py index 6ebabfc..a809347 100644 --- a/aria/parser/loading/request.py +++ b/aria/parser/loading/request.py @@ -13,8 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os +import tempfile + from requests import Session -from requests.exceptions import ConnectionError +from requests.exceptions import (ConnectionError, InvalidSchema) from cachecontrol import CacheControl from cachecontrol.caches import FileCache @@ -22,7 +25,7 @@ from .exceptions import LoaderException, DocumentNotFoundException from .loader import Loader SESSION = None -SESSION_CACHE_PATH = '/tmp' +SESSION_CACHE_PATH = os.path.join(tempfile.gettempdir(), 'aria_requests') class RequestLoader(Loader): @@ -53,6 +56,8 @@ class RequestLoader(Loader): try: self._response = SESSION.get(self.uri, headers=self.headers) + except InvalidSchema as e: + raise DocumentNotFoundException('document not found: "%s"' % self.uri, cause=e) except ConnectionError as e: raise LoaderException('request connection error: "%s"' % self.uri, cause=e) except Exception as e: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/aria/parser/loading/uri.py ---------------------------------------------------------------------- diff --git a/aria/parser/loading/uri.py b/aria/parser/loading/uri.py index f0cde3a..1b23bf6 100644 --- a/aria/parser/loading/uri.py +++ b/aria/parser/loading/uri.py @@ -66,8 +66,9 @@ class UriTextLoader(Loader): except DocumentNotFoundException: # Try prefixes in order for prefix in self._prefixes: - if as_file(prefix) is not None: - uri = os.path.join(prefix, self.location.uri) + prefix_as_file = as_file(prefix) + if prefix_as_file is not None: + uri = os.path.join(prefix_as_file, self.location.uri) else: uri = urljoin(prefix, self.location.uri) try: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/aria/storage/filesystem_rapi.py ---------------------------------------------------------------------- diff --git a/aria/storage/filesystem_rapi.py b/aria/storage/filesystem_rapi.py index eb30e0b..6693dbd 100644 --- a/aria/storage/filesystem_rapi.py +++ b/aria/storage/filesystem_rapi.py @@ -17,10 +17,10 @@ SQLalchemy based RAPI """ import os import shutil +from multiprocessing import RLock from contextlib import contextmanager from functools import partial from distutils import dir_util # https://github.com/PyCQA/pylint/issues/73; pylint: disable=no-name-in-module -from multiprocessing import RLock from aria.storage import ( api, http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/aria/utils/uris.py ---------------------------------------------------------------------- diff --git a/aria/utils/uris.py b/aria/utils/uris.py index 1686517..5f7bcf5 100644 --- a/aria/utils/uris.py +++ b/aria/utils/uris.py @@ -16,13 +16,29 @@ import os import urlparse + +_IS_WINDOWS = (os.name == 'nt') + + def as_file(uri): """ - If the URI is a file (either the :code:`file` scheme or no scheme), then returns the absolute + If the URI is a file (either the :code:`file` scheme or no scheme), then returns the normalized path. Otherwise, returns None. """ + if _IS_WINDOWS: + # We need this extra check in Windows before urlparse because paths might have a drive + # prefix, e.g. "C:" which will be considered a scheme for urlparse below + path = uri.replace('/', '\\') + if os.path.exists(path): + return os.path.normpath(path) + url = urlparse.urlparse(uri) - if (not url.scheme) or (url.scheme == 'file'): - return os.path.abspath(url.path) + scheme = url.scheme + if (not scheme) or (scheme == 'file'): + path = url.path + if _IS_WINDOWS: + path = path.replace('/', '\\') + return os.path.normpath(path) + return None http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/conftest.py ---------------------------------------------------------------------- diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..4b24f18 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 pytest + +import aria + + +@pytest.fixture(scope='session', autouse=True) +def install_aria_extensions(): + aria.install_aria_extensions() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/end2end/test_orchestrator.py ---------------------------------------------------------------------- diff --git a/tests/end2end/test_orchestrator.py b/tests/end2end/test_orchestrator.py new file mode 100644 index 0000000..f930577 --- /dev/null +++ b/tests/end2end/test_orchestrator.py @@ -0,0 +1,60 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 sys + +from aria.orchestrator.runner import Runner +from aria.orchestrator.workflows.builtin import BUILTIN_WORKFLOWS +from aria.parser.modeling.storage import initialize_storage +from aria.utils.imports import import_fullname +from aria.utils.collections import OrderedDict + +from tests.parser.service_templates import consume_node_cellar + + +WORKFLOW_POLICY_INTERNAL_PROPERTIES = ('function', 'implementation', 'dependencies') + + +def test_install(): + _workflow('install') + + +def test_custom(): + _workflow('maintenance_on') + + +def _workflow(workflow_name): + context, _ = consume_node_cellar() + + # TODO: this logic will eventually stabilize and be part of the ARIA API, + # likely somewhere in aria.orchestrator.workflows + if workflow_name in BUILTIN_WORKFLOWS: + workflow_fn = import_fullname('aria.orchestrator.workflows.builtin.' + workflow_name) + inputs = {} + else: + policy = context.modeling.instance.policies[workflow_name] + sys.path.append(policy.properties['implementation'].value) + + workflow_fn = import_fullname(policy.properties['function'].value) + inputs = OrderedDict([ + (k, v.value) for k, v in policy.properties.iteritems() + if k not in WORKFLOW_POLICY_INTERNAL_PROPERTIES + ]) + + def _initialize_storage(model_storage): + initialize_storage(context, model_storage, 1) + + runner = Runner(workflow_name, workflow_fn, inputs, _initialize_storage, 1) + runner.run() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/end2end/test_parser.py ---------------------------------------------------------------------- diff --git a/tests/end2end/test_parser.py b/tests/end2end/test_parser.py new file mode 100644 index 0000000..7c243ab --- /dev/null +++ b/tests/end2end/test_parser.py @@ -0,0 +1,40 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 tests.parser.service_templates import consume_node_cellar + + +def test_validation(): + consume_node_cellar('validate') + + +def test_validation_no_cache(): + consume_node_cellar('validate', False) + + +def test_presentation(): + consume_node_cellar('presentation') + + +def test_model(): + consume_node_cellar('model') + + +def test_types(): + consume_node_cellar('types') + + +def test_instance(): + consume_node_cellar('instance') http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/orchestrator/conftest.py ---------------------------------------------------------------------- diff --git a/tests/orchestrator/conftest.py b/tests/orchestrator/conftest.py deleted file mode 100644 index 4b24f18..0000000 --- a/tests/orchestrator/conftest.py +++ /dev/null @@ -1,23 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You 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 pytest - -import aria - - -@pytest.fixture(scope='session', autouse=True) -def install_aria_extensions(): - aria.install_aria_extensions() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/parser/__init__.py ---------------------------------------------------------------------- diff --git a/tests/parser/__init__.py b/tests/parser/__init__.py new file mode 100644 index 0000000..ae1e83e --- /dev/null +++ b/tests/parser/__init__.py @@ -0,0 +1,14 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/parser/service_templates.py ---------------------------------------------------------------------- diff --git a/tests/parser/service_templates.py b/tests/parser/service_templates.py new file mode 100644 index 0000000..8c361e6 --- /dev/null +++ b/tests/parser/service_templates.py @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 aria.utils.caching import cachedmethod + +from .utils import (get_uri, create_context, create_consumer) + + +def consume_node_cellar(consumer_class_name='instance', cache=True): + cachedmethod.ENABLED = cache + uri = get_uri('node-cellar', 'node-cellar.yaml') + context = create_context(uri) + context.args.append('--inputs=' + get_uri('node-cellar', 'inputs.yaml')) + consumer, dumper = create_consumer(context, consumer_class_name) + consumer.consume() + context.validation.dump_issues() + assert not context.validation.has_issues + return context, dumper http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/parser/utils.py ---------------------------------------------------------------------- diff --git a/tests/parser/utils.py b/tests/parser/utils.py new file mode 100644 index 0000000..e55e6e5 --- /dev/null +++ b/tests/parser/utils.py @@ -0,0 +1,78 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 os + +from aria.parser.loading import UriLocation +from aria.parser.consumption import ( + ConsumptionContext, + ConsumerChain, + Read, + Validate, + Model, + Types, + Inputs, + Instance +) +from aria.utils.imports import import_fullname + +from tests.resources import DIR + + +SERVICE_TEMPLATES_DIR = os.path.join(DIR, 'service_templates') + + +def get_uri(*args): + return os.path.join(SERVICE_TEMPLATES_DIR, *args) + + +def create_context(uri, + loader_source='aria.parser.loading.DefaultLoaderSource', + reader_source='aria.parser.reading.DefaultReaderSource', + presenter_source='aria.parser.presentation.DefaultPresenterSource', + presenter=None, + debug=False): + context = ConsumptionContext() + context.loading.loader_source = import_fullname(loader_source)() + context.reading.reader_source = import_fullname(reader_source)() + context.presentation.location = UriLocation(uri) if isinstance(uri, basestring) else uri + context.presentation.presenter_source = import_fullname(presenter_source)() + context.presentation.presenter_class = import_fullname(presenter) + context.presentation.print_exceptions = debug + return context + + +def create_consumer(context, consumer_class_name): + consumer = ConsumerChain(context, (Read, Validate)) + dumper = None + if consumer_class_name == 'validate': + dumper = None + elif consumer_class_name == 'presentation': + dumper = consumer.consumers[0] + elif consumer_class_name == 'model': + consumer.append(Model) + elif consumer_class_name == 'types': + consumer.append(Model, Types) + elif consumer_class_name == 'instance': + consumer.append(Model, Inputs, Instance) + else: + consumer.append(Model, Inputs, Instance) + consumer.append(import_fullname(consumer_class_name)) + + if dumper is None: + # Default to last consumer + dumper = consumer.consumers[-1] + + return consumer, dumper http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/inputs.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/inputs.yaml b/tests/resources/service_templates/node-cellar/inputs.yaml new file mode 100644 index 0000000..37ab9ea --- /dev/null +++ b/tests/resources/service_templates/node-cellar/inputs.yaml @@ -0,0 +1,3 @@ +openstack_credential: + user: username + token: password http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/node-cellar.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/node-cellar.yaml b/tests/resources/service_templates/node-cellar/node-cellar.yaml new file mode 100644 index 0000000..3e579bd --- /dev/null +++ b/tests/resources/service_templates/node-cellar/node-cellar.yaml @@ -0,0 +1,299 @@ +# +# Copyright (c) 2016 GigaSpaces Technologies Ltd. All rights reserved. +# +# 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. +# + +# NFV is not used here, but we are using it just to validate the imports +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0 +#tosca_definitions_version: tosca_simple_yaml_1_0 + +description: >- + Node Cellar TOSCA blueprint. + Here is some Unicode: ä¸å. + +metadata: + template_name: node-cellar + template_author: ARIA + template_version: '1.0.0' + aria_version: '0.0' + +imports: + - types/openstack.yaml + - types/nodejs.yaml + - types/mongodb.yaml + - types/nginx.yaml + - types/aria.yaml + +dsl_definitions: + + default_openstack_credential: &DEFAULT_OPENSTACK_CREDENTIAL + user: openstackadmin + token: { concat: [ openstack, 123 ] } + +repositories: + + node_cellar: + description: >- + The repository for the Node Cellar application and its dependencies. + url: https://github.com/ccoenraets/nodecellar/archive/ + credential: + user: guest + token: '' + +interface_types: + + Maintenance: + derived_from: tosca.interfaces.Root + enable: {} + disable: {} + +node_types: + + NodeMongoApplication: + derived_from: nodejs.Application + interfaces: + Maintenance: + type: Maintenance + requirements: + - database: + capability: tosca.capabilities.Endpoint.Database + node: mongodb.Database + +topology_template: + + inputs: + openstack_credential: + type: openstack.Credential + value: *DEFAULT_OPENSTACK_CREDENTIAL + + node_templates: + + # Application + + node_cellar: + description: >- + Node Cellar Node.js web application. + type: NodeMongoApplication + artifacts: + node_cellar: + description: >- + The Node Cellar application package. + type: os.Archive + file: master.zip + repository: node_cellar + deploy_path: /opt/nodejs/applications/node-cellar + properties: + unpack_credential: + user: gigaspaces + token: { get_property: [ SELF, app_endpoint, protocol ] } + #token: { get_property: [ HOST, flavor_name ] } + interfaces: + Maintenance: + enable: juju > charm.maintenance_on + disable: juju > charm.maintenance_off + requirements: + - database: node_cellar_database + capabilities: + app_endpoint: + properties: + protocol: udp + url_path: /nodecellar + + node_cellar_database: + description: >- + Node Cellar MongoDB database. + type: mongodb.Database + properties: + name: node_cellar + artifacts: + initial: + description: >- + The Node Cellar initial database. + type: mongodb.DatabaseDump + file: node-cellar.json + repository: node_cellar + + # Server software + + nodejs: + description: >- + Node.js instance. + type: nodejs.Server + requirements: + - host: application_host + node_filter: # cannot be validated + properties: + #- flavor_name: { valid_values: [ {concat:[m1,.,small]} ] } # won't work because not validated :/ + - flavor_name: { valid_values: [ m1.small ] } + capabilities: + - scalable: + properties: + - max_instances: { greater_or_equal: 8 } + + mongodb: + description: >- + MongoDB instance. + type: mongodb.Server + requirements: + - host: + node: openstack.Instance + node_filter: + properties: + - flavor_name: { valid_values: [ m1.medium, { concat: [ { concat: [ m1, . ] }, large ] } ] } + #- flavor_name: { valid_values: [ m1.medium, m1.large ] } + capabilities: + - scalable: + properties: + - max_instances: { greater_or_equal: 8 } + + loadbalancer: + type: nginx.LoadBalancer + properties: + algorithm: round-robin + requirements: + - host: loadbalancer_host + + # Hosts + + loadbalancer_host: + description: >- + Host for the loadbalancer. + type: openstack.Instance + properties: + flavor_name: m1.small + os_users: # map of os.UserInfo + root: + password: admin123 + interfaces: + Standard: + inputs: + openstack_credential: { get_input: openstack_credential } + configure: juju > charm.loadbalancer + + application_host: + copy: loadbalancer_host + description: >- + Host for applications. + properties: + flavor_name: m1.small + os_users: # map of os.UserInfo + nodejs: + password: nodejs123 + groups: + - www-data + capabilities: + scalable: + properties: + max_instances: 10 + + data_host: + copy: loadbalancer_host + description: >- + Host for data. + properties: + flavor_name: m1.large + flavor_id: 5d62e82c-924e-4fa9-b1e4-c133867596f7 + os_users: # map of os.UserInfo + mongodb: + password: mongo123 + requirements: + - local_storage: + node: data_volume + relationship: + properties: + location: /mnt/volume + capabilities: + scalable: + properties: + max_instances: 10 + + data_volume: + type: openstack.Volume + properties: + size: 10 GB + interfaces: + Standard: + inputs: + openstack_credential: { get_input: openstack_credential } + + groups: + + node_cellar_group: + type: openstack.Secured + members: + - loadbalancer + - application_host + - data_host + interfaces: + Standard: + inputs: + openstack_credential: { get_input: openstack_credential } + + policies: + + scaling: + type: openstack.Scaling + properties: + bandwidth_threshold: 2 GB + targets: # node templates or groups + - node_cellar_group + + juju: + description: >- + Juju plugin executes charms. + type: aria.Plugin + properties: + executor: host_agent + install: false + + maintenance_on: + type: MaintenanceWorkflow + properties: + enabled: true + + maintenance_off: + type: MaintenanceWorkflow + properties: + enabled: false + + substitution_mappings: + + node_type: tosca.nodes.WebApplication + requirements: + host: [ node_cellar, host ] # doesn't really make sense; just for testing + capabilities: + app_endpoint: [ loadbalancer, client ] + +policy_types: + + MaintenanceWorkflow: + description: >- + Workflow to put all nodes in/out of maintenance mode. For web servers, this will show a "this + site is under maintenance and we'll be back soon" web page. Database nodes will then close all + client connections cleanly and shut down services. + derived_from: aria.Workflow + properties: + function: # @override + type: string + default: workflows.maintenance + implementation: + type: string + default: tests/resources/service_templates/node-cellar + enabled: + description: >- + Whether to turn maintenance mode on or off. + type: boolean + #ctx: + # type: string + # default: abc http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/types/aria.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/types/aria.yaml b/tests/resources/service_templates/node-cellar/types/aria.yaml new file mode 100644 index 0000000..2ddb238 --- /dev/null +++ b/tests/resources/service_templates/node-cellar/types/aria.yaml @@ -0,0 +1,93 @@ + +policy_types: + + aria.Plugin: + _extensions: + role: plugin + description: >- + ARIA Plugin definition. + derived_from: tosca.policies.Root + properties: + executor: + description: >- + Where to execute the plugin's operations. + type: string + constraints: + - valid_values: [ central_deployment_agent, host_agent ] + source: + description: >- + Where to execute the plugin's operations. Where to retrieve the plugin from. Could be + either a path relative to the plugins dir inside the blueprint's root dir or a url. If + install is false, source is redundant. If install is true, source (or package_name) is + mandatory. + type: string + required: false + install_arguments: + description: >- + Optional arguments passed to the 'pip install' command created for the plugin + installation. + type: string + required: false + install: + description: >- + Whether to install the plugin or not as it might already be installed as part of the + agent. + type: boolean + default: true + package_name: + description: >- + Managed plugin package name. If install is false, package_name is redundant. If install is + true, package_name (or source) is mandatory. + type: string + required: false + package_version: + description: >- + Managed plugin package version. + type: string + required: false + supported_platform: + description: >- + Managed plugin supported platform (e.g. linux_x86_64). + type: string + required: false + supported_distribution: + description: >- + Managed plugin distribution. + type: string + required: false + distribution_version: + description: >- + Managed plugin distribution version. + type: string + required: false + distribution_release: + description: >- + Managed plugin distribution release. + type: string + required: false + + aria.Workflow: + _extensions: + role: workflow + description: >- + ARIA Workflow definition. + derived_from: tosca.policies.Root + properties: + function: + description: >- + Python workflow function. + type: string + implementation: + description: >- + The implementation artifact name (i.e., the primary script file name within a TOSCA CSAR + file). + type: string + required: false + dependencies: + description: >- + The optional ordered list of one or more dependent or secondary implementation artifact + name which are referenced by the primary implementation artifact (e.g., a library the + script installs or a secondary script). + type: list + entry_schema: string + required: false http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/types/mongodb.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/types/mongodb.yaml b/tests/resources/service_templates/node-cellar/types/mongodb.yaml new file mode 100644 index 0000000..612dbcb --- /dev/null +++ b/tests/resources/service_templates/node-cellar/types/mongodb.yaml @@ -0,0 +1,73 @@ +# +# Copyright (c) 2016 GigaSpaces Technologies Ltd. All rights reserved. +# +# 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. +# + +imports: + - os.yaml + +node_types: + + mongodb.Server: + description: >- + MongoDB server application. + derived_from: tosca.nodes.DBMS + properties: + root_password: # @override + type: string + default: admin + port: # @override + type: integer + default: 27017 + artifacts: + mongodb: + description: >- + MongoDB application package. + type: os.Archive + file: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.8.tgz + deploy_path: /opt/mongodb + capabilities: + host: # @override + type: tosca.capabilities.Container + valid_source_types: [ mongodb.Database ] + + mongodb.Database: + description: >- + MongoDB database. + + Supports importing database data if a mongodb.DatabaseDump is provided. + derived_from: tosca.nodes.Database + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + create: + implementation: + primary: mongodb/create_and_import_database.sh + dependencies: + - mongodb/utils/api.sh + - utils/os.sh + requirements: + - host: # @override + capability: tosca.capabilities.Container + node: mongodb.Server + relationship: tosca.relationships.HostedOn + +artifact_types: + + mongodb.DatabaseDump: + description: >- + Dump of a MongoDB database. + derived_from: tosca.artifacts.Root + file_ext: + - json http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/types/nginx.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/types/nginx.yaml b/tests/resources/service_templates/node-cellar/types/nginx.yaml new file mode 100644 index 0000000..8986a21 --- /dev/null +++ b/tests/resources/service_templates/node-cellar/types/nginx.yaml @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016 GigaSpaces Technologies Ltd. All rights reserved. +# +# 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. +# + +node_types: + + nginx.LoadBalancer: + description: >- + Nginx as a loadbalancer. + derived_from: tosca.nodes.LoadBalancer + requirements: + - host: + capability: tosca.capabilities.Container + node: tosca.nodes.Compute + relationship: tosca.relationships.HostedOn http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/types/nodejs.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/types/nodejs.yaml b/tests/resources/service_templates/node-cellar/types/nodejs.yaml new file mode 100644 index 0000000..ec8dd83 --- /dev/null +++ b/tests/resources/service_templates/node-cellar/types/nodejs.yaml @@ -0,0 +1,69 @@ +# +# Copyright (c) 2016 GigaSpaces Technologies Ltd. All rights reserved. +# +# 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. +# + +imports: + - os.yaml + +node_types: + + nodejs.Server: + description: >- + Node.js server application. + derived_from: tosca.nodes.WebServer + artifacts: + nodejs: + description: >- + Node.js application package. + type: os.Archive + file: https://nodejs.org/dist/v4.4.7/node-v4.4.7-linux-x64.tar.xz + deploy_path: /opt/nodejs + capabilities: + data_endpoint: # @override + type: tosca.capabilities.Endpoint + properties: + port: + type: tosca.datatypes.network.PortDef + default: 8080 + url_path: + type: string + default: / + admin_endpoint: # @override + type: tosca.capabilities.Endpoint.Admin + properties: + port: + type: tosca.datatypes.network.PortDef + default: 8080 + url_path: + type: string + default: /admin + host: # @override + type: tosca.capabilities.Container + valid_source_types: [ nodejs.Application ] + + nodejs.Application: + derived_from: tosca.nodes.WebApplication + capabilities: + app_endpoint: # @override + type: tosca.capabilities.Endpoint + properties: + port: + type: tosca.datatypes.network.PortDef + default: 8080 + requirements: + - host: # @override + capability: tosca.capabilities.Container + node: nodejs.Server + relationship: tosca.relationships.HostedOn http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/types/openstack.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/types/openstack.yaml b/tests/resources/service_templates/node-cellar/types/openstack.yaml new file mode 100644 index 0000000..a18da53 --- /dev/null +++ b/tests/resources/service_templates/node-cellar/types/openstack.yaml @@ -0,0 +1,201 @@ +# +# Copyright (c) 2016 GigaSpaces Technologies Ltd. All rights reserved. +# +# 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. +# + +imports: + - os.yaml + +dsl_definitions: + + openstack: + uuid_constraints: &OPENSTACK_UUID_CONSTRAINTS + - pattern: '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$' + +node_types: + + openstack.Instance: + description: >- + OpenStack instance. + + You may assign an image_id or attach an openstack.Image artifact (the artifact + will take precedence). + + You may assign either flavor_id or flavor_name (flavor_id will take precedence). + If neither are assigned, flavor_name has a default value. + derived_from: tosca.nodes.Compute + properties: + image_id: + description: >- + See: https://s3itwiki.uzh.ch/display/clouddoc/Supported+Images + type: openstack.UUID + default: 5d62e82c-924e-4fa9-b1e4-c133867596f7 + flavor_id: + type: openstack.UUID + required: false + flavor_name: + type: string + default: m1.medium + required: false + availability_zone: + description: >- + OpenStack availability zone. + type: string + required: false + os_users: + type: map + entry_schema: os.UserInfo + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + inputs: + openstack_credential: + description: The OpenStack API credential for all operations. + type: openstack.Credential + create: + implementation: + primary: openstack/create_instance.sh + dependencies: + - openstack/utils/api.sh + - utils/os.sh + requirements: + - local_storage: # @override + capability: tosca.capabilities.Attachment + node: openstack.Volume + relationship: tosca.relationships.AttachesTo +# relationship: +# type: tosca.relationships.AttachesTo +# interfaces: +# Standard: +# inputs: +# xxx: +# type: string +# default: { concat: [ a, b ] } + occurrences: [ 0, UNBOUNDED ] + + openstack.Volume: + description: >- + OpenStack volume. + + See: http://developer.openstack.org/api-ref-blockstorage-v2.html + derived_from: tosca.nodes.BlockStorage + properties: + tenant_id: + type: openstack.UUID + required: false + availability_zone: + type: string + required: false + source_volid: + type: openstack.UUID + required: false + description: + type: string + required: false + multiattach: + type: boolean + default: false + #snapshot_id: # @override + # type: openstack.UUID + # required: false + name: + type: string + required: false + volume_type: + type: string + required: false + metadata: + type: map + entry_schema: string + required: false + source_replica: + type: openstack.UUID + required: false + consistencygroup_id: + type: openstack.UUID + required: false + scheduler_hints: + type: map + entry_schema: string + required: false + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + inputs: + openstack_credential: + description: The OpenStack API credential for all operations. + type: openstack.Credential + create: + implementation: + primary: openstack/create_volume.sh + dependencies: + - openstack/utils/api.sh + - utils/os.sh + +group_types: + + openstack.Secured: + description: >- + OpenStack secured group. + derived_from: tosca.groups.Root + members: + - openstack.Instance + interfaces: + Standard: + type: tosca.interfaces.node.lifecycle.Standard + inputs: + openstack_credential: + description: The OpenStack API credential for all operations. + type: openstack.Credential + create: + implementation: + primary: openstack/create_secured_group.sh + dependencies: + - openstack/utils/api.sh + - utils/os.sh + +policy_types: + + openstack.Scaling: + description: >- + OpenStack scaling policy. + derived_from: tosca.policies.Scaling + properties: + bandwidth_threshold: + type: scalar-unit.size + default: 1 GB + targets: + - openstack.Instance + - openstack.Secured + +data_types: + + openstack.Credential: + derived_from: tosca.datatypes.Credential + + openstack.UUID: + description: >- + OpenStack UUID (in GUID format). + derived_from: string + constraints: *OPENSTACK_UUID_CONSTRAINTS + +artifact_types: + + openstack.Image: + description: >- + OpenStack image artifact. + derived_from: tosca.artifacts.Deployment.Image.VM + file_ext: + - img + - iso http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/types/os.yaml ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/types/os.yaml b/tests/resources/service_templates/node-cellar/types/os.yaml new file mode 100644 index 0000000..43ea78c --- /dev/null +++ b/tests/resources/service_templates/node-cellar/types/os.yaml @@ -0,0 +1,75 @@ +# +# Copyright (c) 2016 GigaSpaces Technologies Ltd. All rights reserved. +# +# 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. +# + +dsl_definitions: + + os: + user_and_group_name_constraints: &OS_USER_AND_GROUP_NAME_CONSTRAINTS + - pattern: '^[a-z0-9_-]{3,16}$' + password_constraints: &OS_PASSWORD_CONSTRAINTS + - pattern: '^[a-z0-9_-]{6,18}$' + +artifact_types: + + os.Package: + description: >- + Generic application package. + derived_from: tosca.artifacts.Root + + os.Archive: + description: >- + Application package in an archive. + derived_from: os.Package + file_ext: + - zip + - tar + - tar.gz + - tar.xz + properties: + unpack_credential: + type: tosca.datatypes.Credential + required: false + + os.Deb: + description: >- + Debian application package. + derived_from: os.Package + file_ext: + - deb + + os.RPM: + description: >- + RPM application package. + derived_from: os.Package + file_ext: + - rpm + +data_types: + + os.UserInfo: + description: >- + Information about an operating system user. + derived_from: tosca.datatypes.Root + properties: + password: + type: string + constraints: *OS_PASSWORD_CONSTRAINTS + groups: + type: list + entry_schema: + type: string + constraints: *OS_USER_AND_GROUP_NAME_CONSTRAINTS + required: false http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/d35d09a3/tests/resources/service_templates/node-cellar/workflows.py ---------------------------------------------------------------------- diff --git a/tests/resources/service_templates/node-cellar/workflows.py b/tests/resources/service_templates/node-cellar/workflows.py new file mode 100644 index 0000000..b3546bb --- /dev/null +++ b/tests/resources/service_templates/node-cellar/workflows.py @@ -0,0 +1,19 @@ + +from aria import workflow +from aria.orchestrator.workflows.api.task import OperationTask + + +@workflow +def maintenance(ctx, graph, enabled): + """ + Custom workflow to call the operations on the Maintenance interface. + """ + + operation = 'Maintenance.enable' if enabled else 'Maintenance.disable' + + for node_instance in ctx.model.node_instance.iter(): + if operation in node_instance.node.operations: + task = OperationTask.node_instance( + instance=node_instance, + name=operation) + graph.add_tasks(task)