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; + } +}
