[feature/APPC-6]

Added Ansible Adapter Extension for APP-C

Change-Id: I4580fe5ebec526186fff5520fc7d12bff49f3fa4
Signed-off-by: Ashwin Sridharan <asridharan@research.att.com>
Signed-off-by: Patrick Brady <pb071s@att.com>
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/.gitignore b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/.gitignore
new file mode 100644
index 0000000..755cdc3
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/.gitignore
@@ -0,0 +1,3 @@
+/bin/
+/target/
+/.settings/
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/pom.xml b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/pom.xml
new file mode 100644
index 0000000..4fe7edd
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/pom.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2017 Amdocs
+  ================================================================================
+  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.openecomp.appc</groupId>
+		<artifactId>appc-ansible-adapter</artifactId>
+		<version>1.1.0-SNAPSHOT</version>
+	</parent>
+
+	<artifactId>appc-ansible-adapter-bundle</artifactId>
+	<packaging>bundle</packaging>
+	<name>APPC Ansible Service Adapter - bundle</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+			<version>1.9</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-logging</groupId>
+			<artifactId>commons-logging</artifactId>
+			<version>1.2</version>
+		</dependency>
+
+		<dependency>
+	                <groupId>org.apache.httpcomponents</groupId>
+        		<artifactId>httpclient</artifactId>
+		        <version>4.5.2</version>
+	       </dependency>
+
+		<!-- http://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
+		<dependency>
+			<groupId>org.openecomp.appc</groupId>
+			<artifactId>appc-common</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>javax</groupId>
+			<artifactId>javaee-api</artifactId>
+			<version>7.0</version>
+		</dependency>
+
+		<!-- 
+		### DEPENDENCIES NOT REQUIRED 
+
+                 <dependency>
+			<groupId>jce</groupId>
+			<artifactId>jce</artifactId>
+			<version>1_2-do</version>
+			<scope>compile</scope>
+		</dependency>  
+
+
+		<dependency>
+			<groupId>javax.ws.rs</groupId>
+			<artifactId>javax.ws.rs-api</artifactId>
+			<version>2.0</version>
+		</dependency>
+
+			<groupId>javax.xml.bind</groupId>
+			<artifactId>jaxb-api</artifactId>
+			<version>2.1</version>
+		</dependency> 
+
+		<dependency>
+			<groupId>javax.xml</groupId>
+			<artifactId>jaxp-api</artifactId>
+			<version>1.4.2</version>
+		</dependency> 
+
+		#########
+		--> 
+
+		<!-- Needed to run test cases -->
+		<dependency>
+			<groupId>org.glassfish.jersey.core</groupId>
+			<artifactId>jersey-common</artifactId>
+			<version>2.9.1</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.codehaus.jackson</groupId>
+			<artifactId>jackson-jaxrs</artifactId>
+			<version>1.9.12</version>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+
+		<dependency>
+			<groupId>org.openecomp.sdnc.core</groupId>
+			<artifactId>sli-common</artifactId>
+			<scope>compile</scope>
+			<!-- Added exclusion to prevent missing dependency issue on dblib -->
+			<exclusions>
+				<exclusion>
+					<groupId>org.openecomp.sdnc.core</groupId>
+					<artifactId>dblib-provider</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<dependency>
+			<groupId>org.openecomp.sdnc.core</groupId>
+			<artifactId>sli-provider</artifactId>
+			<scope>compile</scope>
+			<!-- Added exclusion to prevent missing dependency issue on dblib -->
+			<exclusions>
+				<exclusion>
+					<groupId>org.openecomp.sdnc.core</groupId>
+					<artifactId>dblib-provider</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<dependency>
+			<groupId>equinoxSDK381</groupId>
+			<artifactId>org.eclipse.osgi</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>jcl-over-slf4j</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>5.1.31</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+
+		 <dependency>
+		        <groupId>org.json</groupId>
+		        <artifactId>json</artifactId>
+		        <version>20160212</version>
+		</dependency>
+
+
+                <dependency>
+    			<groupId>com.google.guava</groupId>
+		        <artifactId>guava</artifactId>
+		        <version>20.0</version>
+		</dependency>
+
+                <!-- 
+                <dependency>
+    			<groupId>com.google.code.gson</groupId>
+		        <artifactId>gson</artifactId>
+		        <version>2.8.0</version>
+		</dependency>
+                -->
+
+	</dependencies>
+
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<configuration>
+					<instructions>
+						<Bundle-SymbolicName>appc-ansible-adapter</Bundle-SymbolicName>
+						<Bundle-Activator>org.openecomp.appc.adapter.ansible.AnsibleActivator</Bundle-Activator>
+						<Export-Package>org.openecomp.appc.adapter.ansible</Export-Package>
+						<Import-Package>org.openecomp.sdnc.sli.*,org.osgi.framework.*,org.slf4j.*, javax.net.*,javax.net.ssl.*,org.xml.sax.*,javax.xml.bind.*,javax.naming.*, javax.security.*</Import-Package>
+						<Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|slf4j-api|jcl-over-slf4j|mysql-connector-java|xml-apis</Embed-Dependency>
+						<Embed-Transitive>true</Embed-Transitive>
+					</instructions>
+
+					<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/AnsibleActivator.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/AnsibleActivator.java
new file mode 100644
index 0000000..fea8171
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/AnsibleActivator.java
@@ -0,0 +1,132 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import org.openecomp.appc.Constants;
+import org.openecomp.appc.adapter.ansible.impl.AnsibleAdapterImpl;
+import org.openecomp.appc.configuration.Configuration;
+import org.openecomp.appc.configuration.ConfigurationFactory;
+import org.openecomp.appc.i18n.Msg;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * This activator is used to initialize and terminate an instance of AnsibleAdapter class
+ * 
+ * Author : Ashwin Sridharan
+ * Date   : Oct 2016
+ */
+public class AnsibleActivator implements BundleActivator {
+
+    /**
+     * The bundle registration
+     */
+    private ServiceRegistration registration = null;
+
+    /**
+     * The reference to the actual implementation object that implements the services
+     */
+    private AnsibleAdapter adapter;
+
+    /**
+     * The logger to be used
+     */
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(AnsibleActivator.class);
+
+    /**
+     * The configuration object used to configure this bundle
+     */
+    private Configuration configuration;
+
+    /**
+     * Called when this bundle is started so the Framework can perform the bundle-specific activities necessary to start
+     * this bundle. This method can be used to register services or to allocate any resources that this bundle needs.
+     * <p>
+     * This method must complete and return to its caller in a timely manner.
+     * </p>
+     * 
+     * @param context
+     *            The execution context of the bundle being started.
+     * @throws java.lang.Exception
+     *             If this method throws an exception, this bundle is marked as stopped and the Framework will remove
+     *             this bundle's listeners, unregister all services registered by this bundle, and release all services
+     *             used by this bundle.
+     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+     */
+    @Override
+    public void start(BundleContext context) throws Exception {
+
+        logger.info("Starting bundle " + getName());
+	String appName = "APPC: ";
+        logger.info(Msg.COMPONENT_INITIALIZING, appName, "Ansible Adapter");
+	adapter = new AnsibleAdapterImpl();
+	
+        if (registration == null) {
+            logger.info(Msg.REGISTERING_SERVICE, appName, adapter.getAdapterName(),
+			AnsibleAdapter.class.getSimpleName());
+            registration = context.registerService(AnsibleAdapter.class, adapter, null);
+        }
+
+        logger.info(Msg.COMPONENT_INITIALIZED, appName, "Ansible adapter");
+    }
+
+    /**
+     * Called when this bundle is stopped so the Framework can perform the bundle-specific activities necessary to stop
+     * the bundle. In general, this method should undo the work that the BundleActivator.start method started. There
+     * should be no active threads that were started by this bundle when this bundle returns. A stopped bundle must not
+     * call any Framework objects.
+     * <p>
+     * This method must complete and return to its caller in a timely manner.
+     * </p>
+     * 
+     * @param context
+     *            The execution context of the bundle being stopped.
+     * @throws java.lang.Exception
+     *             If this method throws an exception, the bundle is still marked as stopped, and the Framework will
+     *             remove the bundle's listeners, unregister all services registered by the bundle, and release all
+     *             services used by the bundle. *
+     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+     */
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        logger.info("Stopping bundle " + getName());
+
+        if (registration != null) {
+            String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
+            logger.info(Msg.COMPONENT_TERMINATING, appName, "Ansible adapter");
+            logger.info(Msg.UNREGISTERING_SERVICE, appName, adapter.getAdapterName());
+            registration.unregister();
+            registration = null;
+            logger.info(Msg.COMPONENT_TERMINATED, appName, "Ansible adapter");
+        }
+    }
+
+    public String getName() {
+        return "APPC Ansible Adapter";
+    }
+
+}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/AnsibleAdapter.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/AnsibleAdapter.java
new file mode 100644
index 0000000..8f2725d
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/AnsibleAdapter.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible;
+
+import java.util.Map;
+
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.sdnc.sli.SvcLogicContext;
+import org.openecomp.sdnc.sli.SvcLogicJavaPlugin;
+import org.openecomp.sdnc.sli.SvcLogicException;
+
+/**
+ * This interface defines the operations that the Ansible  adapter exposes.
+ * 
+ */
+public interface AnsibleAdapter extends SvcLogicJavaPlugin {
+
+
+    /**
+     * Returns the symbolic name of the adapter
+     * 
+     * @return The adapter name
+     */
+    String getAdapterName();
+
+
+    /* Method to post request for execution of Playbook */
+    void reqExec(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+    /* Method to get result of a playbook execution request */
+    void reqExecResult(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+
+    /* Method to get log  of a playbook execution request */
+    void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+
+}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/impl/AnsibleAdapterImpl.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/impl/AnsibleAdapterImpl.java
new file mode 100644
index 0000000..ba35a70
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/impl/AnsibleAdapterImpl.java
@@ -0,0 +1,516 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible.impl;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.lang.*;
+    
+import org.openecomp.appc.Constants;
+import org.openecomp.appc.exceptions.APPCException;
+
+import org.openecomp.appc.configuration.Configuration;
+import org.openecomp.appc.configuration.ConfigurationFactory;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.i18n.Msg;
+import org.openecomp.appc.pool.Pool;
+import org.openecomp.appc.pool.PoolExtensionException;
+import org.openecomp.appc.util.StructuredPropertyHelper;
+import org.openecomp.appc.util.StructuredPropertyHelper.Node;
+
+import org.openecomp.sdnc.sli.SvcLogicContext;
+import org.openecomp.sdnc.sli.SvcLogicException;
+
+
+import org.slf4j.MDC;
+
+import org.json.JSONObject;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+
+import com.google.common.base.Strings;
+//import com.google.gson.Gson;
+//import com.google.gson.GsonBuilder;
+
+import org.openecomp.appc.adapter.ansible.AnsibleAdapter;
+
+import org.openecomp.appc.adapter.ansible.model.AnsibleResult;
+import org.openecomp.appc.adapter.ansible.model.AnsibleMessageParser;
+import org.openecomp.appc.adapter.ansible.model.AnsibleResultCodes;
+import org.openecomp.appc.adapter.ansible.model.AnsibleServerEmulator;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.att.eelf.i18n.EELFResourceManager;
+import static com.att.eelf.configuration.Configuration.*;
+
+
+/**
+ * This class implements the {@link AnsibleAdapter} interface. This interface
+ * defines the behaviors that our service provides.
+ *
+ */
+public class AnsibleAdapterImpl implements AnsibleAdapter {
+
+    /**
+     * The constant used to define the adapter name in the mapped diagnostic
+     * context
+     */
+	
+
+    @SuppressWarnings("nls")
+    public static final String MDC_ADAPTER = "Ansible Adapter";
+
+    /**
+     * The constant used to define the service name in the mapped diagnostic
+     * context
+     */
+    @SuppressWarnings("nls")
+    public static final String MDC_SERVICE = "service";
+
+    /**
+     * The constant for the status code for a failed outcome
+     */
+    @SuppressWarnings("nls")
+    public static final String OUTCOME_FAILURE = "failure";
+
+    /**
+     * The constant for the status code for a successful outcome
+     */
+    @SuppressWarnings("nls")
+    public static final String OUTCOME_SUCCESS = "success";
+
+    /**
+      Adapter Name 
+    **/
+    private static final String ADAPTER_NAME = "Ansible Adapter";
+
+   
+    /**
+     * The logger to be used
+     */
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(AnsibleAdapterImpl.class);
+    
+    /**
+      * A reference to the adapter configuration object.
+    */
+    private Configuration configuration;;
+
+    /** can Specify a X509 certificate file for use if required ... 
+    Must be initialized with setCertFile 
+    **/
+    private String certFile = "";
+
+
+    /**
+     * Connection object 
+     **/
+    ConnectionBuilder  http_client ;
+    
+    /** 
+     * Ansible API Message Handlers
+     **/
+    private AnsibleMessageParser messageProcessor;
+
+    /**
+       indicator whether in test mode
+    **/
+    private boolean  testMode = false;
+
+    /**
+       server emulator object to be used if in test mode 
+    **/
+    private AnsibleServerEmulator testServer;
+    
+    /**
+     * This default constructor is used as a work around because the activator
+     * wasnt getting called
+     */
+    public AnsibleAdapterImpl() {
+	initialize();
+    }
+
+
+    /**
+     * @param props
+     *            not used
+     */
+    public AnsibleAdapterImpl(Properties props) {
+	initialize();
+    }
+
+
+
+    /** 
+	Used for jUnit test and testing interface 
+    **/
+    public AnsibleAdapterImpl(boolean Mode){
+	testMode = Mode;
+	testServer = new AnsibleServerEmulator();
+	messageProcessor = new AnsibleMessageParser();
+    }
+    
+    /**
+     * Returns the symbolic name of the adapter
+     * 
+     * @return The adapter name
+     * @see org.openecomp.appc.adapter.rest.AnsibleAdapter#getAdapterName()
+     */
+    @Override
+    public String getAdapterName() {
+	return ADAPTER_NAME;
+    }
+
+
+    
+    /**
+     * @param rc
+     *  Method posts info to Context memory in case of an error
+     *  and throws a SvcLogicException causing SLI to register this as a failure
+     */
+    @SuppressWarnings("static-method")
+    private void doFailure(SvcLogicContext svcLogic,  int code, String message)  throws SvcLogicException {
+
+	svcLogic.setStatus(OUTCOME_FAILURE);
+	svcLogic.setAttribute("org.openecomp.appc.adapter.ansible.result.code",Integer.toString(code));
+	svcLogic.setAttribute("org.openecomp.appc.adapter.ansible.message",message);
+	
+	throw new SvcLogicException("Ansible Adapter Error = " + message );
+    }
+	
+
+    /**
+     * initialize the  Ansible adapter based on default and over-ride configuration data  
+     */
+    private void initialize()  {
+
+	configuration = ConfigurationFactory.getConfiguration();
+	Properties props = configuration.getProperties();
+	
+	// Create the message processor instance 
+	messageProcessor = new AnsibleMessageParser();
+
+        // Create the http client instance
+        // type of client is extracted from the property file parameter
+        // org.openecomp.appc.adapter.ansible.clientType
+        // It can be :
+        //     1. TRUST_ALL  (trust all SSL certs). To be used ONLY in dev
+        //     2. TRUST_CERT (trust only those whose certificates have been stored in the trustStore file)
+        //     3. DEFAULT    (trust only well known certificates). This is standard behaviour to which it will
+        //     revert. To be used in PROD
+
+        try{
+            String clientType = props.getProperty("org.openecomp.appc.adapter.ansible.clientType");
+	    logger.info("Ansible http client type set to " + clientType);
+
+            if (clientType.equals("TRUST_ALL")){
+                logger.info("Creating http client to trust ALL ssl certificates. WARNING. This should be done only in dev environments");
+                http_client = new ConnectionBuilder(1);
+            }
+            else if (clientType.equals("TRUST_CERT")){
+                // set path to keystore file
+                String trustStoreFile = props.getProperty("org.openecomp.appc.adapter.ansible.trustStore");
+                String key  = props.getProperty("org.openecomp.appc.adapter.ansible.trustStore.trustPasswd");
+                char [] trustStorePasswd = key.toCharArray();
+                String trustStoreType = "JKS";
+                logger.info("Creating http client with trustmanager from " + trustStoreFile);
+                http_client = new ConnectionBuilder(trustStoreFile, trustStorePasswd);
+            }
+            else{
+                logger.info("Creating http client with default behaviour");
+                http_client = new ConnectionBuilder(0);
+            }
+        }
+        catch (Exception e){
+            logger.error("Error Initializing Ansible Adapter due to Unknown Exception: reason = " + e.getMessage());
+        }
+
+	logger.info("Intitialized Ansible Adapter");
+	
+    }
+
+
+    /** set the certificate file if not a trusted/known CA **/
+    private void setCertFile(String CertFile){
+	this.certFile = CertFile;
+    }
+    
+
+
+    // Public Method to post request to execute playbook. Posts the following back
+    // to Svc context memory
+    //  org.openecomp.appc.adapter.ansible.req.code : 100 if successful
+    //  org.openecomp.appc.adapter.ansible.req.messge : any message
+    //  org.openecomp.appc.adapter.ansible.req.Id : a unique uuid to reference the request
+
+    public void reqExec(Map <String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+	String PlaybookName = "";
+	String payload = "";
+	String AgentUrl = "";
+	String User = "";
+	String Password = "";
+	String Id = "";
+	
+	JSONObject JsonPayload;
+	
+	try{
+	    // create json object to send request
+	    JsonPayload = messageProcessor.ReqMessage(params);
+	    
+	    AgentUrl = (String) JsonPayload.remove("AgentUrl");
+       	    User =  (String) JsonPayload.remove("User");
+	    Password = (String) JsonPayload.remove("Password");
+	    Id = (String)JsonPayload.getString("Id");
+	    payload = JsonPayload.toString();
+	    logger.info("Updated Payload  = "  + payload);
+	}
+	catch(APPCException e){
+	    doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request for execution of playbook due to missing mandatory parameters. Reason = " + e.getMessage());
+	}
+	catch(JSONException e){
+	    doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request for execution of playbook due to invalid JSON block. Reason = " + e.getMessage());
+	}
+	catch(NumberFormatException e){
+	    doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request for execution of playbook due to invalid parameter values. Reason = " + e.getMessage());
+	}
+	
+    
+ 
+	int code = -1;
+	String message = "";
+	
+	try{
+	    
+	    // post the test request
+	    //---------------------------------------
+	    logger.info("Posting request = " + payload + " to url = " + AgentUrl );
+	    AnsibleResult testresult = postExecRequest(AgentUrl, payload, User, Password);
+
+    
+	    // Process if HTTP was successfull
+	    if(testresult.getStatusCode() == 200){
+		testresult = messageProcessor.parsePostResponse(testresult.getStatusMessage());
+	    }
+	    else{
+		doFailure(ctx, testresult.getStatusCode(), "Error posting request. Reason = " + testresult.getStatusMessage());
+	    }
+
+    
+	    code = testresult.getStatusCode();
+	    message = testresult.getStatusMessage();
+
+		    
+	    // Check status of test request returned by Agent
+	    //-----------------------------------------------
+	    if (code == AnsibleResultCodes.PENDING.getValue()){
+		logger.info(String.format("Submission of Test %s successful.", PlaybookName));
+		// test request accepted. We are in asynchronous case
+	    }
+	    else{
+		doFailure(ctx, code, "Request for execution of playbook rejected. Reason = " + message);
+	    }
+	}
+	
+	catch(APPCException e){
+	    doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(), "Exception encountered when posting request for execution of playbook. Reason = "  + e.getMessage());
+	}
+
+
+	ctx.setAttribute("org.openecomp.appc.adapter.ansible.result.code", Integer.toString(code));
+	ctx.setAttribute("org.openecomp.appc.adapter.ansible.message", message );
+	ctx.setAttribute("org.openecomp.appc.adapter.ansible.Id", Id);
+	
+    }
+
+
+    // Public method to query status of a specific request
+    // It blocks till the Ansible Server responds or the session times out
+    
+    public void reqExecResult(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+	    
+	// Get uri
+	String ReqUri = "";
+	
+	try{
+	    ReqUri = messageProcessor.ReqUri_Result(params);
+	    System.out.println("Got uri = " + ReqUri);
+	}
+	catch(APPCException e){
+	    doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request to retreive result due to missing parameters. Reason = " + e.getMessage());
+	    return;
+	}
+	catch(NumberFormatException e){
+	    doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error constructing request to retreive result due to invalid parameters value. Reason = " + e.getMessage());
+	    return;
+	}
+
+	int code = -1;
+	String message = "";
+	String results = "";
+	
+	try{
+	    // Try to  retreive the test results (modify the url for that)
+	    AnsibleResult testresult = queryServer(ReqUri, params.get("User"), params.get("Password"));
+	    code = testresult.getStatusCode();
+	    message = testresult.getStatusMessage();
+
+	    if(code == 200){
+		logger.info("Parsing response from Server = " + message);
+		// Valid HTTP. process the Ansible message
+		testresult = messageProcessor.parseGetResponse(message);
+		code = testresult.getStatusCode();
+		message = testresult.getStatusMessage();
+		results = testresult.getResults();
+		
+	    }
+	    
+	    logger.info("Request response = " + message);
+
+	}
+	catch (APPCException e){
+	    doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(), "Exception encountered retreiving result : " + e.getMessage());
+	    return;
+	}
+
+	// We were able to get and process the results. Determine if playbook succeeded
+	
+	if (code == AnsibleResultCodes.FINAL_SUCCESS.getValue()){
+	    message = String.format("Ansible Request  %s finished with Result = %s, Message = %s", params.get("Id"), OUTCOME_SUCCESS, message);
+	    logger.info(message);
+	}
+	else {
+	    logger.info(String.format("Ansible Request  %s finished with Result %s, Message = %s", params.get("Id"), OUTCOME_FAILURE, message));
+	    ctx.setAttribute("org.openecomp.appc.adapter.ansible.results", results);
+	    doFailure(ctx, code, message );
+	    return;	    
+	}
+	
+      
+	ctx.setAttribute("org.openecomp.appc.adapter.ansible.result.code", Integer.toString(400));
+	ctx.setAttribute("org.openecomp.appc.adapter.ansible.message",message);
+	ctx.setAttribute("org.openecomp.appc.adapter.ansible.results", results);
+	ctx.setStatus(OUTCOME_SUCCESS);
+    }
+    
+
+    // Public method to get logs  from plyabook execution for a  specifcic request
+    // It blocks till the Ansible Server responds or the session times out
+    // very similar to reqExecResult
+    // logs are returned in the DG context variable org.openecomp.appc.adapter.ansible.log
+    
+    public void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException{
+
+
+	// Get uri
+	String ReqUri = "";
+	try{
+	    ReqUri = messageProcessor.ReqUri_Log(params);
+	    logger.info("Retreiving results from " + ReqUri); 
+	}
+	catch(Exception e){
+	    doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), e.getMessage());
+	}
+
+	int code = -1;
+	String message = "";
+	float Duration = -1;
+	
+	try{
+	    // Try to  retreive the test results (modify the url for that)
+	    AnsibleResult testresult = queryServer(ReqUri, params.get("User"), params.get("Password"));
+	    code = testresult.getStatusCode();
+	    message = testresult.getStatusMessage();
+
+	    logger.info("Request output = " + message);
+
+	}
+	catch (Exception e){
+	    doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(), "Exception encountered retreiving output : " + e.getMessage());
+	}
+	
+	ctx.setAttribute("org.openecomp.appc.adapter.ansible.log",message);
+	ctx.setStatus(OUTCOME_SUCCESS);
+    }
+    
+
+    
+
+	
+    /**
+     * Method that posts the request
+     **/
+    
+    private AnsibleResult  postExecRequest(String AgentUrl, String Payload, String User, String Password)  {
+	
+	String reqOutput = "UNKNOWN";
+	int    reqStatus = -1;
+
+	AnsibleResult testresult;
+	
+	if (!testMode){
+	    http_client.setHttpContext(User, Password);
+	    testresult  = http_client.Post(AgentUrl, Payload);
+	}
+	else{
+	    testresult = testServer.Post(AgentUrl, Payload);
+	}
+	   
+	return testresult;
+    }
+    
+
+    /* 
+       Method to query Ansible server
+
+    */
+    private AnsibleResult queryServer(String AgentUrl, String User, String Password) {
+
+	String testOutput = "UNKNOWN";
+	int    testStatus = -1;
+	AnsibleResult testresult;
+	
+	logger.info("Querying url = " + AgentUrl);
+
+	if (!testMode){
+	    testresult = http_client.Get(AgentUrl);
+	}
+	else{
+	    testresult = testServer.Get(AgentUrl);
+	}
+	
+	return testresult;
+	
+    }
+
+
+
+}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/impl/ConnectionBuilder.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/impl/ConnectionBuilder.java
new file mode 100644
index 0000000..5c2801c
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/impl/ConnectionBuilder.java
@@ -0,0 +1,225 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible.impl;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.entity.StringEntity;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.CertificateException;
+import java.security.KeyManagementException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.NoSuchAlgorithmException;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.X509TrustManager;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+
+
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.adapter.ansible.model.AnsibleResult;
+import org.openecomp.appc.adapter.ansible.model.AnsibleResultCodes;
+
+
+/** 
+     * Returns custom http client 
+     - based on options
+     - can create one with ssl using an X509 certificate that does NOT  have a known CA
+     - create one which trusts ALL SSL certificates
+     - return default httpclient (which only trusts known CAs from default cacerts file for process) -- this is the default option
+     
+**/
+
+
+public class ConnectionBuilder {
+
+
+
+    private   CloseableHttpClient http_client = null;
+    private HttpClientContext http_context  = new HttpClientContext();
+
+
+
+
+    // Various constructors depending on how we want to instantiate the http ConnectionBuilder instance
+
+
+    /**
+     * Constructor that initializes an http client based on certificate
+     **/
+    public ConnectionBuilder(String CertFile) throws KeyStoreException, CertificateException, IOException, KeyManagementException, NoSuchAlgorithmException, APPCException{
+	
+	
+	/* Point to the certificate */
+	FileInputStream fs = new FileInputStream(CertFile);
+	
+	/* Generate a certificate from the X509 */
+	CertificateFactory cf = CertificateFactory.getInstance("X.509");
+	X509Certificate cert = (X509Certificate)cf.generateCertificate(fs);
+	
+	/* Create a keystore object and load the certificate there */
+	KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+	keystore.load(null, null);
+	keystore.setCertificateEntry("cacert", cert);
+	
+	
+	SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore).build();
+	SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+	
+	http_client  = HttpClients.custom().setSSLSocketFactory(factory).build();
+    };
+
+
+    /**
+     * Constructor which trusts all certificates in a specific java keystore file (assumes a JKS file)
+     **/
+    public ConnectionBuilder(String trustStoreFile, char[] trustStorePasswd) throws KeyStoreException, IOException, KeyManagementException, NoSuchAlgorithmException, CertificateException {
+	
+	
+	/* Load the specified trustStore */
+	KeyStore keystore = KeyStore.getInstance("JKS");
+	FileInputStream readStream = new FileInputStream(trustStoreFile);
+	keystore.load(readStream,trustStorePasswd);
+	
+	SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore).build();
+	SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+	
+	http_client  = HttpClients.custom().setSSLSocketFactory(factory).build();
+    };
+
+    /**
+     * Constructor that trusts ALL SSl certificates  (NOTE : ONLY FOR DEV TESTING) if Mode == 1
+     or Default if Mode == 0
+    */
+    public ConnectionBuilder(int Mode) throws SSLException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException{
+	if (Mode == 1){
+	    SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null,  new TrustSelfSignedStrategy()).build();
+	    SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+	    
+	    http_client = HttpClients.custom().setSSLSocketFactory(factory).build();       	    
+	}
+
+	else{
+	    http_client = HttpClients.createDefault();
+	}
+	
+    };
+
+   
+    // Use to create an http context with auth headers
+    public  void  setHttpContext(String User, String MyPassword){
+	
+	// Are credential provided ? If so, set the context to be used 
+	if (User != null && ! User.isEmpty() && MyPassword != null && ! MyPassword.isEmpty()){	
+	    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(User, MyPassword);
+	    AuthScope authscope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT);
+	    BasicCredentialsProvider credsprovider = new BasicCredentialsProvider();
+	    credsprovider.setCredentials(authscope, credentials);
+	    http_context.setCredentialsProvider(credsprovider);
+	}
+
+	
+    };
+
+
+    // Method posts to the ansible server and writes out response to 
+    // Ansible result object 
+    public AnsibleResult Post(String AgentUrl, String Payload){
+
+	AnsibleResult result = new AnsibleResult();
+	try{
+	    
+	    HttpPost postObj = new HttpPost(AgentUrl);
+	    StringEntity bodyParams = new StringEntity(Payload, "UTF-8");
+	    postObj.setEntity(bodyParams);
+	    postObj.addHeader("Content-type", "application/json");
+	    
+	    HttpResponse response = http_client.execute(postObj, http_context);
+	    
+	    HttpEntity entity = response.getEntity();
+	    String responseOutput =  entity != null ? EntityUtils.toString(entity) : null;
+	    int responseCode = response.getStatusLine().getStatusCode();
+	    result.setStatusCode(responseCode);
+	    result.setStatusMessage(responseOutput);
+	}
+	
+	catch(IOException io){
+	    result.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
+	    result.setStatusMessage(io.getMessage());
+	}
+	
+	
+
+	return result;
+
+    }
+    
+    // Method gets information from an Ansible server and writes out response to
+    // Ansible result object
+
+    public AnsibleResult Get(String AgentUrl){
+
+	AnsibleResult result = new AnsibleResult();
+
+	try{
+	    HttpGet getObj = new HttpGet(AgentUrl );
+	    HttpResponse response =  http_client.execute(getObj, http_context);
+	    
+	    
+	    HttpEntity entity = response.getEntity();
+	    String responseOutput =  entity != null ? EntityUtils.toString(entity) : null;
+	    int responseCode = response.getStatusLine().getStatusCode();
+	    result.setStatusCode(responseCode);
+	    result.setStatusMessage(responseOutput);
+
+	}
+	catch(IOException io){
+	    result.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
+	    result.setStatusMessage(io.getMessage());
+	}
+	
+	return result;
+    };
+
+}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleMessageParser.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleMessageParser.java
new file mode 100644
index 0000000..e9b8899
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleMessageParser.java
@@ -0,0 +1,362 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible.model;
+
+/**
+ * This module imples the APP-C/Ansible Server interface
+ * based on the REST API specifications
+ */
+
+import java.lang.NumberFormatException ;
+import java.util.*;
+import com.google.common.base.Strings;
+
+import org.json.JSONObject;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.adapter.ansible.model.AnsibleResult;
+
+
+/**
+ * Class that validates and constructs requests sent/received from 
+ * Ansible Server
+ *
+ */
+public class AnsibleMessageParser {
+
+
+
+
+    // Accepts a map of strings and
+    // a) validates if all parameters are appropriate (else, throws an exception)
+    // and b) if correct returns a JSON object with appropriate key-value
+    // pairs to send to the server. 
+    public JSONObject ReqMessage(Map <String, String> params) throws APPCException, NumberFormatException, JSONException{
+
+	// Mandatory  parameters, that must be in the supplied information to the Ansible Adapter
+	// 1. URL to connect to
+	// 2. credentials for URL (assume username password for now)
+	// 3. Playbook name
+	String[] mandatoryTestParams = {"AgentUrl", "PlaybookName", "User", "Password"};
+
+	// Optional testService parameters that may be provided in the request
+	String[] optionalTestParams = {"EnvParameters", "NodeList", "LocalParameters", "Timeout", "Version", "FileParameters", "Action"};
+
+	JSONObject JsonPayload = new JSONObject();
+	String payload = "";
+	JSONObject paramsJson;
+
+  
+	// Verify all the mandatory parameters are there 
+	for (String key: mandatoryTestParams){
+	    if (! params.containsKey(key)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !", key));
+	    }
+	    payload = params.get(key);
+	    if (Strings.isNullOrEmpty(payload)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key % value is Null or Emtpy", key));
+	    }
+	    
+	    JsonPayload.put(key, payload);
+	}
+
+	// Iterate through optional parameters
+	// If null or empty omit it 
+	for (String key : optionalTestParams){
+	    if (params.containsKey(key)){
+		payload = params.get(key);
+		if(!Strings.isNullOrEmpty(payload)){
+		    
+		    // different cases require different treatment
+		    switch (key){
+		    case "Timeout": 
+			int Timeout = Integer.parseInt(payload);
+			if (Timeout < 0){
+			    throw new NumberFormatException(" : specified negative integer for timeout = " +  payload);
+			}
+			JsonPayload.put(key, payload);
+			break;
+
+		    case "Version": 
+			JsonPayload.put(key, payload);
+			break;
+
+		    case "LocalParameters":  
+			paramsJson = new JSONObject(payload);
+			JsonPayload.put(key, paramsJson);
+			break;
+			
+		    case "EnvParameters":  
+			paramsJson = new JSONObject(payload);
+			JsonPayload.put(key, paramsJson);
+			break;
+			
+		    case "NodeList":  
+			JSONArray paramsArray = new JSONArray(payload);
+			JsonPayload.put(key, paramsArray);
+			break;
+			
+		    case "FileParameters":
+			// Files may have strings with newlines. Escape them as appropriate
+			String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+			JSONObject fileParams = new JSONObject(formattedPayload);
+			JsonPayload.put(key, fileParams);
+			break;
+			
+		    }
+		}
+	    }
+	}
+	
+
+	// Generate a unique uuid for the test
+	String ReqId = UUID.randomUUID().toString();
+	JsonPayload.put("Id", ReqId);
+
+	return JsonPayload;
+	
+    }
+
+
+
+    // method that validates that the Map has  enough information
+    // to query Ansible server for a result . If so, it
+    // returns the appropriate url, else an empty string
+    public String ReqUri_Result(Map <String, String> params) throws APPCException, NumberFormatException{
+	
+	// Mandatory  parameters, that must be in the request
+	String[] mandatoryTestParams = {"AgentUrl", "Id", "User", "Password" };
+	
+	// Verify all the mandatory parameters are there
+	String payload = "";
+	String Uri = "";
+	
+	for (String key: mandatoryTestParams){
+	    if (! params.containsKey(key)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !", key));		    
+	    }
+
+	    payload = params.get(key);
+	    if (Strings.isNullOrEmpty(payload)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !", key));		    
+	    }
+
+	}
+
+	Uri = params.get("AgentUrl") + "?Id=" + params.get("Id") + "&Type=GetResult";
+
+	return Uri;
+      
+    }
+
+
+
+    // method that validates that the Map has  enough information
+    // to query Ansible server for logs. If so, it populates the appropriate
+    // returns the appropriate url, else an empty string
+    public String ReqUri_Output(Map <String, String> params) throws APPCException, NumberFormatException{
+	
+	
+	// Mandatory  parameters, that must be in the request
+	String[] mandatoryTestParams = {"AgentUrl", "Id", "User", "Password" };
+	
+	// Verify all the mandatory parameters are there
+	String payload = "";
+	String Uri = "";
+	
+	for (String key: mandatoryTestParams){
+	    if (! params.containsKey(key)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !", key));		    
+	    }
+	    payload = params.get(key);
+	    if (Strings.isNullOrEmpty(payload)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !", key));		    
+	    }
+
+	}
+
+	Uri = params.get("AgentUrl") + "?Id=" + params.get("Id") + "&Type=GetOutput";
+	return Uri;
+      
+    }
+
+    // method that validates that the Map has  enough information
+    // to query Ansible server for logs. If so, it populates the appropriate
+    // returns the appropriate url, else an empty string
+    public String ReqUri_Log(Map <String, String> params) throws APPCException, NumberFormatException{
+	
+	
+	// Mandatory  parameters, that must be in the request
+	String[] mandatoryTestParams = {"AgentUrl", "Id", "User", "Password" };
+	
+	// Verify all the mandatory parameters are there
+	String payload = "";
+	String Uri = "";
+	
+	for (String key: mandatoryTestParams){
+	    if (! params.containsKey(key)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !", key));		    
+	    }
+	    payload = params.get(key);
+	    if (Strings.isNullOrEmpty(payload)){
+		throw new APPCException(String.format("Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !", key));		    
+	    }
+
+	}
+
+	Uri = params.get("AgentUrl") + "?Id=" + params.get("Id") + "&Type=GetLog";
+	return Uri;
+      
+    }
+
+   
+    /** 
+	This method parses response from the 
+	Ansible Server when we do a post 
+	and returns an AnsibleResult object
+    **/
+    
+    public AnsibleResult  parsePostResponse(String Input) throws APPCException{
+
+	AnsibleResult ansibleResult = new AnsibleResult();
+	
+	try{
+	    //Jsonify it
+	    JSONObject  postResponse = new JSONObject(Input);
+		
+	    // Mandatory keys required are StatusCode and StatusMessage
+	    int Code = postResponse.getInt("StatusCode");
+	    String Message = postResponse.getString("StatusMessage");
+
+	    
+	    // Status code must must be either 100 (accepted) or 101 (rejected)
+	    boolean valCode = AnsibleResultCodes.CODE.checkValidCode(AnsibleResultCodes.INITRESPONSE.getValue(), Code);
+	    if(!valCode){
+		throw new APPCException("Invalid InitResponse code  = " + Code + " received. MUST be one of " + AnsibleResultCodes.CODE.getValidCodes(AnsibleResultCodes.INITRESPONSE.getValue()) );
+	    }
+	    
+	    ansibleResult.setStatusCode(Code);
+	    ansibleResult.setStatusMessage(Message);
+
+	}
+	catch(JSONException e){
+	    ansibleResult = new AnsibleResult(600, "Error parsing response = " + Input + ". Error = " + e.getMessage(), "");
+	}
+
+	
+	return ansibleResult;
+    }
+
+
+    /** This method  parses response from an Ansible server when we do a GET for a result 
+	and returns an AnsibleResult object
+     **/
+    public AnsibleResult  parseGetResponse(String Input) throws APPCException {
+
+	AnsibleResult ansibleResult = new AnsibleResult();
+	int FinalCode = AnsibleResultCodes.FINAL_SUCCESS.getValue();
+
+
+	try{
+	    
+	    //Jsonify it
+	    JSONObject  postResponse = new JSONObject(Input);
+	    
+	    // Mandatory keys required are Status and Message
+	    int Code = postResponse.getInt("StatusCode");
+	    String Message = postResponse.getString("StatusMessage");
+	    
+	    // Status code must be valid
+	    // Status code must must be either 100 (accepted) or 101 (rejected)
+	    boolean valCode = AnsibleResultCodes.CODE.checkValidCode(AnsibleResultCodes.FINALRESPONSE.getValue(), Code);
+	    
+	    if(!valCode){
+		throw new APPCException("Invalid FinalResponse code  = " + Code + " received. MUST be one of " + AnsibleResultCodes.CODE.getValidCodes(AnsibleResultCodes.FINALRESPONSE.getValue()));
+	    }
+
+	    
+	    ansibleResult.setStatusCode(Code);
+	    ansibleResult.setStatusMessage(Message);
+	    System.out.println("Received response with code = " + Integer.toString(Code) + " Message = " + Message);
+
+	    if(! postResponse.isNull("Results")){
+
+		// Results are available. process them 
+		// Results is a dictionary of the form
+		// {host :{status:s, group:g, message:m, hostname:h}, ...}
+		System.out.println("Processing results in response");
+		JSONObject results = postResponse.getJSONObject("Results");
+		System.out.println("Get JSON dictionary from Results ..");
+		Iterator<String> hosts = results.keys();
+		System.out.println("Iterating through hosts");
+		
+		while(hosts.hasNext()){
+		    String host = hosts.next();
+		    System.out.println("Processing host = " + host);
+		    
+		    try{
+			JSONObject host_response = results.getJSONObject(host);
+			int subCode = host_response.getInt("StatusCode");
+			String message = host_response.getString("StatusMessage");
+
+			System.out.println("Code = " + Integer.toString(subCode) + " Message = " + message);
+			
+			if(subCode != 200 || ! message.equals("SUCCESS")){
+			    FinalCode = AnsibleResultCodes.REQ_FAILURE.getValue();
+			}
+		    }
+		    catch(JSONException e){
+			ansibleResult.setStatusCode(AnsibleResultCodes.INVALID_RESPONSE.getValue());
+			ansibleResult.setStatusMessage(String.format("Error processing response message = %s from host %s", results.getString(host), host));
+			break;
+		    }
+		}
+
+		ansibleResult.setStatusCode(FinalCode);
+
+		// We return entire Results object as message
+		ansibleResult.setResults(results.toString());
+
+	    }
+	    else{
+		ansibleResult.setStatusCode(AnsibleResultCodes.INVALID_RESPONSE.getValue());
+		ansibleResult.setStatusMessage("Results not found in GET for response");
+	    }
+	    
+	    
+	}
+	catch(JSONException e){
+	    ansibleResult = new AnsibleResult(AnsibleResultCodes.INVALID_PAYLOAD.getValue(), "Error parsing response = " + Input + ". Error = " + e.getMessage(), "");
+	}
+
+
+	return ansibleResult;
+    }
+
+
+
+};    
+	    
+	    
+
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleResult.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleResult.java
new file mode 100644
index 0000000..3453a84
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleResult.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible.model;
+
+
+/* Simple class to store code and message returned by POST/GET to an Ansible Server */
+public class AnsibleResult{
+    private int StatusCode;
+    private String StatusMessage;
+    private String Results;
+    
+
+    public    AnsibleResult(){
+	StatusCode = -1;
+	StatusMessage = "UNKNOWN";
+	Results = "UNKNOWN";
+
+    }
+
+    // constructor
+    public AnsibleResult(int code, String message, String result){
+	StatusCode = code;
+	StatusMessage = message;
+	Results = result;
+    }
+
+    //*************************************************
+    // Various set methods
+    public void setStatusCode(int code){
+	this.StatusCode = code;
+    }
+
+    public void setStatusMessage(String message){
+	this.StatusMessage = message;
+    }
+
+    public void setResults(String results){
+	this.Results = results;
+    }
+    
+
+    void set(int code, String message, String results){
+	this.StatusCode = code;
+	this.StatusMessage = message;
+	this.Results = results;
+
+    }
+
+    //*********************************************
+    // Various get methods
+    public int getStatusCode(){
+	return this.StatusCode;
+    }
+
+    public String getStatusMessage(){
+	return this.StatusMessage;
+    }
+
+    public String getResults(){
+	return this.Results;
+    }
+
+
+}
+    
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleResultCodes.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleResultCodes.java
new file mode 100644
index 0000000..57b6792
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleResultCodes.java
@@ -0,0 +1,120 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible.model;
+
+
+import java.util.*;
+
+/**
+ * enum of the various codes that APP-C uses to resolve different
+ *  status of response from Ansible Server
+ **/
+
+public enum AnsibleResultCodes{
+
+    SUCCESS(400),
+    KEYSTORE_EXCEPTION(622),
+    CERTIFICATE_ERROR(610),
+    IO_EXCEPTION (611),
+    HOST_UNKNOWN(625),
+    USER_UNAUTHORIZED(613),
+    UNKNOWN_EXCEPTION(699),
+    SSL_EXCEPTION(697),
+    INVALID_PAYLOAD(698),
+    INVALID_RESPONSE(601),
+    PENDING(100),
+    REJECTED(101),
+    FINAL_SUCCESS(200),
+    REQ_FAILURE(401),
+    MESSAGE(1),
+    CODE(0),
+    INITRESPONSE(0),
+    FINALRESPONSE(1); 
+    
+    private final Set<Integer> InitCodes = new HashSet<Integer>(Arrays.asList(100, 101));
+    private final Set<Integer> FinalCodes = new HashSet<Integer>(Arrays.asList(200, 500));
+    private final ArrayList<Set<Integer>>CodeSets = new ArrayList<Set<Integer>>(Arrays.asList(InitCodes, FinalCodes));
+    
+    private  final Set<String> MessageSet = new HashSet<String>(Arrays.asList("PENDING", "FINISHED", "TERMINATED"));
+
+    private final int value;
+    
+    AnsibleResultCodes(int value){
+	this.value = value;
+    };
+
+
+    public int getValue(){
+	return this.value;
+    }
+
+
+    public boolean checkValidCode(int Type, int Code){
+	Set<Integer>CodeSet = CodeSets.get(Type);
+	if (CodeSet.contains(Code)){
+	    return true;
+	}
+	else{
+	    return false;
+	}
+    }
+
+
+    public String getValidCodes(int Type){
+	Set<Integer>CodeSet = CodeSets.get(Type);
+	
+	Iterator iter = CodeSet.iterator();
+	String ValidCodes = "[ ";
+	while(iter.hasNext()){
+	    ValidCodes = ValidCodes +  iter.next().toString() + ",";
+	}
+
+	ValidCodes = ValidCodes + "]";
+	return ValidCodes;
+    }
+
+
+    public boolean checkValidMessage(String Message){
+	if (MessageSet.contains(Message)){
+	    return true;
+	}
+	else{
+	    return false;
+	}
+    }
+
+
+
+    public String getValidMessages(){
+	Iterator iter = MessageSet.iterator();
+	String ValidMessage = "[ ";
+	while(iter.hasNext()){
+	    ValidMessage = ValidMessage +  iter.next() + ",";
+	}
+
+	ValidMessage = ValidMessage + "]";
+	return ValidMessage;
+    }
+
+
+};
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleServerEmulator.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleServerEmulator.java
new file mode 100644
index 0000000..6ee917c
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/java/org/openecomp/appc/adapter/ansible/model/AnsibleServerEmulator.java
@@ -0,0 +1,146 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+
+
+
+/* Class to emulate responses  from the Ansible Server that is compliant with the APP-C Ansible Server
+   Interface. Used for jUnit tests to verify code is working. In tests it can be used
+   as a replacement for methods from ConnectionBuilder class
+*/
+
+package org.openecomp.appc.adapter.ansible.model;
+
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import com.google.common.base.Strings;
+
+import org.json.JSONObject;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.appc.adapter.ansible.model.AnsibleResult;
+
+public class AnsibleServerEmulator {
+
+    
+    private String playbookName = "test_playbook.yaml";
+    private String TestId;
+
+    /**
+     * Method that emulates the response from an Ansible Server
+     when presented with a request to execute a playbook 
+     Returns an ansible object result. The response code is always the http code 200 (i.e connection successful)
+     payload is json string as would be sent back by Ansible Server
+    **/
+    
+    public AnsibleResult Post(String AgentUrl, String payload){
+	AnsibleResult result = new AnsibleResult() ;
+	
+	try{
+	    // Request must be a JSON object
+	    
+	    JSONObject message = new JSONObject(payload);
+	    if (message.isNull("Id")){
+		RejectRequest(result, "Must provide a valid Id");
+	    }
+	    else if(message.isNull("PlaybookName")){
+		RejectRequest(result, "Must provide a playbook Name");
+	    }
+	    else if(!message.getString("PlaybookName").equals(playbookName)){
+		RejectRequest(result, "Playbook " + message.getString("PlaybookName") + "  not found in catalog");
+	    }
+	    else{
+		AcceptRequest(result);
+	    }
+	}
+	catch (JSONException e){
+	    RejectRequest(result, e.getMessage());
+	}
+
+	return result;
+    }
+
+
+    /** Method to emulate response from an Ansible
+	Server when presented with a GET request
+	Returns an ansibl object result. The response code is always the http code 200 (i.e connection successful)
+	payload is json string as would be sent back by Ansible Server
+
+    **/
+    public AnsibleResult Get(String AgentUrl){
+
+	// Extract id
+	Pattern pattern = Pattern.compile(".*?\\?Id=(.*?)&Type.*");
+	Matcher matcher = pattern.matcher(AgentUrl);
+	String Id = "";
+	
+	if (matcher.find()){
+	    Id = matcher.group(1);
+	}
+
+	AnsibleResult get_result = new AnsibleResult();
+
+	JSONObject response = new JSONObject();
+	response.put("StatusCode", 200);
+	response.put("StatusMessage", "FINISHED");
+
+	JSONObject results = new JSONObject();
+
+	JSONObject vm_results = new JSONObject();
+	vm_results.put("StatusCode", 200);
+	vm_results.put("StatusMessage", "SUCCESS");
+	vm_results.put("Id", Id);
+	results.put("192.168.1.10", vm_results);
+	
+
+	response.put("Results", results);
+
+	get_result.setStatusCode(200);
+	get_result.setStatusMessage(response.toString());
+
+	return get_result;
+	
+    }
+
+    
+    private void RejectRequest(AnsibleResult result, String Message){
+	result.setStatusCode(200);
+	JSONObject response = new JSONObject();
+	response.put("StatusCode", AnsibleResultCodes.REJECTED.getValue());
+	response.put("StatusMessage", Message);
+	result.setStatusMessage(response.toString());
+	
+    }
+
+    private void AcceptRequest(AnsibleResult result){
+	result.setStatusCode(200);
+	JSONObject response = new JSONObject();
+	response.put("StatusCode", AnsibleResultCodes.PENDING.getValue());
+	response.put("StatusMessage", "PENDING");
+	result.setStatusMessage(response.toString());
+
+    }
+
+};
+    
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/resources/org/openecomp/appc/default.properties b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/resources/org/openecomp/appc/default.properties
new file mode 100644
index 0000000..f49f122
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/main/resources/org/openecomp/appc/default.properties
@@ -0,0 +1,46 @@
+###
+# ============LICENSE_START=======================================================
+# APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright (C) 2017 Amdocs
+# ================================================================================
+# 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.
+###
+
+#
+# Default properties for the APP-C TestService Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded 
+# to supply configuration options 
+org.openecomp.appc.bootstrap.file=appc.properties
+org.openecomp.appc.bootstrap.path=${user.home},/opt/opendaylight/current/properties
+
+appc.application.name=APPC
+
+#
+# Define the message resource bundle name to be loaded 
+org.openecomp.appc.resources=org.openecomp/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.openecomp.appc.provider.adaptor.name=org.openecomp.appc.appc_ansible_adapter
+
+
+# Default truststore path and password
+org.openecomp.appc.adapter.ansible.trustStore=/opt/opendaylight/tls-client/mykeystore.js
+org.openecomp.appc.adapter.ansible.trustStore.trustPasswd=changeit
+org.openecomp.appc.adapter.ansible.clientType=DEFAULT
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/adapter/ansible/impl/TestAnsibleAdapterImpl.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/adapter/ansible/impl/TestAnsibleAdapterImpl.java
new file mode 100644
index 0000000..ab76b70
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/adapter/ansible/impl/TestAnsibleAdapterImpl.java
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+package org.openecomp.appc.adapter.ansible.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openecomp.appc.Constants;
+import org.openecomp.appc.configuration.ConfigurationFactory;
+import org.openecomp.appc.exceptions.APPCException;
+import org.openecomp.sdnc.sli.SvcLogicContext;
+import org.openecomp.sdnc.sli.SvcLogicException;
+import org.slf4j.MDC;
+
+import org.openecomp.appc.adapter.ansible.AnsibleAdapter;
+import org.openecomp.appc.adapter.ansible.impl.AnsibleAdapterImpl;
+
+public class TestAnsibleAdapterImpl {
+
+
+    private AnsibleAdapterImpl adapter;
+    private String TestId;
+    private boolean testMode = true;
+    
+    @SuppressWarnings("nls")
+    @BeforeClass
+    public static void once() throws NoSuchFieldException, SecurityException, NoSuchMethodException {
+
+    }
+
+    @Before
+    public void setup() throws IllegalArgumentException, IllegalAccessException {
+	testMode = true;
+	adapter = new AnsibleAdapterImpl(testMode);
+    }
+    
+    @Test
+    public void testA() throws IOException, IllegalStateException, IllegalArgumentException,
+       APPCException {
+
+            Map<String, String> params = new HashMap<>();
+	    params.put("AgentUrl", "https://192.168.1.1");
+            params.put("User", "test");
+	    params.put("Password", "test");
+	    params.put("PlaybookName", "test_playbook.yaml");
+	    
+            SvcLogicContext svcContext = new SvcLogicContext();          
+            try{
+		String Pending = "100";
+		adapter.reqExec(params, svcContext);
+		String status=svcContext.getAttribute("org.openecomp.appc.adapter.ansible.result.code");
+		TestId=svcContext.getAttribute("org.openecomp.appc.adapter.ansible.result.Id");
+		System.out.println("Comparing " + Pending + " and " + status);
+		assertEquals(Pending,status);
+	    }
+	    catch(SvcLogicException e){
+	        String message  =svcContext.getAttribute("org.openecomp.appc.adapter.ansible.result.message");	
+		String status=svcContext.getAttribute("org.openecomp.appc.adapter.ansible.result.code");
+		fail(e.getMessage() + " Code = " + status);
+	    }
+	    catch(Exception e){
+		fail(e.getMessage() + " Unknown exception encountered " );
+            }
+		
+    }
+
+    @Test
+    public void testB() throws IOException, IllegalStateException, IllegalArgumentException,
+         APPCException {
+
+            Map<String, String> params = new HashMap<>();
+
+	    params.put("AgentUrl", "https://192.168.1.1");
+	    params.put("User", "test");
+	    params.put("Password", "test");
+	    params.put("Id", "100");
+
+            for (String ukey: params.keySet()){
+                  System.out.println(String.format("Ansible Parameter %s = %s", ukey, params.get(ukey)));
+	    }
+
+            SvcLogicContext svcContext = new SvcLogicContext();          
+
+            try{
+		adapter.reqExecResult(params, svcContext);
+		String status=svcContext.getAttribute("org.openecomp.appc.adapter.ansible.result.code");
+		assertEquals("400",status);
+	    }
+	    catch(SvcLogicException e){
+	        String message  = svcContext.getAttribute("org.openecomp.appc.adapter.ansible.result.message");	
+		String status=svcContext.getAttribute("org.openecomp.appc.adapter.ansible.result.code");
+		fail(e.getMessage()  + " Code = " + status);
+	    }
+	    catch(Exception e){
+		fail(e.getMessage() + " Unknown exception encountered " );
+            }
+	    
+    }
+
+}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/test/ExecutorHarness.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/test/ExecutorHarness.java
new file mode 100644
index 0000000..ade5476
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/test/ExecutorHarness.java
@@ -0,0 +1,180 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+
+package org.openecomp.appc.test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.appc.test.InterceptLogger;
+import org.openecomp.sdnc.sli.SvcLogicContext;
+import org.openecomp.sdnc.sli.SvcLogicJavaPlugin;
+
+/**
+ * This class is used as a test harness to wrap the call to an executor node.
+ */
+
+public class ExecutorHarness {
+
+    /**
+     * The executor to be tested
+     */
+    private SvcLogicJavaPlugin executor;
+
+    /**
+     * The collection of all exec methods found on the class
+     */
+    private Map<String, Method> methods;
+
+    /**
+     * The field of the class being tested that contains the reference to the logger to be used. This is modified to
+     * point to our interception logger for the test.
+     */
+    private Field contextLogger;
+
+    /**
+     * The interception logger that buffers all messages logged and allows us to look at them as part of the test case.
+     */
+    private InterceptLogger logger;
+
+    /**
+     * Create the harness and initialize it
+     * 
+     * @throws SecurityException
+     *             If a security manager, s, is present and any of the following conditions is met:
+     *             <ul>
+     *             <li>invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field</li>
+     *             <li>the caller's class loader is not the same as or an ancestor of the class loader for the current
+     *             class and invocation of s.checkPackageAccess() denies access to the package of this class</li>
+     *             </ul>
+     * @throws NoSuchFieldException
+     *             if a field with the specified name is not found.
+     * @throws IllegalAccessException
+     *             if this Field object is enforcing Java language access control and the underlying field is either
+     *             inaccessible or final.
+     * @throws IllegalArgumentException
+     *             if the specified object is not an instance of the class or interface declaring the underlying field
+     *             (or a subclass or implementor thereof), or if an unwrapping conversion fails.
+     */
+    @SuppressWarnings("nls")
+    public ExecutorHarness() throws NoSuchFieldException, SecurityException, IllegalArgumentException,
+                    IllegalAccessException {
+        methods = new HashMap<>();
+        new SvcLogicContext();
+
+        Class<?> contextClass = SvcLogicContext.class;
+        contextLogger = contextClass.getDeclaredField("LOG");
+        contextLogger.setAccessible(true);
+        logger = new InterceptLogger();
+        contextLogger.set(null, logger);
+    }
+
+    /**
+     * Convenience constructor
+     * 
+     * @param executor
+     *            The executor to be tested by the harness
+     * @throws SecurityException
+     *             If a security manager, s, is present and any of the following conditions is met:
+     *             <ul>
+     *             <li>invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field</li>
+     *             <li>the caller's class loader is not the same as or an ancestor of the class loader for the current
+     *             class and invocation of s.checkPackageAccess() denies access to the package of this class</li>
+     *             </ul>
+     * @throws NoSuchFieldException
+     *             if a field with the specified name is not found.
+     * @throws IllegalAccessException
+     *             if this Field object is enforcing Java language access control and the underlying field is either
+     *             inaccessible or final.
+     * @throws IllegalArgumentException
+     *             if the specified object is not an instance of the class or interface declaring the underlying field
+     *             (or a subclass or implementor thereof), or if an unwrapping conversion fails.
+     */
+    public ExecutorHarness(SvcLogicJavaPlugin executor) throws NoSuchFieldException, SecurityException,
+                    IllegalArgumentException, IllegalAccessException {
+        this();
+        setExecutor(executor);
+    }
+
+    /**
+     * @param executor
+     *            The java plugin class to be executed
+     */
+    public void setExecutor(SvcLogicJavaPlugin executor) {
+        this.executor = executor;
+        scanExecutor();
+    }
+
+    /**
+     * @return The java plugin class to be executed
+     */
+    public SvcLogicJavaPlugin getExecutor() {
+        return executor;
+    }
+
+    /**
+     * @return The set of all methods that meet the signature requirements
+     */
+    public List<String> getExecMethodNames() {
+        List<String> names = new ArrayList<>();
+        names.addAll(methods.keySet());
+        return names;
+    }
+
+    /**
+     * Returns an indication if the named method is a valid executor method that could be called from a DG execute node
+     * 
+     * @param methodName
+     *            The method name to be validated
+     * @return True if the method name meets the signature requirements, false if the method either does not exist or
+     *         does not meet the requirements.
+     */
+    public boolean isExecMethod(String methodName) {
+        return methods.containsKey(methodName);
+    }
+
+    /**
+     * This method scans the executor class hierarchy to locate all methods that match the required signature of the
+     * executor and records these methods in a map.
+     */
+    private void scanExecutor() {
+        methods.clear();
+        Class<?> executorClass = executor.getClass();
+        Method[] publicMethods = executorClass.getMethods();
+        for (Method method : publicMethods) {
+            if (method.getReturnType().equals(Void.class)) {
+                Class<?>[] paramTypes = method.getParameterTypes();
+                if (paramTypes.length == 2) {
+                    if (Map.class.isAssignableFrom(paramTypes[0])
+                        && SvcLogicContext.class.isAssignableFrom(paramTypes[1])) {
+                        methods.put(method.getName(), method);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/test/InterceptLogger.java b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/test/InterceptLogger.java
new file mode 100644
index 0000000..d6f3e6a
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/java/org/openecomp/appc/test/InterceptLogger.java
@@ -0,0 +1,452 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * 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.
+ */
+
+
+package org.openecomp.appc.test;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+
+/**
+ * This class is used as an intercept logger that can be used in testing to intercept and record all messages that are
+ * logged, thus allowing a junit test case to examine the log output and make assertions.
+ */
+public class InterceptLogger implements org.slf4j.Logger {
+
+    /**
+     * This inner class represents an intercepted log event
+     */
+    public class LogRecord {
+        private Level level;
+        private String message;
+        private long timestamp;
+        private Throwable t;
+
+        public LogRecord(Level level, String message) {
+            setLevel(level);
+            setTimestamp(System.currentTimeMillis());
+            setMessage(message);
+        }
+
+        public LogRecord(Level level, String message, Throwable t) {
+            this(level, message);
+            setThrowable(t);
+        }
+
+        /**
+         * @return the value of level
+         */
+        public Level getLevel() {
+            return level;
+        }
+
+        /**
+         * @return the value of message
+         */
+        public String getMessage() {
+            return message;
+        }
+
+        /**
+         * @return the value of timestamp
+         */
+        public long getTimestamp() {
+            return timestamp;
+        }
+
+        /**
+         * @param level
+         *            the value for level
+         */
+        public void setLevel(Level level) {
+            this.level = level;
+        }
+
+        /**
+         * @param message
+         *            the value for message
+         */
+        public void setMessage(String message) {
+            this.message = message;
+        }
+
+        /**
+         * @param timestamp
+         *            the value for timestamp
+         */
+        public void setTimestamp(long timestamp) {
+            this.timestamp = timestamp;
+        }
+
+        /**
+         * @return the value of t
+         */
+        public Throwable getThrowable() {
+            return t;
+        }
+
+        /**
+         * @param t
+         *            the value for t
+         */
+        public void setThrowable(Throwable t) {
+            this.t = t;
+        }
+
+    }
+
+    /**
+     * The list of all intercepted log events
+     */
+    private List<LogRecord> events;
+
+    /**
+     * Create the intercept logger
+     */
+    public InterceptLogger() {
+        events = new ArrayList<LogRecord>(1000);
+    }
+
+    /**
+     * @return Returns all intercepted log events
+     */
+    public List<LogRecord> getLogRecords() {
+        return events;
+    }
+
+    /**
+     * Clears all log events
+     */
+    public void clear() {
+        events.clear();
+    }
+
+    @Override
+    public void debug(Marker marker, String msg) {
+        debug(msg);
+    }
+
+    @Override
+    public void debug(Marker marker, String format, Object arg) {
+        debug(MessageFormat.format(format, arg));
+    }
+
+    @Override
+    public void debug(Marker marker, String format, Object... arguments) {
+        debug(MessageFormat.format(format, arguments));
+    }
+
+    @Override
+    public void debug(Marker marker, String format, Object arg1, Object arg2) {
+        debug(MessageFormat.format(format, arg1, arg2));
+    }
+
+    @Override
+    public void debug(Marker marker, String msg, Throwable t) {
+        debug(msg, t);
+    }
+
+    @Override
+    public void debug(String msg) {
+        events.add(new LogRecord(Level.DEBUG, msg));
+    }
+
+    @Override
+    public void debug(String format, Object arg) {
+        events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arg)));
+    }
+
+    @Override
+    public void debug(String format, Object... arguments) {
+        events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arguments)));
+    }
+
+    @Override
+    public void debug(String format, Object arg1, Object arg2) {
+        events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arg1, arg2)));
+    }
+
+    @Override
+    public void debug(String msg, Throwable t) {
+        events.add(new LogRecord(Level.DEBUG, msg, t));
+    }
+
+    @Override
+    public void error(Marker marker, String msg) {
+        error(msg);
+    }
+
+    @Override
+    public void error(Marker marker, String format, Object arg) {
+        error(format, arg);
+    }
+
+    @Override
+    public void error(Marker marker, String format, Object... arguments) {
+        error(format, arguments);
+    }
+
+    @Override
+    public void error(Marker marker, String format, Object arg1, Object arg2) {
+        error(format, arg1, arg2);
+    }
+
+    @Override
+    public void error(Marker marker, String msg, Throwable t) {
+        events.add(new LogRecord(Level.ERROR, msg, t));
+    }
+
+    @Override
+    public void error(String msg) {
+        events.add(new LogRecord(Level.ERROR, msg));
+    }
+
+    @Override
+    public void error(String format, Object arg) {
+        events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arg)));
+    }
+
+    @Override
+    public void error(String format, Object... arguments) {
+        events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arguments)));
+    }
+
+    @Override
+    public void error(String format, Object arg1, Object arg2) {
+        events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arg1, arg2)));
+    }
+
+    @Override
+    public void error(String msg, Throwable t) {
+        events.add(new LogRecord(Level.ERROR, msg, t));
+    }
+
+    @Override
+    public String getName() {
+        return null;
+    }
+
+    @Override
+    public void info(Marker marker, String msg) {
+        info(msg);
+    }
+
+    @Override
+    public void info(Marker marker, String format, Object arg) {
+        info(format, arg);
+    }
+
+    @Override
+    public void info(Marker marker, String format, Object... arguments) {
+        info(format, arguments);
+    }
+
+    @Override
+    public void info(Marker marker, String format, Object arg1, Object arg2) {
+        info(format, arg1, arg2);
+    }
+
+    @Override
+    public void info(Marker marker, String msg, Throwable t) {
+        events.add(new LogRecord(Level.INFO, msg, t));
+    }
+
+    @Override
+    public void info(String msg) {
+        events.add(new LogRecord(Level.INFO, msg));
+    }
+
+    @Override
+    public void info(String format, Object arg) {
+        events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arg)));
+    }
+
+    @Override
+    public void info(String format, Object... arguments) {
+        events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arguments)));
+    }
+
+    @Override
+    public void info(String format, Object arg1, Object arg2) {
+        events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arg1, arg2)));
+    }
+
+    @Override
+    public void info(String msg, Throwable t) {
+        events.add(new LogRecord(Level.INFO, msg, t));
+    }
+
+    @Override
+    public boolean isDebugEnabled() {
+        return true;
+    }
+
+    @Override
+    public boolean isDebugEnabled(Marker marker) {
+        return true;
+    }
+
+    @Override
+    public boolean isErrorEnabled() {
+        return true;
+    }
+
+    @Override
+    public boolean isErrorEnabled(Marker marker) {
+        return true;
+    }
+
+    @Override
+    public boolean isInfoEnabled() {
+        return true;
+    }
+
+    @Override
+    public boolean isInfoEnabled(Marker marker) {
+        return true;
+    }
+
+    @Override
+    public boolean isTraceEnabled() {
+        return true;
+    }
+
+    @Override
+    public boolean isTraceEnabled(Marker marker) {
+        return true;
+    }
+
+    @Override
+    public boolean isWarnEnabled() {
+        return true;
+    }
+
+    @Override
+    public boolean isWarnEnabled(Marker marker) {
+        return true;
+    }
+
+    @Override
+    public void trace(Marker marker, String msg) {
+        trace(msg);
+    }
+
+    @Override
+    public void trace(Marker marker, String format, Object arg) {
+        trace(format, arg);
+    }
+
+    @Override
+    public void trace(Marker marker, String format, Object... argArray) {
+        trace(format, argArray);
+    }
+
+    @Override
+    public void trace(Marker marker, String format, Object arg1, Object arg2) {
+        trace(format, arg1, arg2);
+    }
+
+    @Override
+    public void trace(Marker marker, String msg, Throwable t) {
+        trace(msg, t);
+    }
+
+    @Override
+    public void trace(String msg) {
+        events.add(new LogRecord(Level.TRACE, msg));
+    }
+
+    @Override
+    public void trace(String format, Object arg) {
+        events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arg)));
+    }
+
+    @Override
+    public void trace(String format, Object... arguments) {
+        events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arguments)));
+    }
+
+    @Override
+    public void trace(String format, Object arg1, Object arg2) {
+        events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arg1, arg2)));
+    }
+
+    @Override
+    public void trace(String msg, Throwable t) {
+        events.add(new LogRecord(Level.TRACE, msg, t));
+    }
+
+    @Override
+    public void warn(Marker marker, String msg) {
+        warn(msg);
+    }
+
+    @Override
+    public void warn(Marker marker, String format, Object arg) {
+        warn(format, arg);
+    }
+
+    @Override
+    public void warn(Marker marker, String format, Object... arguments) {
+        warn(format, arguments);
+    }
+
+    @Override
+    public void warn(Marker marker, String format, Object arg1, Object arg2) {
+        warn(format, arg1, arg2);
+    }
+
+    @Override
+    public void warn(Marker marker, String msg, Throwable t) {
+        events.add(new LogRecord(Level.WARN, msg, t));
+    }
+
+    @Override
+    public void warn(String msg) {
+        events.add(new LogRecord(Level.WARN, msg));
+    }
+
+    @Override
+    public void warn(String format, Object arg) {
+        events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arg)));
+    }
+
+    @Override
+    public void warn(String format, Object... arguments) {
+        events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arguments)));
+    }
+
+    @Override
+    public void warn(String format, Object arg1, Object arg2) {
+        events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arg1, arg2)));
+    }
+
+    @Override
+    public void warn(String msg, Throwable t) {
+        events.add(new LogRecord(Level.WARN, msg, t));
+    }
+}
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/resources/org/openecomp/appc/default.properties b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/resources/org/openecomp/appc/default.properties
new file mode 100644
index 0000000..774caa4
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-bundle/src/test/resources/org/openecomp/appc/default.properties
@@ -0,0 +1,109 @@
+###
+# ============LICENSE_START=======================================================
+# APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright (C) 2017 Amdocs
+# ================================================================================
+# 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.
+###
+
+#
+# Default properties for the APP-C Provider Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded 
+# to supply configuration options 
+org.openecomp.appc.bootstrap.file=appc.properties
+org.openecomp.appc.bootstrap.path=/opt/openecomp/appc/data/properties,${user.home},.
+
+appc.application.name=APPC
+
+#
+# Define the message resource bundle name to be loaded 
+org.openecomp.appc.resources=org/openecomp/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.openecomp.appc.provider.adaptor.name=org.openecomp.appc.appc_provider_adapter
+#
+# Set up the logging environment
+#
+org.openecomp.appc.logging.file=org/openecomp/appc/logback.xml
+org.openecomp.appc.logging.path=${user.home};etc;../etc
+org.openecomp.appc.logger=org.openecomp.appc
+org.openecomp.appc.security.logger=org.openecomp.appc.security
+#
+# The minimum and maximum provider/tenant context pool sizes.  Min=1 means that as soon 
+# as the provider/tenant is referenced a Context is opened and added to the pool.  Max=0 
+# means that the upper bound on the pool is unbounded. 
+org.openecomp.appc.provider.min.pool=1
+org.openecomp.appc.provider.max.pool=0
+
+#
+# The following properties are used to configure the retry logic for connection to the 
+# IaaS provider(s).  The retry delay property is the amount of time, in seconds, the
+# application waits between retry attempts.  The retry limit is the number of retries
+# that are allowed before the request is failed.
+org.openecomp.appc.provider.retry.delay = 30
+org.openecomp.appc.provider.retry.limit = 10
+
+#
+# The trusted hosts list for SSL access when a certificate is not provided.
+#
+provider.trusted.hosts=*
+#
+# The amount of time, in seconds, to wait for a server state change (start->stop, stop->start, etc).
+# If the server does not change state to a valid state within the alloted time, the operation 
+# fails.
+org.openecomp.appc.server.state.change.timeout=300
+#
+# The amount of time to wait, in seconds, between subsequent polls to the OpenStack provider 
+# to refresh the status of a resource we are waiting on.
+#
+org.openecomp.appc.openstack.poll.interval=20
+#
+# The connection information to connect to the provider we are using.  These properties 
+# are "structured" properties, in that the name is a compound name, where the nodes 
+# of the name can be ordered (1, 2, 3, ...).  All of the properties with the same ordinal
+# position are defining the same entity.  For example, provider1.type and provider1.name 
+# are defining the same provider, whereas provider2.name and provider2.type are defining
+# the values for a different provider.  Any number of providers can be defined in this 
+# way. 
+#
+
+# Don't change these 2 right now since they are hard coded in the DG
+#provider1.type=appc
+#provider1.name=appc
+
+#These you can change
+#provider1.identity=appc
+#provider1.tenant1.name=appc
+#provider1.tenant1.userid=appc
+#provider1.tenant1.password=appc
+
+# After a change to the provider make sure to recheck these values with an api call to provider1.identity/tokens
+test.expected-regions=1
+test.expected-endpoints=1
+
+#Your OpenStack IP
+#test.ip=192.168.1.2
+# Your OpenStack Platform's Keystone Port (default is 5000)
+#test.port=5000
+#test.tenantid=abcde12345fghijk6789lmnopq123rst
+#test.vmid=abc12345-1234-5678-890a-abcdefg12345
+# Port 8774 below is default port for OpenStack's Nova API Service
+#test.url=http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345
+
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/.gitignore b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/.gitignore
new file mode 100644
index 0000000..615a76b
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/bin/
+/classes/
+/.settings/
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/pom.xml b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/pom.xml
new file mode 100644
index 0000000..2a7ef63
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2017 Amdocs
+  ================================================================================
+  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>
+    <artifactId>appc-ansible-adapter</artifactId>
+    <groupId>org.openecomp.appc</groupId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>appc-ansible-adapter-features</artifactId>
+  <name>Ansible Adaptor - Features</name>
+
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.openecomp.appc</groupId>
+      <artifactId>appc-ansible-adapter-bundle</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.mdsal</groupId>
+      <artifactId>features-mdsal</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+
+    <!-- dependency for opendaylight-karaf-empty for use by testing -->
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>opendaylight-karaf-empty</artifactId>
+      <type>zip</type>
+    </dependency>
+
+<!--     <dependency> -->
+<!--       Required for launching the feature tests -->
+<!--       <groupId>org.opendaylight.yangtools</groupId> -->
+<!--       <artifactId>features-test</artifactId> -->
+<!--       <scope>test</scope> -->
+<!--     </dependency> -->
+
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-yangtools</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <filtering>true</filtering>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>filter</id>
+            <goals>
+              <goal>resources</goal>
+            </goals>
+            <phase>generate-resources</phase>
+          </execution>
+        </executions>
+      </plugin>
+      <!-- launches the feature test, which validates that your karaf feature 
+        can be installed inside of a karaf container. It doesn't validate that your 
+        functionality works correctly, just that you have all of the dependent bundles 
+        defined correctly. -->
+      <!-- <plugin> -->
+      <!-- <groupId>org.apache.maven.plugins</groupId> -->
+      <!-- <artifactId>maven-surefire-plugin</artifactId> -->
+      <!-- <version>2.16</version> -->
+      <!-- <configuration> -->
+      <!-- <systemPropertyVariables> -->
+      <!-- <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId> -->
+      <!-- <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId> -->
+      <!-- <karaf.distro.version>${odl.karaf.empty.distro.version}</karaf.distro.version> -->
+      <!-- </systemPropertyVariables> -->
+      <!-- <dependenciesToScan> -->
+      <!-- <dependency>org.opendaylight.yangtools:features-test</dependency> -->
+      <!-- </dependenciesToScan> -->
+      <!-- </configuration> -->
+      <!-- </plugin> -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-artifacts</id>
+            <goals>
+              <goal>attach-artifact</goal>
+            </goals>
+            <phase>package</phase>
+            <configuration>
+              <artifacts>
+                <artifact>
+                  <file>${project.build.directory}/classes/${features.file}</file>
+                  <type>xml</type>
+                  <classifier>features</classifier>
+                </artifact>
+              </artifacts>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/src/main/resources/features.xml b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/src/main/resources/features.xml
new file mode 100644
index 0000000..2a5873e
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-features/src/main/resources/features.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2017 Amdocs
+  ================================================================================
+  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.
+  -->
+
+
+<features name="appc-ansible-adapter-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">     
+
+     <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.features.version}/xml/features</repository>
+    
+    <feature name='appc-ansible-adapter' description="appc-ansible-adapter" version='${project.version}'>
+        <feature version="${broker-mdsal.version}">odl-mdsal-broker</feature>
+        <feature>sdnc-sli</feature>
+         <bundle dependency="true">mvn:org.openecomp.appc/appc-common/${project.version}</bundle>
+        <bundle>mvn:org.openecomp.appc/appc-ansible-adapter-bundle/${project.version}</bundle>
+    </feature>
+
+</features>
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/pom.xml b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/pom.xml
new file mode 100644
index 0000000..06ca94f
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2017 Amdocs
+  ================================================================================
+  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>
+        <artifactId>appc-ansible-adapter</artifactId>
+        <groupId>org.openecomp.appc</groupId>
+        <version>1.1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>appc-ansible-adapter-installer</artifactId>
+    <name>Ansible Adapter - Karaf Installer</name>
+    <packaging>pom</packaging>
+    <properties>
+        <application.name>appc-ansible-adapter</application.name>
+        <features.boot>appc-ansible-adapter</features.boot>
+        <features.repositories>mvn:org.openecomp.appc/appc-ansible-adapter-features/${project.version}/xml/features</features.repositories>
+        <include.transitive.dependencies>false</include.transitive.dependencies>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.openecomp.appc</groupId>
+            <artifactId>appc-ansible-adapter-features</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
+            <exclusions>
+                <exclusion>
+                    <groupId>*</groupId>
+                    <artifactId>*</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.openecomp.appc</groupId>
+            <artifactId>appc-ansible-adapter-bundle</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>maven-repo-zip</id>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                        	<appendAssemblyId>false</appendAssemblyId>
+                            <attach>false</attach>
+                            <finalName>stage/${application.name}-${project.version}</finalName>
+                            <descriptors>
+                                <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+                            </descriptors>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>installer-zip</id>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                        	<appendAssemblyId>false</appendAssemblyId>
+                            <attach>true</attach>
+                            <finalName>${application.name}-${project.version}</finalName>
+                            <descriptors>
+                                <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+                            </descriptors>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-dependencies</id>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <phase>prepare-package</phase>
+                        <configuration>
+                            <transitive>false</transitive>
+                            <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>true</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <useRepositoryLayout>true</useRepositoryLayout>
+                            <addParentPoms>false</addParentPoms>
+                            <copyPom>false</copyPom>
+                            <excludeGroupIds>org.opendaylight</excludeGroupIds>
+                            <scope>provided</scope>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-version</id>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <!-- here the phase you need -->
+                        <phase>validate</phase>
+                        <configuration>
+                            <outputDirectory>${basedir}/target/stage</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>src/main/resources/scripts</directory>
+                                    <includes>
+                                        <include>install-feature.sh</include>
+                                    </includes>
+                                    <filtering>true</filtering>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/assembly/assemble_installer_zip.xml b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 0000000..4ecf625
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,60 @@
+<!--
+  ============LICENSE_START=======================================================
+  APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2017 Amdocs
+  ================================================================================
+  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.
+  -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+	<id>adapter</id>
+	<formats>
+		<format>zip</format>
+	</formats>
+
+	<!--  we want "system" and related files right at the root level
+		  as this file is suppose to be unzip on top of a karaf
+		  distro. -->
+	<includeBaseDirectory>false</includeBaseDirectory>
+
+	<fileSets>
+		<fileSet>
+			<directory>target/stage/</directory>
+			<outputDirectory>${application.name}</outputDirectory>
+			<fileMode>755</fileMode>
+			<includes>
+				<include>*.sh</include>
+			</includes>
+		</fileSet>
+		<fileSet>
+			<directory>target/stage/</directory>
+			<outputDirectory>${application.name}</outputDirectory>
+			<fileMode>644</fileMode>
+			<excludes>
+				<exclude>*.sh</exclude>
+			</excludes>
+		</fileSet>
+	</fileSets>
+
+
+
+</assembly>
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 0000000..4d672a3
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,48 @@
+<!--
+  ============LICENSE_START=======================================================
+  APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2017 Amdocs
+  ================================================================================
+  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.
+  -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+	<id>adapter</id>
+	<formats>
+		<format>zip</format>
+	</formats>
+
+	<!--  we want "system" and related files right at the root level
+		  as this file is suppose to be unzip on top of a karaf
+		  distro. -->
+	<includeBaseDirectory>false</includeBaseDirectory>
+
+	<fileSets>
+		<fileSet>
+			<directory>target/assembly/</directory>
+			<outputDirectory>.</outputDirectory>
+			<excludes>
+			</excludes>
+		</fileSet>
+	</fileSets>
+
+</assembly>
diff --git a/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/main/resources/scripts/install-feature.sh b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 0000000..6892eea
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/appc-ansible-adapter-installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,41 @@
+###
+# ============LICENSE_START=======================================================
+# APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright (C) 2017 Amdocs
+# ================================================================================
+# 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.
+###
+
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+	unzip -n -d ${ODL_HOME} ${REPOZIP}
+else
+	echo "ERROR : repo zip ($REPOZIP) not found"
+	exit 1
+fi
+
+${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot}
diff --git a/appc-adapters/appc-ansible-adapter/pom.xml b/appc-adapters/appc-ansible-adapter/pom.xml
new file mode 100644
index 0000000..9520020
--- /dev/null
+++ b/appc-adapters/appc-ansible-adapter/pom.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  APPC
+  ================================================================================
+  Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+  Copyright (C) 2017 Amdocs
+  ================================================================================
+  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/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.openecomp.appc</groupId>
+    <artifactId>appc-adapters</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>appc-ansible-adapter</artifactId>
+  <name>Appc Ansible Adapter</name>
+  <description>Abstractions to interact with Ansible server via REST</description>
+  <packaging>pom</packaging>
+
+  <build>
+    <plugins>
+
+     <!-- Black duck plugin Not required for regular builds 
+     <plugin> <groupId>com.blackducksoftware.integration</groupId> <artifactId>hub-maven-plugin</artifactId>
+           <version>1.4.0</version> <inherited>false</inherited> <configuration> <hubProjectName>${project.name}</hubProjectName>
+           <outputDirectory>${project.basedir}</outputDirectory> <deployHubBdio>false</deployHubBdio>
+           </configuration> <extensions>true</extensions>
+           <executions> 
+		<execution> 
+			<id>create-bdio-file</id> 
+			<phase>package</phase>
+           		<goals> 
+				<goal>createHubOutput</goal> 
+			</goals> 
+		</execution> 
+	    </executions> 
+
+     </plugin>
+     -->
+
+    </plugins>
+  </build>
+
+  <reporting>
+    <plugins>
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <configuration>
+          <additionalDependencies>
+            <additionalDependency>
+              <groupId>org.slf4j</groupId>
+              <artifactId>slf4j-api</artifactId>
+              <version>${slf4j.version}</version>
+            </additionalDependency>
+            <additionalDependency>
+              <groupId>org.antlr</groupId>
+              <artifactId>antlr4</artifactId>
+              <version>${antlr.version}</version>
+            </additionalDependency>
+            <additionalDependency>
+              <groupId>org.antlr</groupId>
+              <artifactId>antlr4-runtime</artifactId>
+              <version>4.3</version>
+            </additionalDependency>
+          </additionalDependencies>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>javadoc-no-fork</report>
+              <report>test-javadoc-no-fork</report>
+            </reports>
+          </reportSet>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+              <report>test-aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>2.3</version>
+        <reportSets>
+          <reportSet>
+            <id>aggregate</id>
+            <reports>
+              <report>aggregate</report>
+              <report>test-aggregate</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changelog-plugin</artifactId>
+        <version>2.3</version>
+        <reportSets>
+          <reportSet>
+            <id>dual-report</id>
+            <configuration>
+              <type>range</type>
+              <range>30</range>
+            </configuration>
+            <reports>
+              <report>changelog</report>
+              <report>file-activity</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>taglist-maven-plugin</artifactId>
+        <version>2.4</version>
+      </plugin>
+    </plugins>
+
+  </reporting>
+
+  <dependencyManagement>
+    <dependencies>
+
+      <dependency>
+        <groupId>org.openecomp.appc</groupId>
+        <artifactId>appc-ansible-adapter-features</artifactId>
+        <classifier>features</classifier>
+        <type>xml</type>
+        <version>${project.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.openecomp.appc</groupId>
+        <artifactId>appc-ansible-adapter-provider</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+
+     <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>4.11</version>
+        <scope>test</scope>
+    </dependency>
+
+
+    </dependencies>
+
+
+  </dependencyManagement>
+
+  <pluginRepositories>
+   <!-- Black Duck plugin dependencies -->
+        <pluginRepository>
+            <id>JCenter</id>
+            <name>JCenter Repository</name>
+            <url>http://jcenter.bintray.com</url>
+        </pluginRepository>
+
+  </pluginRepositories>
+
+  <modules>
+    <module>appc-ansible-adapter-bundle</module>
+    <module>appc-ansible-adapter-features</module>
+    <module>appc-ansible-adapter-installer</module>
+  </modules>
+</project>
diff --git a/appc-adapters/pom.xml b/appc-adapters/pom.xml
index 0e4e12c..2de68e4 100644
--- a/appc-adapters/pom.xml
+++ b/appc-adapters/pom.xml
@@ -18,5 +18,6 @@
 		<module>appc-netconf-adapter</module>
 		<module>appc-ssh-adapter</module>
 		<module>appc-rest-healthcheck-adapter</module>
+		<module>appc-ansible-adapter</module>
 	</modules>
 </project>