You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by im...@apache.org on 2015/06/15 14:43:15 UTC
[10/12] stratos git commit: Migrating Kubernetes API client to Fabric8
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/Volume.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/Volume.java b/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/Volume.java
deleted file mode 100644
index 91b59b0..0000000
--- a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/Volume.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.stratos.kubernetes.client.model;
-
-public class Volume {
-
- private String name;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "Volume [name=" + name + "]";
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/VolumeMount.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/VolumeMount.java b/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/VolumeMount.java
deleted file mode 100644
index 1534988..0000000
--- a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/model/VolumeMount.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.stratos.kubernetes.client.model;
-
-public class VolumeMount {
-
- private String name;
- private String mountPath;
- private boolean readOnly;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getMountPath() {
- return mountPath;
- }
-
- public void setMountPath(String mountPath) {
- this.mountPath = mountPath;
- }
-
- public boolean isReadOnly() {
- return readOnly;
- }
-
- public void setReadOnly(boolean readOnly) {
- this.readOnly = readOnly;
- }
-
- @Override
- public String toString() {
- return "VolumeMount [name=" + name + ", mountPath=" + mountPath
- + ", readOnly=" + readOnly + "]";
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/HttpResponse.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/HttpResponse.java b/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/HttpResponse.java
deleted file mode 100644
index 6a287c1..0000000
--- a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/HttpResponse.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.stratos.kubernetes.client.rest;
-
-/**
- * Holds the data extracted from a HttpResponse.
- */
-public class HttpResponse {
-
- private int statusCode;
- private String content;
- private String reason;
- private KubernetesResponse kubernetesResponse;
-
- public int getStatusCode() {
- return statusCode;
- }
-
- public void setStatusCode(int statusCode) {
- this.statusCode = statusCode;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public String getReason() {
- return reason;
- }
-
- public void setReason(String reason) {
- this.reason = reason;
- }
-
- public KubernetesResponse getKubernetesResponse() {
- return kubernetesResponse;
- }
-
- public void setKubernetesResponse(KubernetesResponse kubernetesResponse) {
- this.kubernetesResponse = kubernetesResponse;
- }
-
- @Override
- public String toString() {
- return "HttpResponse [statusCode=" + statusCode + ", content=" + content
- + ", reason=" + reason + ", kubernetesResponse=" + kubernetesResponse + "]";
- }
-}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponse.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponse.java b/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponse.java
deleted file mode 100644
index e700a1c..0000000
--- a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponse.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.stratos.kubernetes.client.rest;
-
-/**
- * Kubernetes response.
- */
-public class KubernetesResponse {
- private String kind;
- private String creationTimestamp;
- private String selfLink;
- private String apiVersion;
- private String status;
- private String message;
- private int code;
-
- public String getKind() {
- return kind;
- }
-
- public void setKind(String kind) {
- this.kind = kind;
- }
-
- public String getCreationTimestamp() {
- return creationTimestamp;
- }
-
- public void setCreationTimestamp(String creationTimestamp) {
- this.creationTimestamp = creationTimestamp;
- }
-
- public String getSelfLink() {
- return selfLink;
- }
-
- public void setSelfLink(String selfLink) {
- this.selfLink = selfLink;
- }
-
- public String getApiVersion() {
- return apiVersion;
- }
-
- public void setApiVersion(String apiVersion) {
- this.apiVersion = apiVersion;
- }
-
- public String getStatus() {
- return status;
- }
-
- public void setStatus(String status) {
- this.status = status;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public int getCode() {
- return code;
- }
-
- public void setCode(int code) {
- this.code = code;
- }
-}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponseHandler.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponseHandler.java b/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponseHandler.java
deleted file mode 100644
index 6530a09..0000000
--- a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/KubernetesResponseHandler.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.stratos.kubernetes.client.rest;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonSyntaxException;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.http.HttpEntity;
-import org.apache.http.StatusLine;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.ResponseHandler;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-/**
- * Handles a HttpResponse and returns a {@link HttpResponse}
- */
-public class KubernetesResponseHandler implements ResponseHandler<HttpResponse> {
- private static final Log log = LogFactory.getLog(KubernetesResponseHandler.class);
-
- @Override
- public HttpResponse handleResponse(org.apache.http.HttpResponse response) throws ClientProtocolException,
- IOException {
- StatusLine statusLine = response.getStatusLine();
- HttpEntity entity = response.getEntity();
- if (entity == null) {
- throw new ClientProtocolException("Response contains no content");
- }
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- (response.getEntity().getContent())));
-
- String output;
- String result = "";
-
- while ((output = reader.readLine()) != null) {
- result += output;
- }
-
- HttpResponse httpResponse = new HttpResponse();
- httpResponse.setStatusCode(statusLine.getStatusCode());
- httpResponse.setContent(result);
- if (StringUtils.isNotBlank(result) && (isJson(result))) {
- httpResponse.setKubernetesResponse(parseKubernetesResponse(result));
- }
- httpResponse.setReason(statusLine.getReasonPhrase());
-
- if (log.isDebugEnabled()) {
- log.debug("Extracted Kubernetes Response: " + httpResponse.toString());
- }
-
- return httpResponse;
- }
-
- private boolean isJson(String content) {
- try {
- GsonBuilder gsonBuilder = new GsonBuilder();
- Gson gson = gsonBuilder.create();
- gson.fromJson(content, Object.class);
- return true;
- } catch (JsonSyntaxException ignore) {
- return false;
- }
- }
-
- private KubernetesResponse parseKubernetesResponse(String result) {
- try {
- GsonBuilder gsonBuilder = new GsonBuilder();
- Gson gson = gsonBuilder.create();
- return gson.fromJson(result, KubernetesResponse.class);
- } catch (Exception e) {
- log.error("Could not parse kubernetes api response", e);
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/RestClient.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/RestClient.java b/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/RestClient.java
deleted file mode 100644
index 271f38c..0000000
--- a/components/org.apache.stratos.kubernetes.client/src/main/java/org/apache/stratos/kubernetes/client/rest/RestClient.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * 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.stratos.kubernetes.client.rest;
-
-import org.apache.http.client.methods.*;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.PoolingClientConnectionManager;
-
-import java.net.URI;
-
-public class RestClient {
-
- private DefaultHttpClient httpClient;
-
- public RestClient() {
- PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
- // Increase max total connection to 200
- cm.setMaxTotal(200);
- // Increase default max connection per route to 50
- cm.setDefaultMaxPerRoute(50);
-
- httpClient = new DefaultHttpClient(cm);
- }
-
- /**
- * Handle http post request. Return String
- *
- * @param resourcePath This should be REST endpoint
- * @param jsonParamString The json string which should be executed from the post request
- * @return The HttpResponse
- * @throws Exception if any errors occur when executing the request
- */
- public HttpResponse doPost(URI resourcePath, String jsonParamString) throws Exception {
- HttpPost postRequest = null;
- try {
- postRequest = new HttpPost(resourcePath);
-
- StringEntity input = new StringEntity(jsonParamString);
- input.setContentType("application/json");
- postRequest.setEntity(input);
-
- return httpClient.execute(postRequest, new KubernetesResponseHandler());
- } finally {
- releaseConnection(postRequest);
- }
- }
-
- /**
- * Handle http get request. Return String
- *
- * @param resourcePath This should be REST endpoint
- * @return The HttpResponse
- * @throws org.apache.http.client.ClientProtocolException and IOException
- * if any errors occur when executing the request
- */
- public HttpResponse doGet(URI resourcePath) throws Exception {
- HttpGet getRequest = null;
- try {
- getRequest = new HttpGet(resourcePath);
- getRequest.addHeader("Content-Type", "application/json");
-
- return httpClient.execute(getRequest, new KubernetesResponseHandler());
- } finally {
- releaseConnection(getRequest);
- }
- }
-
- public HttpResponse doDelete(URI resourcePath) throws Exception {
- HttpDelete httpDelete = null;
- try {
- httpDelete = new HttpDelete(resourcePath);
- httpDelete.addHeader("Content-Type", "application/json");
-
- return httpClient.execute(httpDelete, new KubernetesResponseHandler());
- } finally {
- releaseConnection(httpDelete);
- }
- }
-
- public HttpResponse doPut(URI resourcePath, String jsonParamString) throws Exception {
-
- HttpPut putRequest = null;
- try {
- putRequest = new HttpPut(resourcePath);
-
- StringEntity input = new StringEntity(jsonParamString);
- input.setContentType("application/json");
- putRequest.setEntity(input);
-
- return httpClient.execute(putRequest, new KubernetesResponseHandler());
- } finally {
- releaseConnection(putRequest);
- }
- }
-
- private void releaseConnection(HttpRequestBase request) {
- if (request != null) {
- request.releaseConnection();
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/AbstractLiveTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/AbstractLiveTest.java b/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/AbstractLiveTest.java
index 03a2b0f..29b7ed4 100644
--- a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/AbstractLiveTest.java
+++ b/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/AbstractLiveTest.java
@@ -19,6 +19,11 @@
package org.apache.stratos.kubernetes.client.live;
+import io.fabric8.kubernetes.api.model.Container;
+import io.fabric8.kubernetes.api.model.ContainerPort;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.Service;
+import io.fabric8.kubernetes.api.model.resource.Quantity;
import junit.framework.TestCase;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
@@ -26,15 +31,14 @@ import org.apache.commons.logging.LogFactory;
import org.apache.stratos.kubernetes.client.KubernetesApiClient;
import org.apache.stratos.kubernetes.client.KubernetesConstants;
import org.apache.stratos.kubernetes.client.exceptions.KubernetesClientException;
-import org.apache.stratos.kubernetes.client.model.Pod;
-import org.apache.stratos.kubernetes.client.model.Port;
-import org.apache.stratos.kubernetes.client.model.Service;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -65,7 +69,7 @@ public class AbstractLiveTest extends TestCase {
protected int containerPort;
protected boolean testPodActivation;
protected boolean testServiceSocket;
- protected String[] minionPublicIPs = {"172.17.8.102"};
+ protected List<String> minionPublicIPs = Arrays.asList("172.17.8.102");
protected List<String> podIdList = new CopyOnWriteArrayList<String>();
protected List<String> serviceIdList = new CopyOnWriteArrayList<String>();
@@ -74,8 +78,7 @@ public class AbstractLiveTest extends TestCase {
log.info("Setting up live test...");
endpoint = System.getProperty(KUBERNETES_API_ENDPOINT);
if (endpoint == null) {
- endpoint = "http://" + DEFAULT_KUBERNETES_MASTER_IP + ":" + KUBERNETES_API_PORT + "/api/"
- + KubernetesConstants.KUBERNETES_API_VERSION + "/";
+ endpoint = "http://" + DEFAULT_KUBERNETES_MASTER_IP + ":" + KUBERNETES_API_PORT;
}
log.info(KUBERNETES_API_ENDPOINT + ": " + endpoint);
client = new KubernetesApiClient(endpoint);
@@ -110,7 +113,7 @@ public class AbstractLiveTest extends TestCase {
String minionPublicIPsStr = System.getProperty(MINION_PUBLIC_IPS);
if (StringUtils.isNotBlank(minionPublicIPsStr)) {
- minionPublicIPs = minionPublicIPsStr.split(",");
+ minionPublicIPs = Arrays.asList(minionPublicIPsStr.split(","));
}
log.info(MINION_PUBLIC_IPS + ": " + minionPublicIPsStr);
log.info("Kubernetes live test setup completed");
@@ -124,9 +127,11 @@ public class AbstractLiveTest extends TestCase {
log.info("Kubernetes resources cleaned");
}
- protected void createPod(String podId, String podName, String containerPortName, int cpu, int memory) throws KubernetesClientException {
+ protected void createPod(String podId, String podName, String containerPortName, int cpu, int memory)
+ throws KubernetesClientException {
+
log.info("Creating pod: [pod] " + podId);
- List<Port> ports = createPorts(containerPortName);
+ List<ContainerPort> ports = createPorts(containerPortName);
client.createPod(podId, podName, dockerImage, cpu, memory, ports, null);
podIdList.add(podId);
@@ -135,6 +140,17 @@ public class AbstractLiveTest extends TestCase {
assertNotNull(pod);
log.info("Pod created successfully: [pod] " + podId);
+ List<Container> containers = pod.getSpec().getContainers();
+ assertEquals(1, containers.size());
+
+ Map<String, Quantity> limits = containers.get(0).getResources().getLimits();
+ int memoryInMb = memory * 1024 * 1024;
+
+ log.info("Verifying container resource limits...");
+ assertEquals(String.valueOf(cpu), limits.get(KubernetesConstants.RESOURCE_CPU).getAmount());
+ assertEquals(String.valueOf(memoryInMb), limits.get(KubernetesConstants.RESOURCE_MEMORY).getAmount());
+ log.info("Container resource limits verified successfully");
+
if (testPodActivation) {
boolean activated = false;
long startTime = System.currentTimeMillis();
@@ -148,17 +164,21 @@ public class AbstractLiveTest extends TestCase {
log.info("Waiting pod status to be changed to running: [pod] " + podId);
sleep(2000);
pod = client.getPod(podId);
- if ((pod != null) && (pod.getCurrentState().getStatus().equals(KubernetesConstants.POD_STATUS_RUNNING))) {
+ if ((pod != null) && (pod.getStatus().getPhase().equals(KubernetesConstants.POD_STATUS_RUNNING))) {
activated = true;
- log.info("Pod state changed to running: [pod]" + pod.getId());
+ log.info("Pod state changed to running: [pod]" + pod.getMetadata().getName());
}
}
assertNotNull(pod);
- assertEquals(KubernetesConstants.POD_STATUS_RUNNING, pod.getCurrentState().getStatus());
+ assertEquals(KubernetesConstants.POD_STATUS_RUNNING, pod.getStatus().getPhase());
}
}
+ Pod getPod(String podId) throws KubernetesClientException {
+ return client.getPod(podId);
+ }
+
void deletePod(String podId) throws KubernetesClientException {
log.info("Deleting pod: " + podId);
client.deletePod(podId);
@@ -180,9 +200,9 @@ public class AbstractLiveTest extends TestCase {
}
protected void createService(String serviceId, String serviceName, int servicePort, String containerPortName,
- String[] publicIPs) throws KubernetesClientException, InterruptedException, IOException {
+ int containerPort, List<String> publicIPs) throws KubernetesClientException, InterruptedException, IOException {
log.info("Creating service...");
- client.createService(serviceId, serviceName, servicePort, containerPortName, publicIPs,
+ client.createService(serviceId, serviceName, servicePort, containerPortName, containerPort, publicIPs,
KubernetesConstants.SESSION_AFFINITY_CLIENT_IP);
serviceIdList.add(serviceId);
@@ -192,6 +212,10 @@ public class AbstractLiveTest extends TestCase {
log.info("Service creation successful");
}
+ Service getService(String serviceId) throws KubernetesClientException {
+ return client.getService(serviceId);
+ }
+
void deleteService(String serviceId) throws KubernetesClientException {
log.info(String.format("Deleting service: [service] %s", serviceId));
client.deleteService(serviceId);
@@ -219,9 +243,9 @@ public class AbstractLiveTest extends TestCase {
}
}
- protected List<Port> createPorts(String containerPortName) {
- List<Port> ports = new ArrayList<Port>();
- Port port = new Port();
+ protected List<ContainerPort> createPorts(String containerPortName) {
+ List<ContainerPort> ports = new ArrayList<ContainerPort>();
+ ContainerPort port = new ContainerPort();
port.setName(containerPortName);
port.setContainerPort(containerPort);
port.setProtocol("tcp");
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesApiClientLiveTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesApiClientLiveTest.java b/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesApiClientLiveTest.java
index 7983194..64c2f69 100644
--- a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesApiClientLiveTest.java
+++ b/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesApiClientLiveTest.java
@@ -20,6 +20,7 @@
*/
package org.apache.stratos.kubernetes.client.live;
+import io.fabric8.kubernetes.api.model.Pod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.kubernetes.client.exceptions.KubernetesClientException;
@@ -47,7 +48,7 @@ public class KubernetesApiClientLiveTest extends AbstractLiveTest {
public void testPodCreation() throws Exception {
log.info("Testing pod creation...");
- createPod("stratos-test-pod-2", "stratos-test-pod", "http-1", 1, 512);
+ createPod("stratos-test-pod-1", "stratos-test-pod", "http-1", 1, 512);
createPod("stratos-test-pod-2", "stratos-test-pod", "http-1", 2, 512);
deletePod("stratos-test-pod-1");
@@ -71,23 +72,24 @@ public class KubernetesApiClientLiveTest extends AbstractLiveTest {
String serviceName = "stratos-test-pod";
String containerPortName = "http-1";
- createService(serviceId, serviceName, SERVICE_PORT, containerPortName, minionPublicIPs);
+ createService(serviceId, serviceName, SERVICE_PORT, containerPortName, containerPort, minionPublicIPs);
- createPod("stratos-test-pod-1", serviceName, containerPortName, 1, 512);
- createPod("stratos-test-pod-2", serviceName, containerPortName, 2, 512);
+ createPod("stratos-test-pod-3", serviceName, containerPortName, 1, 512);
+ createPod("stratos-test-pod-4", serviceName, containerPortName, 2, 512);
if (testServiceSocket) {
// test service accessibility
- log.info(String.format("Connecting to service: [portal] %s:%d", minionPublicIPs[0], SERVICE_PORT));
+ log.info(String.format("Connecting to service: [portal] %s:%d", minionPublicIPs.get(0), SERVICE_PORT));
sleep(4000);
- Socket socket = new Socket(minionPublicIPs[0], SERVICE_PORT);
+ Socket socket = new Socket(minionPublicIPs.get(0), SERVICE_PORT);
assertTrue(socket.isConnected());
- log.info(String.format("Connecting to service successful: [portal] %s:%d", minionPublicIPs[0], SERVICE_PORT));
+ log.info(String.format("Connecting to service successful: [portal] %s:%d", minionPublicIPs.get(0),
+ SERVICE_PORT));
}
deleteService(serviceId);
- deletePod("stratos-test-pod-1");
- deletePod("stratos-test-pod-2");
+ deletePod("stratos-test-pod-3");
+ deletePod("stratos-test-pod-4");
}
}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesClusterCleanTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesClusterCleanTest.java b/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesClusterCleanTest.java
index b8af5ca..c94cd0e 100644
--- a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesClusterCleanTest.java
+++ b/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/live/KubernetesClusterCleanTest.java
@@ -19,11 +19,11 @@
package org.apache.stratos.kubernetes.client.live;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.Service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.kubernetes.client.exceptions.KubernetesClientException;
-import org.apache.stratos.kubernetes.client.model.Pod;
-import org.apache.stratos.kubernetes.client.model.Service;
import org.junit.Test;
import java.util.ArrayList;
@@ -43,7 +43,7 @@ public class KubernetesClusterCleanTest extends AbstractLiveTest {
List<Pod> podList = getPods();
while ((podList != null) && (podList.size() > 0)) {
for (Pod pod : podList) {
- deletePod(pod.getId());
+ deletePod(pod.getMetadata().getName());
}
podList = client.getPods();
}
@@ -51,7 +51,7 @@ public class KubernetesClusterCleanTest extends AbstractLiveTest {
List<Service> serviceList = getServices();
while ((serviceList != null) && (serviceList.size() > 0)) {
for (Service service : serviceList) {
- deleteService(service.getId());
+ deleteService(service.getMetadata().getName());
}
serviceList = getServices();
}
@@ -64,7 +64,7 @@ public class KubernetesClusterCleanTest extends AbstractLiveTest {
private List<Pod> getPods() throws KubernetesClientException {
List<Pod> podList = new ArrayList<Pod>();
for(Pod pod : client.getPods()) {
- if(!pod.getId().startsWith("kube")) {
+ if(!pod.getMetadata().getName().startsWith("kube")) {
podList.add(pod);
}
}
@@ -74,7 +74,7 @@ public class KubernetesClusterCleanTest extends AbstractLiveTest {
private List<Service> getServices() throws KubernetesClientException {
List<Service> serviceList = new ArrayList<Service>();
for (Service service : client.getServices()) {
- if (!service.getId().startsWith("kube")) {
+ if (!service.getMetadata().getName().startsWith("kube")) {
serviceList.add(service);
}
}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/unit/PodUnitTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/unit/PodUnitTest.java b/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/unit/PodUnitTest.java
deleted file mode 100644
index 27c2f54..0000000
--- a/components/org.apache.stratos.kubernetes.client/src/test/java/org/apache/stratos/kubernetes/client/unit/PodUnitTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.stratos.kubernetes.client.unit;
-
-import junit.framework.TestCase;
-import org.apache.stratos.kubernetes.client.model.*;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-@Category(org.apache.stratos.kubernetes.client.UnitTests.class)
-public class PodUnitTest extends TestCase {
-
- @Before
- public void setUp() {
- }
-
- @Test
- public void testPods() throws Exception {
- String podId = "nirmal-test-pod";
- String time = "2014/11/02";
- String selfLink = "link";
- Pod pod = new Pod();
- String apiVersion = "v1beta1";
- pod.setApiVersion(apiVersion);
- pod.setId(podId);
- pod.setCreationTimestamp(time);
- pod.setSelfLink(selfLink);
- pod.setResourceVersion(apiVersion);
- String kind = "Pod";
- pod.setKind(kind);
- Labels l = new Labels();
- l.setName("nirmal");
- pod.setLabels(l);
- State desiredState = new State();
- Manifest m = new Manifest();
- m.setId(podId);
- m.setVersion(apiVersion);
- Container c = new Container();
- c.setName("master");
- c.setImage("image");
- Port p = new Port();
- p.setContainerPort(8379);
- p.setHostPort(8379);
- c.addPort(p);
- m.addContainer(c);
- desiredState.setManifest(m);
- pod.setDesiredState(desiredState);
- State currentState = desiredState;
- pod.setCurrentState(currentState);
-
- assertEquals(podId, pod.getId());
- assertEquals(apiVersion, pod.getApiVersion());
- assertEquals(apiVersion, pod.getResourceVersion());
- assertEquals(kind, pod.getKind());
- assertEquals(l, pod.getLabels());
- assertEquals(currentState, pod.getCurrentState());
- assertEquals(selfLink, pod.getSelfLink());
- assertEquals(desiredState, pod.getDesiredState());
- assertEquals(time, pod.getCreationTimestamp());
-
- assertEquals(true, pod.equals(pod));
-
- Pod pod2 = new Pod();
- pod2.setId(podId);
-
- assertEquals(true, pod.equals(pod2));
- assertEquals(true, pod.hashCode() == pod2.hashCode());
-
- pod2.setId("aa");
- assertEquals(false, pod.equals(pod2));
-
- pod2.setId(null);
- assertEquals(false, pod.equals(pod2));
-
- assertEquals(false, pod.equals(null));
- assertEquals(false, pod.equals(desiredState));
-
- pod.setId(null);
- pod2.setId(podId);
- assertEquals(false, pod.equals(pod2));
-
- pod2.setId(null);
- assertEquals(true, pod.equals(pod2));
- assertEquals(true, pod.hashCode() == pod2.hashCode());
-
- }
-}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/org.apache.stratos.messaging/pom.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/pom.xml b/components/org.apache.stratos.messaging/pom.xml
index f75f11c..7316270 100644
--- a/components/org.apache.stratos.messaging/pom.xml
+++ b/components/org.apache.stratos.messaging/pom.xml
@@ -30,7 +30,7 @@
<groupId>org.apache.stratos</groupId>
<artifactId>org.apache.stratos.messaging</artifactId>
<packaging>bundle</packaging>
- <name>Apache Stratos - Messaging Component</name>
+ <name>Apache Stratos - Messaging</name>
<url>http://apache.org</url>
<dependencies>
@@ -113,12 +113,12 @@
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Export-Package>
+ org.apache.stratos.messaging,
org.apache.stratos.messaging.*,
+ org.apache.stratos.messaging.topology,
+ org.apache.stratos.messaging.topology.*,
org.apache.stratos.messaging.util.MessagingConstants,
</Export-Package>
- <!--Private-Package>
- org.apache.stratos.messaging.internal;
- </Private-Package-->
<Import-Package>
!org.apache.commons.logging,
org.apache.commons.logging; version=0.0.0,
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/components/pom.xml
----------------------------------------------------------------------
diff --git a/components/pom.xml b/components/pom.xml
index 7bbe37d..ff05c41 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -66,7 +66,6 @@
<!-- Redirector -->
<module>org.apache.stratos.sso.redirector.ui</module>
<module>org.apache.stratos.keystore.mgt</module>
- <module>org.apache.stratos.activation</module>
<!--Logging mgt-->
<module>org.apache.stratos.logging.view.ui</module>
<!-- RESTful admin services -->
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/dependencies/fabric8/kubernetes-api/README.md
----------------------------------------------------------------------
diff --git a/dependencies/fabric8/kubernetes-api/README.md b/dependencies/fabric8/kubernetes-api/README.md
new file mode 100644
index 0000000..1f8c473
--- /dev/null
+++ b/dependencies/fabric8/kubernetes-api/README.md
@@ -0,0 +1,7 @@
+## Fabric8 Kubernetes Client API
+
+Fabric8 Kubernetes Client API 2.1.11 has been forked to fix issue [1]. The fix has been merged to master branch,
+once the next Fabric8 release is published to Nexus this fork can be removed.
+
+[1] [origin-schema-generator/pull/50] (https://github.com/fabric8io/origin-schema-generator/pull/50)
+
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/dependencies/fabric8/kubernetes-api/pom.xml
----------------------------------------------------------------------
diff --git a/dependencies/fabric8/kubernetes-api/pom.xml b/dependencies/fabric8/kubernetes-api/pom.xml
new file mode 100644
index 0000000..936935a
--- /dev/null
+++ b/dependencies/fabric8/kubernetes-api/pom.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2005-2014 Red Hat, Inc.
+
+ Red Hat 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.
+
+-->
+<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.apache.stratos</groupId>
+ <artifactId>stratos-dependencies-fabric8</artifactId>
+ <version>4.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>kubernetes-api</artifactId>
+ <version>2.1.11-stratosv1</version>
+ <packaging>bundle</packaging>
+
+ <name>Fabric8 :: Kubernetes API</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.fabric8</groupId>
+ <artifactId>cxf-utils</artifactId>
+ <version>2.1.11</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.stratos</groupId>
+ <artifactId>kubernetes-model</artifactId>
+ <version>2.1.11-stratosv1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ <version>2.4.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-yaml</artifactId>
+ <version>2.4.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-client</artifactId>
+ <version>3.0.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ <version>1.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20140107</version>
+ </dependency>
+ <dependency>
+ <groupId>net.oauth.core</groupId>
+ <artifactId>oauth</artifactId>
+ <version>20100527</version>
+ </dependency>
+ <dependency>
+ <groupId>dnsjava</groupId>
+ <artifactId>dnsjava</artifactId>
+ <version>2.1.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.websocket</groupId>
+ <artifactId>websocket-client</artifactId>
+ <version>9.1.5.v20140505</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-io</artifactId>
+ <version>9.1.5.v20140505</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-util</artifactId>
+ <version>9.1.5.v20140505</version>
+ </dependency>
+ <!-- dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <version>2.0.1</version>
+ </dependency -->
+ <!-- testing -->
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>1.7.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.7.12</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- lets force the codegen to run first -->
+ <dependency>
+ <groupId>io.fabric8</groupId>
+ <artifactId>kubernetes-codegen</artifactId>
+ <version>2.1.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <version>2.3.7</version>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+ <Export-Package>
+ io.fabric8.kubernetes.api.*,
+ </Export-Package>
+ <Import-Package>
+ !javax.xml.bind.annotation.adapters,
+ org.osgi.framework,
+ *;resolution:=optional
+ </Import-Package>
+ <DynamicImport-Package>*</DynamicImport-Package>
+ <!-- Embedding apache cxf dependencies as they cannot be imported into carbon runtime at the moment -->
+ <Embed-Dependency>
+ jackson-annotations,jackson-core,jackson-databind,jackson-jaxrs-base,jackson-jaxrs-json-provider,
+ jackson-module-jaxb-annotations,jackson-dataformat-yaml,javax.annotation-api,javax.ws.rs-api,
+ jetty-io,jetty-util,json,oauth,xmlschema-core,fabric8-utils,cxf-utils,
+ cxf-rt-rs-client,cxf-rt-transports-http,cxf-rt-frontend-jaxrs,cxf-core,dnsjava
+ </Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <mainClass>io.fabric8.kubernetes.api.Example</mainClass>
+ <classpathScope>test</classpathScope>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+
+ <profiles>
+ <profile>
+ <id>trigger</id>
+ <properties>
+ <build>console-build</build>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>${exec-maven-plugin.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <executable>java</executable>
+ <classpathScope>test</classpathScope>
+ <!-- TODO for some reason this fails when running inside maven - wacky! -->
+ <arguments>
+ <argument>-classpath</argument>
+ <classpath />
+ <argument>io.fabric8.kubernetes.api.TriggerBuild</argument>
+ <argument>${build}</argument>
+ </arguments>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/AbstractWatcher.java
----------------------------------------------------------------------
diff --git a/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/AbstractWatcher.java b/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/AbstractWatcher.java
new file mode 100644
index 0000000..68793bc
--- /dev/null
+++ b/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/AbstractWatcher.java
@@ -0,0 +1,61 @@
+package io.fabric8.kubernetes.api;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.fabric8.kubernetes.api.watch.WatchEvent;
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.UpgradeException;
+import org.eclipse.jetty.websocket.api.WebSocketAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+public abstract class AbstractWatcher<T extends HasMetadata> extends WebSocketAdapter implements Watcher<T> {
+
+ private static final transient Logger LOG = LoggerFactory.getLogger(KubernetesClient.class);
+
+ private ObjectMapper objectMapper;
+
+ @Override
+ public void onWebSocketConnect(Session sess) {
+ super.onWebSocketConnect(sess);
+ LOG.debug("Got connect: {}", sess);
+ objectMapper = KubernetesFactory.createObjectMapper();
+ }
+
+ @Override
+ public void onWebSocketClose(int statusCode, String reason) {
+ super.onWebSocketClose(statusCode, reason);
+ LOG.debug("Connection closed: {} - {}", statusCode, reason);
+ objectMapper = null;
+ }
+
+ @Override
+ public void onWebSocketText(String message) {
+ LOG.trace("Received message: {}", message);
+ if (message != null && message.length() > 0) {
+ try {
+ WatchEvent event = objectMapper.reader(WatchEvent.class).readValue(message);
+ T obj = (T) event.getObject();
+ Action action = Action.valueOf(event.getType());
+ eventReceived(action, obj);
+ } catch (IOException e) {
+ LOG.error("Could not deserialize watch event: {}", message, e);
+ } catch (ClassCastException e) {
+ LOG.error("Received wrong type of object for watch", e);
+ } catch (IllegalArgumentException e) {
+ LOG.error("Invalid event type", e);
+ }
+ }
+ }
+
+ public void onWebSocketError(Throwable cause) {
+ if (cause instanceof UpgradeException) {
+ LOG.error("WebSocketError: Could not upgrade connection: {}", (((UpgradeException) cause).getResponseStatusCode()), cause);
+ } else {
+ LOG.error("WebSocketError: {}", cause);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/3414e7ce/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/Controller.java
----------------------------------------------------------------------
diff --git a/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/Controller.java b/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/Controller.java
new file mode 100644
index 0000000..3e90776
--- /dev/null
+++ b/dependencies/fabric8/kubernetes-api/src/main/java/io/fabric8/kubernetes/api/Controller.java
@@ -0,0 +1,850 @@
+/**
+ * Copyright 2005-2014 Red Hat, Inc.
+ *
+ * Red Hat 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 io.fabric8.kubernetes.api;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import io.fabric8.kubernetes.api.extensions.Templates;
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.fabric8.kubernetes.api.model.KubernetesList;
+import io.fabric8.kubernetes.api.model.Namespace;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.PodSpec;
+import io.fabric8.kubernetes.api.model.PodTemplateSpec;
+import io.fabric8.kubernetes.api.model.ReplicationController;
+import io.fabric8.kubernetes.api.model.ReplicationControllerSpec;
+import io.fabric8.kubernetes.api.model.SecretVolumeSource;
+import io.fabric8.kubernetes.api.model.Service;
+import io.fabric8.kubernetes.api.model.Volume;
+import io.fabric8.openshift.api.model.BuildConfig;
+import io.fabric8.openshift.api.model.DeploymentConfig;
+import io.fabric8.openshift.api.model.ImageStream;
+import io.fabric8.openshift.api.model.OAuthClient;
+import io.fabric8.openshift.api.model.Route;
+import io.fabric8.openshift.api.model.template.Template;
+import io.fabric8.utils.Files;
+import io.fabric8.utils.IOHelpers;
+import io.fabric8.utils.Objects;
+import io.fabric8.utils.Strings;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+
+import javax.ws.rs.WebApplicationException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import static io.fabric8.kubernetes.api.KubernetesHelper.getName;
+import static io.fabric8.kubernetes.api.KubernetesHelper.getObjectId;
+import static io.fabric8.kubernetes.api.KubernetesHelper.getOrCreateMetadata;
+import static io.fabric8.kubernetes.api.KubernetesHelper.getPodMap;
+import static io.fabric8.kubernetes.api.KubernetesHelper.getReplicationControllerMap;
+import static io.fabric8.kubernetes.api.KubernetesHelper.getServiceMap;
+import static io.fabric8.kubernetes.api.KubernetesHelper.loadJson;
+import static io.fabric8.kubernetes.api.KubernetesHelper.summaryText;
+import static io.fabric8.kubernetes.api.KubernetesHelper.toItemList;
+
+/**
+ * Applies DTOs to the current Kubernetes master
+ */
+public class Controller {
+ private static final transient Logger LOG = LoggerFactory.getLogger(Controller.class);
+
+ private final KubernetesClient kubernetes;
+ private Map<String, Pod> podMap;
+ private Map<String, ReplicationController> replicationControllerMap;
+ private Map<String, Service> serviceMap;
+ private boolean throwExceptionOnError = true;
+ private boolean allowCreate = true;
+ private boolean recreateMode;
+ private boolean servicesOnlyMode;
+ private boolean ignoreServiceMode;
+ private boolean ignoreRunningOAuthClients = true;
+ private boolean processTemplatesLocally;
+ private File logJsonDir;
+ private File basedir;
+
+ public Controller() {
+ this(new KubernetesClient());
+ }
+
+ public Controller(KubernetesClient kubernetes) {
+ this.kubernetes = kubernetes;
+ }
+
+ public String apply(File file) throws Exception {
+ String ext = Files.getFileExtension(file);
+
+ if ("yaml".equalsIgnoreCase(ext)) {
+ return applyYaml(file);
+ } else if ("json".equalsIgnoreCase(ext)) {
+ return applyJson(file);
+ } else {
+ throw new IllegalArgumentException("Unknown file type " + ext);
+ }
+ }
+
+ /**
+ * Applies the given JSON to the underlying REST APIs in a single operation without needing to explicitly parse first.
+ */
+ public String applyJson(byte[] json) throws Exception {
+ Object dto = loadJson(json);
+ apply(dto, "REST call");
+ return "";
+ }
+
+ /**
+ * Applies the given JSON to the underlying REST APIs in a single operation without needing to explicitly parse first.
+ */
+ public String applyJson(String json) throws Exception {
+ Object dto = loadJson(json);
+ apply(dto, "REST call");
+ return "";
+ }
+
+ /**
+ * Applies the given JSON to the underlying REST APIs in a single operation without needing to explicitly parse first.
+ */
+ public String applyJson(File json) throws Exception {
+ Object dto = loadJson(json);
+ apply(dto, "REST call");
+ return "";
+ }
+
+ /**
+ * Applies the given YAML to the underlying REST APIs in a single operation without needing to explicitly parse first.
+ */
+ public String applyYaml(String yaml) throws Exception {
+ String json = convertYamlToJson(yaml);
+ Object dto = loadJson(json);
+ apply(dto, "REST call");
+ return "";
+ }
+
+ /**
+ * Applies the given YAML to the underlying REST APIs in a single operation without needing to explicitly parse first.
+ */
+ public String applyYaml(File yaml) throws Exception {
+ String json = convertYamlToJson(yaml);
+ Object dto = loadJson(json);
+ apply(dto, "REST call");
+ return "";
+ }
+
+ private String convertYamlToJson(String yamlString) throws FileNotFoundException {
+ Yaml yaml = new Yaml();
+
+ Map<String, Object> map = (Map<String, Object>) yaml.load(yamlString);
+ JSONObject jsonObject = new JSONObject(map);
+
+ return jsonObject.toString();
+ }
+
+ private String convertYamlToJson(File yamlFile) throws FileNotFoundException {
+ Yaml yaml = new Yaml();
+ FileInputStream fstream = new FileInputStream(yamlFile);
+
+ Map<String, Object> map = (Map<String, Object>) yaml.load(fstream);
+ JSONObject jsonObject = new JSONObject(map);
+
+ return jsonObject.toString();
+ }
+
+ /**
+ * Applies the given JSON to the underlying REST APIs in a single operation without needing to explicitly parse first.
+ */
+ public String applyJson(InputStream json) throws Exception {
+ Object dto = loadJson(json);
+ apply(dto, "REST call");
+ return "";
+ }
+
+ /**
+ * Applies the given DTOs onto the Kubernetes master
+ */
+ public void apply(Object dto, String sourceName) throws Exception {
+ if (dto instanceof List) {
+ List list = (List) dto;
+ for (Object element : list) {
+ if (dto == element) {
+ LOG.warn("Found recursive nested object for " + dto + " of class: " + dto.getClass().getName());
+ continue;
+ }
+ apply(element, sourceName);
+ }
+ } else if (dto instanceof KubernetesList) {
+ applyList((KubernetesList) dto, sourceName);
+ } else if (dto != null) {
+ applyEntity(dto, sourceName);
+ }
+ }
+
+ /**
+ * Applies the given DTOs onto the Kubernetes master
+ */
+ public void applyEntity(Object dto, String sourceName) throws Exception {
+ if (dto instanceof Pod) {
+ applyPod((Pod) dto, sourceName);
+ } else if (dto instanceof ReplicationController) {
+ applyReplicationController((ReplicationController) dto, sourceName);
+ } else if (dto instanceof Service) {
+ applyService((Service) dto, sourceName);
+ } else if (dto instanceof Namespace) {
+ applyNamespace((Namespace) dto);
+ } else if (dto instanceof Route) {
+ applyRoute((Route) dto, sourceName);
+ } else if (dto instanceof BuildConfig) {
+ applyBuildConfig((BuildConfig) dto, sourceName);
+ } else if (dto instanceof DeploymentConfig) {
+ applyDeploymentConfig((DeploymentConfig) dto, sourceName);
+ } else if (dto instanceof ImageStream) {
+ applyImageStream((ImageStream) dto, sourceName);
+ } else if (dto instanceof OAuthClient) {
+ applyOAuthClient((OAuthClient) dto, sourceName);
+ } else if (dto instanceof Template) {
+ applyTemplate((Template) dto, sourceName);
+ } else {
+ throw new IllegalArgumentException("Unknown entity type " + dto);
+ }
+ }
+
+ public void applyOAuthClient(OAuthClient entity, String sourceName) {
+ String id = getName(entity);
+ Objects.notNull(id, "No name for " + entity + " " + sourceName);
+ if (isServicesOnlyMode()) {
+ LOG.debug("Only processing Services right now so ignoring OAuthClient: " + id);
+ return;
+ }
+ OAuthClient old = kubernetes.getOAuthClient(id);
+ if (isRunning(old)) {
+ if (isIgnoreRunningOAuthClients()) {
+ LOG.info("Not updating the OAuthClient which are shared across namespaces as its already running");
+ return;
+ }
+ if (UserConfigurationCompare.configEqual(entity, old)) {
+ LOG.info("OAuthClient hasn't changed so not doing anything");
+ } else {
+ if (isRecreateMode()) {
+ kubernetes.deleteOAuthClient(id);
+ doCreateOAuthClient(entity, sourceName);
+ } else {
+ try {
+ Object answer = kubernetes.updateOAuthClient(id, entity);
+ LOG.info("Updated pod result: " + answer);
+ } catch (Exception e) {
+ onApplyError("Failed to update pod from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ }
+ }
+ } else {
+ if (!isAllowCreate()) {
+ LOG.warn("Creation disabled so not creating an OAuthClient from " + sourceName + " name " + getName(entity));
+ } else {
+ doCreateOAuthClient(entity, sourceName);
+ }
+ }
+ }
+
+ protected void doCreateOAuthClient(OAuthClient entity, String sourceName) {
+ Object result = null;
+ try {
+ result = kubernetes.createOAuthClient(entity);
+ } catch (Exception e) {
+ onApplyError("Failed to create OAuthClient from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ }
+
+ /**
+ * Creates/updates the template and processes it returning the processed DTOs
+ */
+ public Object applyTemplate(Template entity, String sourceName) throws Exception {
+ if (!isProcessTemplatesLocally()) {
+ String namespace = getNamespace();
+ String id = getName(entity);
+ Objects.notNull(id, "No name for " + entity + " " + sourceName);
+ Template old = kubernetes.getTemplate(id, namespace);
+ if (isRunning(old)) {
+ if (UserConfigurationCompare.configEqual(entity, old)) {
+ LOG.info("Template hasn't changed so not doing anything");
+ } else {
+ boolean recreateMode = isRecreateMode();
+ // TODO seems you can't update templates right now
+ recreateMode = true;
+ if (recreateMode) {
+ kubernetes.deleteTemplate(id, namespace);
+ doCreateTemplate(entity, namespace, sourceName);
+ } else {
+ LOG.info("Updating a entity from " + sourceName);
+ try {
+ Object answer = kubernetes.updateTemplate(id, entity, namespace);
+ LOG.info("Updated entity: " + answer);
+ } catch (Exception e) {
+ onApplyError("Failed to update controller from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ }
+ }
+ } else {
+ if (!isAllowCreate()) {
+ LOG.warn("Creation disabled so not creating a entity from " + sourceName + " namespace " + namespace + " name " + getName(entity));
+ } else {
+ doCreateTemplate(entity, namespace, sourceName);
+ }
+ }
+ }
+ return processTemplate(entity, sourceName);
+ }
+
+ protected void doCreateTemplate(Template entity, String namespace, String sourceName) {
+ LOG.info("Creating a template from " + sourceName + " namespace " + namespace + " name " + getName(entity));
+ try {
+ Object answer = kubernetes.createTemplate(entity, namespace);
+ logGeneratedEntity("Created template: ", namespace, entity, answer);
+ } catch (Exception e) {
+ onApplyError("Failed to template entity from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ }
+
+ protected void logGeneratedEntity(String message, String namespace, HasMetadata entity, Object result) {
+ if (logJsonDir != null) {
+ File namespaceDir = new File(logJsonDir, namespace);
+ namespaceDir.mkdirs();
+ String kind = KubernetesHelper.getKind(entity);
+ String name = KubernetesHelper.getName(entity);
+ if (Strings.isNotBlank(kind)) {
+ name = kind.toLowerCase() + "-" + name;
+ }
+ if (Strings.isNullOrBlank(name)) {
+ LOG.warn("No name for the entity " + entity);
+ } else {
+ String fileName = name + ".json";
+ File file = new File(namespaceDir, fileName);
+ if (file.exists()) {
+ int idx = 1;
+ while (true) {
+ fileName = name + "-" + idx++ + ".json";
+ file = new File(namespaceDir, fileName);
+ if (!file.exists()) {
+ break;
+ }
+ }
+ }
+ String text;
+ if (result instanceof String) {
+ text = result.toString();
+ } else {
+ try {
+ text = KubernetesHelper.toJson(result);
+ } catch (JsonProcessingException e) {
+ LOG.warn("Could not convert " + result + " to JSON: " + e, e);
+ if (result != null) {
+ text = result.toString();
+ } else {
+ text = "null";
+ }
+ }
+ }
+ try {
+ IOHelpers.writeFully(file, text);
+ Object fileLocation = file;
+ if (basedir != null) {
+ String path = Files.getRelativePath(basedir, file);
+ if (path != null) {
+ fileLocation = Strings.stripPrefix(path, "/");
+ }
+ }
+ LOG.info(message + fileLocation);
+ } catch (IOException e) {
+ LOG.warn("Failed to write to file " + file + ". " + e, e);
+ }
+ return;
+ }
+ }
+ LOG.info(message + result);
+ }
+
+ public Object processTemplate(Template entity, String sourceName) {
+ if (isProcessTemplatesLocally()) {
+ try {
+ return Templates.processTemplatesLocally(entity);
+ } catch (IOException e) {
+ onApplyError("Failed to process template " + sourceName + ". " + e + ". " + entity, e);
+ return null;
+ }
+ } else {
+ String id = getName(entity);
+ Objects.notNull(id, "No name for " + entity + " " + sourceName);
+ String namespace = KubernetesHelper.getNamespace(entity);
+ LOG.info("Creating Template " + namespace + ":" + id + " " + summaryText(entity));
+ Object result = null;
+ try {
+ String json = kubernetes.processTemplate(entity, namespace);
+ logGeneratedEntity("Template processed into: ", namespace, entity, json);
+ result = loadJson(json);
+ printSummary(result);
+ } catch (Exception e) {
+ onApplyError("Failed to create controller from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ return result;
+ }
+ }
+
+
+ protected void printSummary(Object kubeResource) throws IOException {
+ if (kubeResource != null) {
+ LOG.debug(" " + kubeResource.getClass().getSimpleName() + " " + kubeResource);
+ }
+ if (kubeResource instanceof Template) {
+ Template template = (Template) kubeResource;
+ String id = getName(template);
+ LOG.info(" Template " + id + " " + summaryText(template));
+ printSummary(template.getObjects());
+ return;
+ }
+ List<HasMetadata> list = toItemList(kubeResource);
+ for (HasMetadata object : list) {
+ if (object != null) {
+ if (object == list) {
+ LOG.warn("Ignoring recursive list " + list);
+ continue;
+ } else if (object instanceof List) {
+ printSummary(object);
+ } else {
+ String kind = object.getClass().getSimpleName();
+ String id = getObjectId(object);
+ LOG.info(" " + kind + " " + id + " " + summaryText(object));
+ }
+ }
+ }
+ }
+
+ public void applyRoute(Route entity, String sourceName) {
+ String id = getName(entity);
+ Objects.notNull(id, "No name for " + entity + " " + sourceName);
+ String namespace = KubernetesHelper.getNamespace(entity);
+ if (Strings.isNullOrBlank(namespace)) {
+ namespace = kubernetes.getNamespace();
+ }
+ Route route = kubernetes.findRoute(id, namespace);
+ if (route == null) {
+ try {
+ LOG.info("Creating Route " + namespace + ":" + id + " " + KubernetesHelper.summaryText(entity));
+ kubernetes.createRoute(entity, namespace);
+ } catch (WebApplicationException e) {
+ if (e.getResponse().getStatus() == 404) {
+ // could be OpenShift 0.4.x which has the old style REST API - lets try that...
+ LOG.warn("Got a 404 - could be an old Kubernetes/OpenShift environment - lets try the old style REST API...");
+ try {
+ kubernetes.createRouteOldAPi(entity, namespace);
+ } catch (Exception e1) {
+ onApplyError("Failed to create Route from " + sourceName + ". " + e1 + ". " + entity, e1);
+ }
+ } else {
+ onApplyError("Failed to create Route from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ } catch (Exception e) {
+ onApplyError("Failed to create Route from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ }
+ }
+
+ public void applyBuildConfig(BuildConfig entity, String sourceName) {
+ String id = getName(entity);
+ Objects.notNull(id, "No name for " + entity + " " + sourceName);
+ String namespace = KubernetesHelper.getNamespace(entity);
+ if (Strings.isNullOrBlank(namespace)) {
+ namespace = kubernetes.getNamespace();
+ }
+ BuildConfig old = kubernetes.getBuildConfig(id, namespace);
+ if (isRunning(old)) {
+ if (UserConfigurationCompare.configEqual(entity, old)) {
+ LOG.info("BuildConfig hasn't changed so not doing anything");
+ } else {
+ if (isRecreateMode()) {
+ kubernetes.deleteBuildConfig(id, namespace);
+ doCreateBuildConfig(entity, namespace, sourceName);
+ } else {
+ LOG.info("Updating BuildConfig from " + sourceName);
+ try {
+ String resourceVersion = KubernetesHelper.getResourceVersion(old);
+ KubernetesHelper.getOrCreateMetadata(entity).setResourceVersion(resourceVersion);
+ Object answer = kubernetes.updateBuildConfig(id, entity, namespace);
+ logGeneratedEntity("Updated BuildConfig: ", namespace, entity, answer);
+ } catch (Exception e) {
+ onApplyError("Failed to update BuildConfig from " + sourceName + ". " + e + ". " + entity, e);
+ }
+ }
+ }
+ } else {
+ if (!isAllowCreate()) {
+ LOG.warn("Creation disabled so not creating BuildConfig from " + sourceName + " namespace " + namespace + " name " + getName(entity));
+ } else {
+ doCreateBuildConfig(entity, namespace, sourceName);
+ }
+ }
+ }
+
+ public void doCreateBuildConfig(BuildConfig entity, String namespace ,String sourceName) {
+ try {
+ kubernetes.createBuildConfig(entity, namespace);
+ } catch (Exception e) {
+ onApplyError("Failed to create BuildConfig from " + sourceName + ". " + e, e);
+ }
+ }
+
+ public void applyDeploymentConfig(DeploymentConfig entity, String sourceName) {
+ try {
+ kubernetes.createDeploymentConfig(entity, getNamespace());
+ } catch (Exception e) {
+ onApplyError("Failed to create DeploymentConfig from " + sourceName + ". " + e, e);
+ }
+ }
+
+ public void applyImageStream(ImageStream entity, String sourceName) {
+ try {
+ kubernetes.createImageStream(entity, getNamespace());
+ } catch (Exception e) {
+ onApplyError("Failed to create BuildConfig from " + sourceName + ". " + e, e);
+ }
+ }
+
+ public void applyList(KubernetesList list, String sourceName) throws Exception {
+ List<HasMetadata> entities = list.getItems();
+ if (entities != null) {
+ for (Object entity : entities) {
+ applyEntity(entity, sourceName);
+ }
+ }
+ }
+
+ public void applyService(Service service, String sourceName) throws Exception {
+ String namespace = getNamespace();
+ String id = getName(service);
+ Objects.notNull(id, "No name for " + service + " " + sourceName);
+ if (isIgnoreServiceMode()) {
+ LOG.debug("Ignoring Service: " + namespace + ":" + id);
+ return;
+ }
+ if (serviceMap == null) {
+ serviceMap = getServiceMap(kubernetes, namespace);
+ }
+ Service old = serviceMap.get(id);
+ if (isRunning(old)) {
+ if (UserConfigurationCompare.configEqual(service, old)) {
+ LOG.info("Service hasn't changed so not doing anything");
+ } else {
+ if (isRecreateMode()) {
+ kubernetes.deleteService(service, namespace);
+ doCreateService(service, namespace, sourceName);
+ } else {
+ LOG.info("Updating a service from " + sourceName);
+ try {
+ Object answer = kubernetes.updateService(id, service, namespace);
+ logGeneratedEntity("Updated service: ", namespace, service, answer);
+ } catch (Exception e) {
+ onApplyError("Failed to update controller from " + sourceName + ". " + e + ". " + service, e);
+ }
+ }
+ }
+ } else {
+ if (!isAllowCreate()) {
+ LOG.warn("Creation disabled so not creating a service from " + sourceName + " namespace " + namespace + " name " + getName(service));
+ } else {
+ doCreateService(service, namespace, sourceName);
+ }
+ }
+ }
+
+ protected void doCreateService(Service service, String namespace, String sourceName) {
+ LOG.info("Creating a service from " + sourceName + " namespace " + namespace + " name " + getName(service));
+ try {
+ Object answer;
+ if (Strings.isNotBlank(namespace)) {
+ answer = kubernetes.createService(service, namespace);
+ } else {
+ answer = kubernetes.createService(service);
+ }
+ logGeneratedEntity("Created service: ", namespace, service, answer);
+ } catch (Exception e) {
+ onApplyError("Failed to create service from " + sourceName + ". " + e + ". " + service, e);
+ }
+ }
+
+ public void applyNamespace(Namespace entity) {
+ String namespace = getOrCreateMetadata(entity).getName();
+ LOG.info("Creating a namespace " + namespace);
+ try {
+ Object answer = kubernetes.createNamespace(entity);
+ logGeneratedEntity("Created namespace: ", namespace, entity, answer);
+ } catch (Exception e) {
+ onApplyError("Failed to create namespace. " + e + ". " + entity, e);
+ }
+ }
+
+ public void applyReplicationController(ReplicationController replicationController, String sourceName) throws Exception {
+ String namespace = getNamespace();
+ String id = getName(replicationController);
+ Objects.notNull(id, "No name for " + replicationController + " " + sourceName);
+ if (isServicesOnlyMode()) {
+ LOG.debug("Only processing Services right now so ignoring ReplicationController: " + namespace + ":" + id);
+ return;
+ }
+ if (replicationControllerMap == null) {
+ replicationControllerMap = getReplicationControllerMap(kubernetes, namespace);
+ }
+ ReplicationController old = replicationControllerMap.get(id);
+ if (isRunning(old)) {
+ if (UserConfigurationCompare.configEqual(replicationController, old)) {
+ LOG.info("ReplicationController hasn't changed so not doing anything");
+ } else {
+ if (isRecreateMode()) {
+ kubernetes.deleteReplicationControllerAndPods(replicationController, namespace);
+ doCreateReplicationController(replicationController, namespace, sourceName);
+ } else {
+ LOG.info("Updating replicationController from " + sourceName + " namespace " + namespace + " name " + getName(replicationController));
+ try {
+ Object answer = kubernetes.updateReplicationController(id, replicationController);
+ logGeneratedEntity("Updated replicationController: ", namespace, replicationController, answer);
+ } catch (Exception e) {
+ onApplyError("Failed to update replicationController from " + sourceName + ". " + e + ". " + replicationController, e);
+ }
+ }
+ }
+ } else {
+ if (!isAllowCreate()) {
+ LOG.warn("Creation disabled so not creating a replicationController from " + sourceName + " namespace " + namespace + " name " + getName(replicationController));
+ } else {
+ doCreateReplicationController(replicationController, namespace, sourceName);
+ }
+ }
+ }
+
+ protected void doCreateReplicationController(ReplicationController replicationController, String namespace, String sourceName) {
+ LOG.info("Creating a replicationController from " + sourceName + " namespace " + namespace + " name " + getName(replicationController));
+ try {
+ // lets check that if secrets are required they exist
+ ReplicationControllerSpec spec = replicationController.getSpec();
+ if (spec != null) {
+ PodTemplateSpec template = spec.getTemplate();
+ if (template != null) {
+ PodSpec podSpec = template.getSpec();
+ validatePodSpec(podSpec, namespace);
+ }
+ }
+ Object answer;
+ if (Strings.isNotBlank(namespace)) {
+ answer = kubernetes.createReplicationController(replicationController, namespace);
+ } else {
+ answer = kubernetes.createReplicationController(replicationController);
+ }
+ logGeneratedEntity("Created replicationController: ", namespace, replicationController, answer);
+ } catch (Exception e) {
+ onApplyError("Failed to create replicationController from " + sourceName + ". " + e + ". " + replicationController, e);
+ }
+ }
+
+ /**
+ * Lets verify that any dependencies are available; such as volumes or secrets
+ */
+ protected void validatePodSpec(PodSpec podSpec, String namespace) {
+ List<Volume> volumes = podSpec.getVolumes();
+ if (volumes != null) {
+ for (Volume volume : volumes) {
+ SecretVolumeSource secret = volume.getSecret();
+ if (secret != null) {
+ String secretName = secret.getSecretName();
+ if (Strings.isNotBlank(secretName)) {
+ KubernetesHelper.validateSecretExists(kubernetes, namespace, secretName);
+ }
+ }
+ }
+ }
+ }
+
+ public void applyPod(Pod pod, String sourceName) throws Exception {
+ String namespace = getNamespace();
+ String id = getName(pod);
+ Objects.notNull(id, "No name for " + pod + " " + sourceName);
+ if (isServicesOnlyMode()) {
+ LOG.debug("Only processing Services right now so ignoring Pod: " + namespace + ":" + id);
+ return;
+ }
+ if (podMap == null) {
+ podMap = getPodMap(kubernetes, namespace);
+ }
+ Pod old = podMap.get(id);
+ if (isRunning(old)) {
+ if (UserConfigurationCompare.configEqual(pod, old)) {
+ LOG.info("Pod hasn't changed so not doing anything");
+ } else {
+ if (isRecreateMode()) {
+ kubernetes.deletePod(pod, namespace);
+ doCreatePod(pod, namespace, sourceName);
+ } else {
+ LOG.info("Updating a pod from " + sourceName + " namespace " + namespace + " name " + getName(pod));
+ try {
+ Object answer = kubernetes.updatePod(id, pod);
+ LOG.info("Updated pod result: " + answer);
+ } catch (Exception e) {
+ onApplyError("Failed to update pod from " + sourceName + ". " + e + ". " + pod, e);
+ }
+ }
+ }
+ } else {
+ if (!isAllowCreate()) {
+ LOG.warn("Creation disabled so not creating a pod from " + sourceName + " namespace " + namespace + " name " + getName(pod));
+ } else {
+ doCreatePod(pod, namespace, sourceName);
+ }
+ }
+ }
+
+ protected void doCreatePod(Pod pod, String namespace, String sourceName) {
+ LOG.info("Creating a pod from " + sourceName + " namespace " + namespace + " name " + getName(pod));
+ try {
+ PodSpec podSpec = pod.getSpec();
+ if (podSpec != null) {
+ validatePodSpec(podSpec, namespace);
+ }
+ Object answer;
+ if (Strings.isNotBlank(namespace)) {
+ answer = kubernetes.createPod(pod, namespace);
+ } else {
+ answer = kubernetes.createPod(pod);
+ }
+ LOG.info("Created pod result: " + answer);
+ } catch (Exception e) {
+ onApplyError("Failed to create pod from " + sourceName + ". " + e + ". " + pod, e);
+ }
+ }
+
+ public String getNamespace() {
+ return kubernetes.getNamespace();
+ }
+
+ public void setNamespace(String namespace) {
+ kubernetes.setNamespace(namespace);
+ }
+
+ public boolean isThrowExceptionOnError() {
+ return throwExceptionOnError;
+ }
+
+ public void setThrowExceptionOnError(boolean throwExceptionOnError) {
+ this.throwExceptionOnError = throwExceptionOnError;
+ }
+
+ public boolean isProcessTemplatesLocally() {
+ return processTemplatesLocally;
+ }
+
+ public void setProcessTemplatesLocally(boolean processTemplatesLocally) {
+ this.processTemplatesLocally = processTemplatesLocally;
+ }
+
+ public File getLogJsonDir() {
+ return logJsonDir;
+ }
+
+ /**
+ * Lets you configure the directory where JSON logging files should go
+ */
+ public void setLogJsonDir(File logJsonDir) {
+ this.logJsonDir = logJsonDir;
+ }
+
+ public File getBasedir() {
+ return basedir;
+ }
+
+ public void setBasedir(File basedir) {
+ this.basedir = basedir;
+ }
+
+ protected boolean isRunning(HasMetadata entity) {
+ return entity != null;
+ }
+
+
+ /**
+ * Logs an error applying some JSON to Kubernetes and optionally throws an exception
+ */
+ protected void onApplyError(String message, Exception e) {
+ LOG.error(message, e);
+ if (throwExceptionOnError) {
+ throw new RuntimeException(message, e);
+ }
+ }
+
+ /**
+ * Returns true if this controller allows new resources to be created in the given namespace
+ */
+ public boolean isAllowCreate() {
+ return allowCreate;
+ }
+
+ public void setAllowCreate(boolean allowCreate) {
+ this.allowCreate = allowCreate;
+ }
+
+ /**
+ * If enabled then updates are performed by deleting the resource first then creating it
+ */
+ public boolean isRecreateMode() {
+ return recreateMode;
+ }
+
+ public void setRecreateMode(boolean recreateMode) {
+ this.recreateMode = recreateMode;
+ }
+
+ public void setServicesOnlyMode(boolean servicesOnlyMode) {
+ this.servicesOnlyMode = servicesOnlyMode;
+ }
+
+ /**
+ * If enabled then only services are created/updated to allow services to be created/updated across
+ * a number of apps before any pods/replication controllers are updated
+ */
+ public boolean isServicesOnlyMode() {
+ return servicesOnlyMode;
+ }
+
+ /**
+ * If enabled then all services are ignored to avoid them being recreated. This is useful if you want to
+ * recreate ReplicationControllers and Pods but leave Services as they are to avoid the portalIP addresses
+ * changing
+ */
+ public boolean isIgnoreServiceMode() {
+ return ignoreServiceMode;
+ }
+
+ public void setIgnoreServiceMode(boolean ignoreServiceMode) {
+ this.ignoreServiceMode = ignoreServiceMode;
+ }
+
+ public boolean isIgnoreRunningOAuthClients() {
+ return ignoreRunningOAuthClients;
+ }
+
+ public void setIgnoreRunningOAuthClients(boolean ignoreRunningOAuthClients) {
+ this.ignoreRunningOAuthClients = ignoreRunningOAuthClients;
+ }
+}