Implementing rest utilities to invoke Docker.

Project: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/commit/9f0eb33c
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/tree/9f0eb33c
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/diff/9f0eb33c

Branch: refs/heads/docker
Commit: 9f0eb33cd40e56f4294afb9d6e832f44dd0a7f97
Parents: fbc9e2a
Author: Nadeesh Dilanga <[email protected]>
Authored: Wed Jun 15 03:42:37 2016 -0400
Committer: Nadeesh Dilanga <[email protected]>
Committed: Wed Jun 15 03:42:37 2016 -0400

----------------------------------------------------------------------
 .../activities/docker/DockerActivity.java       |  22 ++-
 .../taverna/activities/docker/DockerConfig.java |  77 +++++++++
 .../activities/docker/DockerHttpResponse.java   |  49 ++++++
 .../taverna/activities/docker/RESTUtil.java     | 157 +++++++++++++++++++
 .../docker/test/TestCreateContainer.java        |  43 +++++
 5 files changed, 343 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/9f0eb33c/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerActivity.java
----------------------------------------------------------------------
diff --git 
a/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerActivity.java
 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerActivity.java
index 2760546..c81e9de 100644
--- 
a/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerActivity.java
+++ 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerActivity.java
@@ -19,6 +19,8 @@
 package org.apache.taverna.activities.docker;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.taverna.invocation.InvocationContext;
+import org.apache.taverna.reference.ReferenceService;
 import org.apache.taverna.reference.T2Reference;
 import 
org.apache.taverna.workflowmodel.processor.activity.AbstractAsynchronousActivity;
 import 
org.apache.taverna.workflowmodel.processor.activity.ActivityConfigurationException;
@@ -31,18 +33,28 @@ import java.util.Map;
  */
 public class DockerActivity extends AbstractAsynchronousActivity<JsonNode> {
 
-    @Override
-    public void configure(JsonNode jsonNode) throws 
ActivityConfigurationException {
+    private JsonNode activityConfig;
 
+    @Override
+    public void configure(JsonNode activityConfig) throws 
ActivityConfigurationException {
+      this.activityConfig = activityConfig;
     }
 
     @Override
     public JsonNode getConfiguration() {
-        return null;
+        return activityConfig;
     }
 
     @Override
-    public void executeAsynch(Map<String, T2Reference> map, 
AsynchronousActivityCallback asynchronousActivityCallback) {
-
+    public void executeAsynch(Map<String, T2Reference> map, final 
AsynchronousActivityCallback callback) {
+        callback.requestRun(new Runnable() {
+            @Override
+            public void run() {
+                InvocationContext context = callback.getContext();
+                ReferenceService referenceService = 
context.getReferenceService();
+                //TODO invoke container remote api and set final response 
result to callback.receiveResult();
+
+            }
+        });
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/9f0eb33c/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerConfig.java
----------------------------------------------------------------------
diff --git 
a/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerConfig.java
 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerConfig.java
new file mode 100644
index 0000000..30d12c5
--- /dev/null
+++ 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerConfig.java
@@ -0,0 +1,77 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.taverna.activities.docker;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+public class DockerConfig {
+
+    /**
+     * Hold the hostname of the docker container.
+     */
+    private String containerHost;
+
+    /**
+     * Remote REST API port exposed by Docker
+     */
+    private int remoteAPIPort = 443;
+
+    /**
+     * JSON payload to invoke create container REST API.
+     */
+    private JsonNode createContainerPayload;
+
+    /**
+     * Complete HTTP URL for create container
+     */
+    private final String createContainerURL;
+
+    /**
+     * Docker remote REST resource path for creating a container
+     */
+    public static final String CREATE_CONTAINER_RESOURCE_PATH = 
"/containers/create";
+
+    /**
+     * Transport protocol
+     */
+    public static final String PROTOCOL = "https";
+
+    public DockerConfig(String containerHost, int remoteAPIPort, JsonNode 
createContainerPayload) {
+        this.containerHost = containerHost;
+        this.remoteAPIPort = remoteAPIPort;
+        this.createContainerPayload = createContainerPayload;
+        this.createContainerURL = PROTOCOL + "://" + containerHost +  ":" + 
remoteAPIPort + CREATE_CONTAINER_RESOURCE_PATH ;
+    }
+
+    public String getContainerHost() {
+        return containerHost;
+    }
+
+    public int getRemoteAPIPort() {
+        return remoteAPIPort;
+    }
+
+    public JsonNode getCreateContainerPayload() {
+        return createContainerPayload;
+    }
+
+    public String getCreateContainerURL() {
+        return createContainerURL;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/9f0eb33c/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerHttpResponse.java
----------------------------------------------------------------------
diff --git 
a/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerHttpResponse.java
 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerHttpResponse.java
new file mode 100644
index 0000000..336bca9
--- /dev/null
+++ 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/DockerHttpResponse.java
@@ -0,0 +1,49 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.docker;
+
+import org.apache.http.Header;
+
+public class DockerHttpResponse {
+
+    private Header[] headers;
+
+    private int statusCode;
+
+    private String body;
+
+    public DockerHttpResponse(Header[] headers, int statusCode, String body) {
+        this.headers = headers;
+        this.statusCode = statusCode;
+        this.body = body;
+    }
+
+    public Header[] getHeaders() {
+        return headers;
+    }
+
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    public String getBody() {
+        return body;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/9f0eb33c/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/RESTUtil.java
----------------------------------------------------------------------
diff --git 
a/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/RESTUtil.java
 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/RESTUtil.java
index 460f275..99fff51 100644
--- 
a/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/RESTUtil.java
+++ 
b/taverna-docker-activity/src/main/java/org/apache/taverna/activities/docker/RESTUtil.java
@@ -19,5 +19,162 @@
 
 package org.apache.taverna.activities.docker;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.SingleClientConnManager;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.ssl.SSLContexts;
+import org.apache.log4j.Logger;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.security.cert.CertificateException;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
 public class RESTUtil {
+
+    /**
+     * Http header name for content type
+     */
+    private static final String CONTENT_TYPE = "Content-Type";
+
+    /**
+     * Http content type value for JSON messages.
+     */
+    private static final String JSON_CONTENT_TYPE = "application/json";
+
+    /**
+     * Logger
+     */
+    private static Logger LOG = Logger.getLogger(RESTUtil.class);
+
+
+    public static boolean createContainer(DockerConfig dockerConfig) {
+        try {
+            URL url = new URL(dockerConfig.getCreateContainerURL());
+            org.apache.http.conn.ssl.SSLSocketFactory factory = new 
org.apache.http.conn.ssl.SSLSocketFactory(SSLContext.getDefault());
+            Scheme https = new Scheme(DockerConfig.PROTOCOL,factory , 
url.getPort());
+            SchemeRegistry schemeRegistry = new SchemeRegistry();
+            schemeRegistry.register(https);
+            ClientConnectionManager connectionManager = new 
SingleClientConnManager(null, schemeRegistry);
+            Map<String,String> headers = new HashMap<String,String>();
+            headers.put(CONTENT_TYPE, JSON_CONTENT_TYPE);
+            DockerHttpResponse response = 
doPost(connectionManager,dockerConfig.getCreateContainerURL(), headers, 
dockerConfig.getCreateContainerPayload());
+            if(response.getStatusCode() == 201){
+                JsonNode node = getJson(response.getBody());
+                LOG.info(String.format("Successfully created Docker container 
id: %s ", getDockerId(node)));
+                return true;
+            }
+
+        } catch (MalformedURLException e1) {
+            LOG.error(String.format("Malformed URL encountered. This can be 
due to invalid URL parts. " +
+                            "Docker Host=%s, Port=%d and Resource Path=%s",
+                    dockerConfig.getContainerHost(),
+                    dockerConfig.getRemoteAPIPort(),
+                    DockerConfig.CREATE_CONTAINER_RESOURCE_PATH), e1);
+        } catch (NoSuchAlgorithmException e2) {
+            LOG.error("Failed to create SSLContext for invoking the REST 
service over https.", e2);
+        } catch (IOException e3) {
+            LOG.error("Error occurred while reading the docker http response", 
e3);
+        }
+        return false;
+    }
+
+    private static DockerHttpResponse doPost(ClientConnectionManager 
connectionManager, String url, Map<String, String> headers, JsonNode payload) {
+        DefaultHttpClient httpClient = null;
+        CloseableHttpResponse response = null;
+        DockerHttpResponse dockerResponse = null;
+        HttpPost httpPost = null;
+        try {
+            httpPost = new HttpPost(url);
+            HttpEntity entity = new StringEntity(payload.toString());
+            httpPost.setEntity(entity);
+            for (Map.Entry<String, String> entry : headers.entrySet()) {
+                httpPost.setHeader(new BasicHeader(entry.getKey(), 
entry.getValue()));
+            }
+            httpClient = new DefaultHttpClient(connectionManager, null);
+            response = httpClient.execute(httpPost);
+            if (response != null) {
+                dockerResponse = new 
DockerHttpResponse(response.getAllHeaders(), 
response.getStatusLine().getStatusCode(),readBody(response.getEntity()).toString());
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            LOG.error("Failed to complete Http POST invocation", e);
+            dockerResponse = new DockerHttpResponse(new Header[]{new 
BasicHeader(
+                    CONTENT_TYPE, JSON_CONTENT_TYPE)},
+                    500,
+                    "{\"error\":\"internal server error\", \"message\":\""+ 
e.getMessage() +"\"}");
+        } finally {
+            if(httpPost != null){
+              httpPost.releaseConnection();
+            }
+            if (httpClient != null) {
+                httpClient.close();
+            }
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException ignore) {}
+            }
+        }
+      return dockerResponse;
+    }
+
+    private static StringBuilder readBody(HttpEntity entity) throws 
IOException {
+        String charset = null;
+        String contentType = entity.getContentType().getValue().toLowerCase();
+        String[] contentTypeParts = contentType.split(";");
+        for (String contentTypePart : contentTypeParts) {
+            contentTypePart = contentTypePart.trim();
+            if (contentTypePart.startsWith("charset=")) {
+                charset = contentTypePart.substring("charset=".length());
+            }
+        }
+        BufferedReader reader = new BufferedReader(new 
InputStreamReader(entity.getContent(), charset != null ? charset : "UTF-8"));
+        String str;
+        StringBuilder responseBuilder = new StringBuilder();
+        while ((str = reader.readLine()) != null) {
+            responseBuilder.append(str + "\n");
+         }
+        return responseBuilder;
+    }
+
+    private static JsonNode getJson(String s) throws IOException {
+        ObjectMapper mapper = new ObjectMapper();
+        return mapper.readTree(s);
+    }
+
+    private static String getDockerId(JsonNode node){
+        String dockerId = null;
+        Iterator<JsonNode> itr = node.elements();
+        while(itr.hasNext()){
+            JsonNode child = itr.next();
+            if("id".equalsIgnoreCase(child.textValue())){
+                dockerId =  child.textValue();
+                break;
+            }
+        }
+        return dockerId;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/9f0eb33c/taverna-docker-activity/src/test/java/org/apache/taverna/activities/docker/test/TestCreateContainer.java
----------------------------------------------------------------------
diff --git 
a/taverna-docker-activity/src/test/java/org/apache/taverna/activities/docker/test/TestCreateContainer.java
 
b/taverna-docker-activity/src/test/java/org/apache/taverna/activities/docker/test/TestCreateContainer.java
new file mode 100644
index 0000000..bd68abb
--- /dev/null
+++ 
b/taverna-docker-activity/src/test/java/org/apache/taverna/activities/docker/test/TestCreateContainer.java
@@ -0,0 +1,43 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.docker.test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.taverna.activities.docker.DockerConfig;
+import org.apache.taverna.activities.docker.RESTUtil;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class TestCreateContainer{
+
+//    @Test
+//    public void testCreateContainer(){
+//        try {
+//            String payload = "{\"Hostname\":\"foo.com\", \"User\":\"foo\", 
\"Memory\":0, \"MemorySwap\":0,\"AttachStdin\":false, 
\"AttachStdout\":true,\"Attachstderr\":true,\"PortSpecs\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,
 \"Cmd\":[\"date\"], 
\"Image\":\"ubuntu\",\"Tag\":\"latest\",\"Volumes\":{\"/tmp\":{} 
},\"WorkingDir\":\"\",\"DisableNetwork\":false, \"ExposedPorts\":{\"22/tcp\": 
{} }}";
+//            DockerConfig config = new DockerConfig("192.168.99.100",2376, 
new ObjectMapper().readTree(payload));
+//            boolean res = RESTUtil.createContainer(config);
+//            System.out.println(">>>" + res);
+//        } catch (IOException e) {
+//            e.printStackTrace();
+//        }
+//
+//    }
+}

Reply via email to