summaryrefslogtreecommitdiffstats
path: root/onap-dcae-dcaepolicy-lib
diff options
context:
space:
mode:
Diffstat (limited to 'onap-dcae-dcaepolicy-lib')
-rw-r--r--onap-dcae-dcaepolicy-lib/LICENSE.txt30
-rw-r--r--onap-dcae-dcaepolicy-lib/MANIFEST.in1
-rw-r--r--onap-dcae-dcaepolicy-lib/README.md293
-rw-r--r--onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/__init__.py22
-rw-r--r--onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/dcae_policy.py200
-rw-r--r--onap-dcae-dcaepolicy-lib/pom.xml247
-rw-r--r--onap-dcae-dcaepolicy-lib/requirements.txt1
-rw-r--r--onap-dcae-dcaepolicy-lib/setup.py39
-rw-r--r--onap-dcae-dcaepolicy-lib/tox.ini11
9 files changed, 844 insertions, 0 deletions
diff --git a/onap-dcae-dcaepolicy-lib/LICENSE.txt b/onap-dcae-dcaepolicy-lib/LICENSE.txt
new file mode 100644
index 0000000..45ec201
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/LICENSE.txt
@@ -0,0 +1,30 @@
+============LICENSE_START=======================================================
+org.onap.dcae
+================================================================================
+Copyright (c) 2017 AT&T Intellectual Property. 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.
+============LICENSE_END=========================================================
+ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+================================================================================
+Licensed under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+you may not use this documentation except in compliance with the License.
+You may obtain a copy of the License at
+ https://creativecommons.org/licenses/by/4.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/onap-dcae-dcaepolicy-lib/MANIFEST.in b/onap-dcae-dcaepolicy-lib/MANIFEST.in
new file mode 100644
index 0000000..f9bd145
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/MANIFEST.in
@@ -0,0 +1 @@
+include requirements.txt
diff --git a/onap-dcae-dcaepolicy-lib/README.md b/onap-dcae-dcaepolicy-lib/README.md
new file mode 100644
index 0000000..71fdc6a
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/README.md
@@ -0,0 +1,293 @@
+# onap_dcae_dcaepolicy_lib - policy in dcae controller
+- python-package to be used in cloudify plugins to maintain the policies lifecycle
+
+## [setup pypi connection](./nexus_pypi.md) to **nexus** repo server
+
+## build = register and upload to nexus repo server
+
+```bash
+./dev_run.sh build
+```
+
+## upload the python package to nexus repo server
+
+```bash
+./dev_run.sh upload
+```
+
+---
+# usage in plugins
+
+**requirements.txt**
+```python
+--extra-index-url https://YOUR_NEXUS_PYPI_SERVER/simple
+onap-dcae-dcaepolicy-lib
+```
+
+**tasks.py**
+- import
+
+```python
+from onap_dcae_dcaepolicy_lib import Policies
+```
+
+# examples of **@operation** with **@Policies.<>** decorator
+
+## Usage
+
+import the dcaepolicy-node-type.yaml into your blueprint to use the dcae.nodes.type node
+
+```yaml
+imports:
+ - https://YOUR_NEXUS_RAW_SERVER/type_files/dcaepolicy/1.0.0/node-type.yaml
+```
+
+provide the value for policy_id property
+
+```yaml
+node_templates:
+...
+ host_capacity_policy:
+ type: dcae.nodes.policy
+ properties:
+ policy_id: { get_input: host_capacity_policy_id }
+```
+
+Then the dcaepolicyplugin will bring the latest policy to the dcae.nodes.policy node during the install workflow of cloudify.
+
+------
+## cloudify.interfaces.lifecycle.**configure**
+- gather policy data into runtime_properties of policy consumer node
+```yaml
+cloudify.interfaces.lifecycle:
+ configure:
+ implementation: dcae_policy_plugin.onap_dcae_dcaepolicy_lib.node_configure
+```
+
+```python
+from onap_dcae_dcaepolicy_lib import Policies, POLICIES
+from .discovery import DiscoveryClient
+from .demo_app import DemoApp
+
+APPLICATION_CONFIG = "application_config"
+SERVICE_COMPONENT_NAME = "service_component_name"
+
+@operation
+@Policies.gather_policies_to_node
+def node_configure(**kwargs):
+ """decorate with @Policies.gather_policies_to_node on policy consumer node to
+ prepopulate runtime_properties[POLICIES]
+ """
+ app_config = None
+ if APPLICATION_CONFIG in ctx.node.properties:
+ # dockerized blueprint puts the app config into property application_config
+ app_config = ctx.node.properties.get(APPLICATION_CONFIG)
+ else:
+ # CDAP components expect that in property app_config
+ app_config = ctx.node.properties.get("app_config")
+
+ app_config = Policies.shallow_merge_policies_into(app_config)
+ ctx.instance.runtime_properties[APPLICATION_CONFIG] = app_config
+ ctx.logger.info("example: applied policy_configs to property app_config: {0}" \
+ .format(json.dumps(app_config)))
+
+ if SERVICE_COMPONENT_NAME in ctx.instance.runtime_properties:
+ ctx.logger.info("saving app_config({0}) to consul under key={1}" \
+ .format(json.dumps(app_config), \
+ ctx.instance.runtime_properties[SERVICE_COMPONENT_NAME]))
+ DiscoveryClient.put_kv(ctx.instance.runtime_properties[SERVICE_COMPONENT_NAME], app_config)
+
+ # alternative 1 - use the list of policy configs from policies in runtime_properties
+ policy_configs = Policies.get_policy_configs()
+ if policy_configs:
+ ctx.logger.warn("TBD: apply policy_configs: {0}".format(json.dumps(policy_configs)))
+
+ # alternative 2 - use the policies dict by policy_id from runtime_properties
+ if POLICIES in ctx.instance.runtime_properties:
+ policies = ctx.instance.runtime_properties[POLICIES]
+ ctx.logger.warn("TBD: apply policies: {0}".format(json.dumps(policies)))
+
+ ctx.logger.info("deploying the demo component: {0}...".format(ctx.node.id))
+ demo_app = DemoApp(ctx.node.id)
+ demo_app.start()
+ ctx.logger.info("deployed the demo component: {0}".format(demo_app.container_id))
+ demo_app.get_logs()
+```
+
+------
+## execute-operation **policy-update**
+```yaml
+dcae.interfaces.policy:
+ policy_update:
+ implementation: dcae_policy_plugin.onap_dcae_dcaepolicy_lib.policy_update
+```
+
+execute-operation **policy-update** that gets a list of changed policy-configs
+```python
+
+from .discovery import DiscoveryClient
+from .demo_app import DemoApp
+
+APPLICATION_CONFIG = "application_config"
+SERVICE_COMPONENT_NAME = "service_component_name"
+
+@operation
+@Policies.update_policies_on_node(configs_only=True)
+def policy_update(updated_policies, **kwargs):
+ """decorate with @Policies.update_policies_on_node() to update runtime_properties[POLICIES]
+
+ :updated_policies: contains the list of changed policy-configs when configs_only=True (default).
+ Use configs_only=False to bring the full policy objects in :updated_policies:.
+ """
+ app_config = DiscoveryClient.get_value(ctx.instance.runtime_properties[SERVICE_COMPONENT_NAME])
+
+ # This is how to merge the policies into app_config object
+ app_config = Policies.shallow_merge_policies_into(app_config)
+
+ ctx.logger.info("merged updated_policies {0} into app_config {1}"
+ .format(json.dumps(updated_policies), json.dumps(app_config)))
+
+ ctx.instance.runtime_properties[APPLICATION_CONFIG] = app_config
+
+ DiscoveryClient.put_kv(ctx.instance.runtime_properties[SERVICE_COMPONENT_NAME], app_config)
+
+ # example how to notify the dockerized component about the policy change
+ notify_app_through_script = True
+ if notify_app_through_script:
+ ctx.logger.info("notify dockerized app about updated_policies {0} and app_config {1}"
+ .format(json.dumps(updated_policies), json.dumps(app_config)))
+ demo_app = DemoApp(ctx.node.id)
+ demo_app.notify_app_through_script(
+ POLICY_MESSAGE_TYPE,
+ updated_policies=updated_policies,
+ application_config=app_config
+ )
+```
+
+example of the **changed\_policies** with **configs_only=True**
+- list of config objects (preparsed from json string)
+- manual mess produced by mock_policy_updater
+```json
+[{
+ "policy_updated_from_ver": "2",
+ "policy_updated_to_ver": "3",
+ "updated_policy_id": "DCAE_alex.Config_db_client_policy_id_value",
+ "policy_hello": "world!",
+ "policy_updated_ts": "2017-08-17T21:49:39.279187Z"
+}]
+```
+---
+
+example of **policies** in runtime_properties **before policy-update**
+
+```json
+"runtime_properties": {
+ "execute_operation": "policy_update",
+ "service_component_name": "some-uuid.unknown.unknown.unknown.dcae.ecomp.company.com",
+ "application_config": {
+ "policy_hello": "world!",
+ "db": {
+ "type": "db",
+ "input_db_port": 5555,
+ "database_port": 5555
+ },
+ "policy_updated_from_ver": "1",
+ "intention": "policies are shallow merged to the copy of the application_config",
+ "updated_policy_id": "DCAE_alex.Config_db_client_policy_id_value",
+ "client": {
+ "client_version": "1.2.2",
+ "type": "client",
+ "client_policy_id": "DCAE_alex.Config_db_client_policy_id_value"
+ },
+ "policy_updated_ts": "2017-08-17T21:13:47.268782Z",
+ "policy_updated_to_ver": "2"
+ },
+ "exe_task": "node_configure",
+ "policies": {
+ "DCAE_alex.Config_db_client_policy_id_value": {
+ "policy_apply_mode": "script",
+ "policy_body": {
+ "policyName": "DCAE_alex.Config_db_client_policy_id_value.2.xml",
+ "policyConfigMessage": "Config Retrieved! ",
+ "responseAttributes": {
+
+ },
+ "policyConfigStatus": "CONFIG_RETRIEVED",
+ "matchingConditions": {
+ "ECOMPName": "DCAE",
+ "ConfigName": "alex_config_name"
+ },
+ "type": "OTHER",
+ "property": null,
+ "config": {
+ "policy_updated_from_ver": "1",
+ "policy_updated_to_ver": "2",
+ "updated_policy_id": "DCAE_alex.Config_db_client_policy_id_value",
+ "policy_hello": "world!",
+ "policy_updated_ts": "2017-08-17T21:13:47.268782Z"
+ },
+ "policyVersion": "2"
+ },
+ "policy_id": "DCAE_alex.Config_db_client_policy_id_value"
+ }
+ }
+}
+```
+
+example of **policies** in runtime_properties **after policy-update**
+
+```json
+"runtime_properties": {
+ "execute_operation": "policy_update",
+ "service_component_name": "some-uuid.unknown.unknown.unknown.dcae.ecomp.company.com",
+ "application_config": {
+ "policy_hello": "world!",
+ "db": {
+ "input_db_port": 5555,
+ "type": "db",
+ "database_port": 5555
+ },
+ "policy_updated_ts": "2017-08-17T21:49:39.279187Z",
+ "policy_updated_from_ver": "2",
+ "intention": "policies are shallow merged to the copy of the application_config",
+ "client": {
+ "client_version": "1.2.2",
+ "type": "client",
+ "client_policy_id": "DCAE_alex.Config_db_client_policy_id_value"
+ },
+ "updated_policy_id": "DCAE_alex.Config_db_client_policy_id_value",
+ "policy_updated_to_ver": "3"
+ },
+ "exe_task": "node_configure",
+ "policies": {
+ "DCAE_alex.Config_db_client_policy_id_value": {
+ "policy_apply_mode": "script",
+ "policy_body": {
+ "policyName": "DCAE_alex.Config_db_client_policy_id_value.3.xml",
+ "policyConfigMessage": "Config Retrieved! ",
+ "responseAttributes": {
+
+ },
+ "policyConfigStatus": "CONFIG_RETRIEVED",
+ "matchingConditions": {
+ "ECOMPName": "DCAE",
+ "ConfigName": "alex_config_name"
+ },
+ "type": "OTHER",
+ "property": null,
+ "config": {
+ "policy_updated_from_ver": "2",
+ "policy_updated_to_ver": "3",
+ "updated_policy_id": "DCAE_alex.Config_db_client_policy_id_value",
+ "policy_hello": "world!",
+ "policy_updated_ts": "2017-08-17T21:49:39.279187Z"
+ },
+ "policyVersion": "3"
+ },
+ "policy_id": "DCAE_alex.Config_db_client_policy_id_value"
+ }
+ }
+}
+```
+
+--- \ No newline at end of file
diff --git a/onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/__init__.py b/onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/__init__.py
new file mode 100644
index 0000000..b3658b1
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/__init__.py
@@ -0,0 +1,22 @@
+"""expose the Policies class on the package level"""
+
+# org.onap.dcae
+# ================================================================================
+# Copyright (c) 2017 AT&T Intellectual Property. 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+from .dcae_policy import Policies, POLICIES, POLICY_MESSAGE_TYPE
diff --git a/onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/dcae_policy.py b/onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/dcae_policy.py
new file mode 100644
index 0000000..d64d50f
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/onap_dcae_dcaepolicy_lib/dcae_policy.py
@@ -0,0 +1,200 @@
+"""dcae_policy contains decorators for the policy lifecycle in cloudify"""
+
+# org.onap.dcae
+# ================================================================================
+# Copyright (c) 2017 AT&T Intellectual Property. 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+import json
+import copy
+from functools import wraps
+
+from cloudify import ctx
+from cloudify.context import NODE_INSTANCE
+from cloudify.exceptions import NonRecoverableError
+
+POLICIES = 'policies'
+
+POLICY_ID = 'policy_id'
+POLICY_APPLY_MODE = 'policy_apply_mode'
+POLICY_BODY = 'policy_body'
+POLICY_VERSION = "policyVersion"
+POLICY_CONFIG = 'config'
+DCAE_POLICY_TYPE = 'dcae.nodes.policy'
+POLICY_MESSAGE_TYPE = 'policy'
+
+class Policies(object):
+ """static class for policy operations"""
+
+ @staticmethod
+ def gather_policies_to_node(func):
+ """decorate with @Policies.gather_policies_to_node to
+ gather the policies from dcae.nodes.policy nodes this node depends on.
+
+ Places the policies into runtime_properties["policies"].
+
+ Call Policies.shallow_merge_policies_into(config) to merge the policies into config.
+ """
+ def _merge_policy_with_node(target):
+ """get all properties of the policy node and add the actual policy"""
+ policy = dict(target.node.properties)
+ if POLICY_BODY in target.instance.runtime_properties:
+ policy[POLICY_BODY] = target.instance.runtime_properties[POLICY_BODY]
+ return policy
+
+ if not func:
+ return
+
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ """gather and save the policies from dcae.nodes.policy nodes this node related to"""
+ try:
+ if ctx.type == NODE_INSTANCE:
+ policies = dict([(rel.target.node.properties[POLICY_ID], \
+ _merge_policy_with_node(rel.target)) \
+ for rel in ctx.instance.relationships \
+ if DCAE_POLICY_TYPE in rel.target.node.type_hierarchy \
+ and POLICY_ID in rel.target.node.properties \
+ and rel.target.node.properties[POLICY_ID] \
+ ])
+ if policies:
+ ctx.instance.runtime_properties[POLICIES] = policies
+ except Exception as ex:
+ error = "Failed to set the policies {0}".format(str(ex))
+ ctx.logger.error(error)
+ raise NonRecoverableError(error)
+
+ return func(*args, **kwargs)
+ return wrapper
+
+ @staticmethod
+ def _update_policies_on_ctx(updated_policies):
+ """update policies in runtime_properties and return changed_policies"""
+ if POLICIES not in ctx.instance.runtime_properties:
+ return
+ if not updated_policies:
+ ctx.logger.error("update_policies_on_ctx - no updated_policies provided in arguments")
+ return
+
+ policies = ctx.instance.runtime_properties[POLICIES]
+ ctx.logger.info("update_policies_on_ctx: {0}".format(json.dumps(updated_policies)))
+ changed_policies = []
+ ignored_policies = []
+ unexpected_policies = []
+ same_policies = []
+ for policy in updated_policies:
+ if POLICY_ID not in policy or policy[POLICY_ID] not in policies:
+ ignored_policies.append(policy)
+ continue
+ if POLICY_BODY not in policy or POLICY_VERSION not in policy[POLICY_BODY] \
+ or not policy[POLICY_BODY][POLICY_VERSION]:
+ unexpected_policies.append(policy)
+ continue
+
+ deployed_policy = policies[policy[POLICY_ID]].get(POLICY_BODY, {})
+ new_policy_body = policy[POLICY_BODY]
+ if not deployed_policy or POLICY_VERSION not in deployed_policy \
+ or not deployed_policy[POLICY_VERSION] \
+ or deployed_policy[POLICY_VERSION] != new_policy_body[POLICY_VERSION]:
+ policies[policy[POLICY_ID]][POLICY_BODY] = new_policy_body
+ changed_policies.append(dict(policies[policy[POLICY_ID]]))
+ else:
+ same_policies.append(policy)
+
+ if same_policies:
+ ctx.logger.info("same policies: {0}".format(json.dumps(same_policies)))
+ if ignored_policies:
+ ctx.logger.info("ignored policies: {0}".format(json.dumps(ignored_policies)))
+ if unexpected_policies:
+ ctx.logger.warn("unexpected policies: {0}".format(json.dumps(unexpected_policies)))
+
+ if changed_policies:
+ ctx.instance.runtime_properties[POLICIES] = policies
+ return changed_policies
+
+ @staticmethod
+ def update_policies_on_node(configs_only=True):
+ """decorate each policy_update operation with @Policies.update_policies_on_node to
+ filter out the updated_policies to only what applies to the current node instance,
+ update runtime_properties["policies"]
+
+ :configs_only: - set to True if expect to see only the config in updated_policies
+ instead of the whole policy object (False)
+
+ Passes through the filtered list of updated_policies that apply to the current node instance
+
+ :updated_policies: contains the list of changed policy-configs when configs_only=True.
+ """
+ def update_policies_decorator(func):
+ """actual decorator"""
+ if not func:
+ return
+
+ @wraps(func)
+ def wrapper(updated_policies, **kwargs):
+ """update matching policies on context"""
+ if ctx.type != NODE_INSTANCE:
+ return
+
+ updated_policies = Policies._update_policies_on_ctx(updated_policies)
+ if updated_policies:
+ if configs_only:
+ updated_policies = [policy[POLICY_BODY][POLICY_CONFIG] \
+ for policy in updated_policies \
+ if POLICY_BODY in policy \
+ and POLICY_CONFIG in policy[POLICY_BODY] \
+ ]
+ return func(updated_policies, **kwargs)
+ return wrapper
+ return update_policies_decorator
+
+
+ @staticmethod
+ def get_policy_configs():
+ """returns the list of policy configs from the runtime policies"""
+ if ctx.type != NODE_INSTANCE \
+ or POLICIES not in ctx.instance.runtime_properties:
+ return
+ policies = ctx.instance.runtime_properties[POLICIES]
+ if not policies:
+ return
+ policy_configs = [policies[policy_id][POLICY_BODY][POLICY_CONFIG] \
+ for policy_id in policies \
+ if POLICY_BODY in policies[policy_id] \
+ and POLICY_CONFIG in policies[policy_id][POLICY_BODY] \
+ ]
+ return policy_configs
+
+ @staticmethod
+ def shallow_merge_policies_into(config):
+ """shallow merge the policy configs (dict) into config that is expected to be a dict"""
+ if config is None:
+ config = {}
+ policy_configs = Policies.get_policy_configs()
+ if not policy_configs or not isinstance(config, dict):
+ return config
+
+ for policy_config in copy.deepcopy(policy_configs):
+ if not isinstance(policy_config, dict):
+ continue
+
+ config.update(policy_config)
+ for cfg_item in policy_config:
+ if policy_config[cfg_item] is None:
+ config.pop(cfg_item, None)
+
+ return config
diff --git a/onap-dcae-dcaepolicy-lib/pom.xml b/onap-dcae-dcaepolicy-lib/pom.xml
new file mode 100644
index 0000000..642ed5d
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/pom.xml
@@ -0,0 +1,247 @@
+<?xml version="1.0"?>
+<!--
+================================================================================
+Copyright (c) 2017 AT&T Intellectual Property. 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.
+============LICENSE_END=========================================================
+
+ECOMP is a trademark and service mark of AT&T Intellectual Property.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.dcaegen2.utils</groupId>
+ <artifactId>utils</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.onap.dcaegen2.utils</groupId>
+ <artifactId>onap-dcae-dcaepolicy-lib</artifactId>
+ <name>dcaegen2-utils-onap-dcae-dcaepolicy-lib</name>
+ <version>1.0.0-SNAPSHOT</version>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <sonar.sources>.</sonar.sources>
+ <!-- customize the SONARQUBE URL -->
+ <!-- sonar.host.url>http://localhost:9000</sonar.host.url -->
+ <!-- below are language dependent -->
+ <!-- for Python -->
+ <sonar.language>py</sonar.language>
+ <sonar.pluginName>Python</sonar.pluginName>
+ <sonar.inclusions>**/*.py</sonar.inclusions>
+ <!-- for JavaScaript -->
+ <!--
+ <sonar.language>js</sonar.language>
+ <sonar.pluginName>JS</sonar.pluginName>
+ <sonar.inclusions>**/*.js</sonar.inclusions>
+ -->
+ </properties>
+ <build>
+ <finalName>${project.artifactId}-${project.version}</finalName>
+ <pluginManagement>
+ <plugins>
+ <!-- the following plugins are invoked from oparent, we do not need them -->
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <version>1.6.7</version>
+ <configuration>
+ <skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <!-- This version supports the "deployAtEnd" parameter -->
+ <version>2.8</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- first disable the default Java plugins at various stages -->
+ <!-- maven-resources-plugin is called during "*resource" phases by default behavior. it prepares
+ the resources dir. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- maven-compiler-plugin is called during "compile" phases by default behavior. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- maven-jar-plugin is called during "compile" phase by default behavior. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <phase/>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- maven-install-plugin is called during "install" phase by default behavior. it tries to copy stuff under
+ target dir to ~/.m2. we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <!-- maven-surefire-plugin is called during "test" phase by default behavior. it triggers junit test.
+ we do not need it -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.12.4</version>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <!-- plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.4.1</version>
+ <configuration>
+ <descriptors>
+ <descriptor>assembly/dep.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin -->
+ <!-- now we configure custom action (calling a script) at various lifecycle phases -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <executions>
+ <execution>
+ <id>clean phase script</id>
+ <phase>clean</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>${project.artifactId}</argument>
+ <argument>clean</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>generate-sources script</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>${project.artifactId}</argument>
+ <argument>generate-sources</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>compile script</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>${project.artifactId}</argument>
+ <argument>compile</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>package script</id>
+ <phase>package</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>${project.artifactId}</argument>
+ <argument>package</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test script</id>
+ <phase>test</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>${project.artifactId}</argument>
+ <argument>test</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>install script</id>
+ <phase>install</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>${project.artifactId}</argument>
+ <argument>install</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>deploy script</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <arguments>
+ <argument>${project.artifactId}</argument>
+ <argument>deploy</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/onap-dcae-dcaepolicy-lib/requirements.txt b/onap-dcae-dcaepolicy-lib/requirements.txt
new file mode 100644
index 0000000..2f98303
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/requirements.txt
@@ -0,0 +1 @@
+# - not here because cloudify provides it: cloudify-plugins-common==3.4
diff --git a/onap-dcae-dcaepolicy-lib/setup.py b/onap-dcae-dcaepolicy-lib/setup.py
new file mode 100644
index 0000000..b149729
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/setup.py
@@ -0,0 +1,39 @@
+"""setup.py is used for package build and distribution"""
+
+# org.onap.dcae
+# ================================================================================
+# Copyright (c) 2017 AT&T Intellectual Property. 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.
+# ============LICENSE_END=========================================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+from setuptools import setup
+
+setup(
+ name='onap_dcae_dcaepolicy_lib',
+ description='lib of policy decorators to be used by cloudify plugins of dcae controller',
+ version="1.0.0",
+ author='Alex Shatov',
+ email="dcae@lists.openecomp.org",
+ packages=['onap_dcae_dcaepolicy_lib'],
+ install_requires=[
+ ],
+ keywords='policy dcae controller cloudify plugin',
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'Programming Language :: Python :: 2.7'
+ ]
+)
diff --git a/onap-dcae-dcaepolicy-lib/tox.ini b/onap-dcae-dcaepolicy-lib/tox.ini
new file mode 100644
index 0000000..987b009
--- /dev/null
+++ b/onap-dcae-dcaepolicy-lib/tox.ini
@@ -0,0 +1,11 @@
+# content of: tox.ini , put in same dir as setup.py
+[tox]
+envlist = py27,py35
+
+[testenv]
+deps=
+ -rrequirements.txt
+ pytest
+ coverage
+ pytest-cov
+commands=pytest --junitxml xunit-results.xml --cov {envsitepackagesdir} --cov-report=xml