diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e5a4a3be23..c40b2a7c602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ #### New Features * Fix #3291: Retrying the HTTP operation in case of IOException too +* Fix #2712: Add support for watching logs in multi-container Controller resources (Deployments, StatefulSets, ReplicaSet etc) ### 5.5.0 (2021-06-30) diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java index ba686aa2dd9..3d7bb1f7f46 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/ScalableResource.java @@ -16,5 +16,6 @@ package io.fabric8.kubernetes.client.dsl; public interface ScalableResource extends Resource, - Scaleable , Loggable { + Scaleable , Loggable, + Containerable> { } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PodControllerOperationContext.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PodControllerOperationContext.java new file mode 100644 index 00000000000..f7cd075303a --- /dev/null +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/PodControllerOperationContext.java @@ -0,0 +1,226 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.kubernetes.client.dsl.internal; + +import io.fabric8.kubernetes.api.model.DeletionPropagation; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.dsl.base.OperationContext; +import okhttp3.OkHttpClient; + +import java.util.Map; + +public class PodControllerOperationContext extends OperationContext { + protected String containerId; + + public PodControllerOperationContext() { } + + public PodControllerOperationContext(OkHttpClient client, Config config, String plural, String namespace, String name, String containerId, String apiGroupName, String apiGroupVersion, boolean cascading, Object item, Map labels, Map labelsNot, Map labelsIn, Map labelsNotIn, Map fields, Map fieldsNot, String resourceVersion, boolean reloadingFromServer, long gracePeriodSeconds, DeletionPropagation propagationPolicy, long watchRetryInitialBackoffMillis, double watchRetryBackoffMultiplier, boolean isNamespaceFromGlobalConfig, boolean dryRun) { + super(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading, item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, isNamespaceFromGlobalConfig, dryRun); + this.containerId = containerId; + } + + public String getContainerId() { + return containerId; + } + + @Override + public PodControllerOperationContext withOkhttpClient(OkHttpClient client) { + return new PodControllerOperationContext(client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withConfig(Config config) { + return new PodControllerOperationContext(this.client, config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withPlural(String plural) { + return new PodControllerOperationContext(this.client, this.config, plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withNamespace(String namespace) { + return new PodControllerOperationContext(this.client, this.config, this.plural, namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withName(String name) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withApiGroupName(String apiGroupName) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withApiGroupVersion(String apiGroupVersion) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withItem(Object item) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withCascading(boolean cascading) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withLabels(Map labels) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withLabelsIn(Map labelsIn) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withLabelsNot(Map labelsNot) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withLabelsNotIn(Map labelsNotIn) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withFields(Map fields) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withFieldsNot(Map fieldsNot) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withResourceVersion(String resourceVersion) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withReloadingFromServer(boolean reloadingFromServer) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withGracePeriodSeconds(long gracePeriodSeconds) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withPropagationPolicy(DeletionPropagation propagationPolicy) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } + + @Override + public PodControllerOperationContext withDryRun(boolean dryRun) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, this.containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, dryRun); + } + + public PodControllerOperationContext withContainerId(String containerId) { + return new PodControllerOperationContext(this.client, this.config, this.plural, this.namespace, this.name, containerId, this.apiGroupName, + apiGroupVersion, this.cascading, this.item, this.labels, this.labelsNot, this.labelsIn, this.labelsNotIn, + this.fields, this.fieldsNot, this.resourceVersion, this.reloadingFromServer, this.gracePeriodSeconds, + this.propagationPolicy, this.watchRetryInitialBackoffMillis, this.watchRetryBackoffMultiplier, + this.namespaceFromGlobalConfig, this.dryRun); + } +} diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/RollingOperationContext.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/RollingOperationContext.java index 67edb1cff04..24ac8fd9b42 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/RollingOperationContext.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/RollingOperationContext.java @@ -17,13 +17,12 @@ import io.fabric8.kubernetes.api.model.DeletionPropagation; import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.dsl.base.OperationContext; import okhttp3.OkHttpClient; import java.util.Map; import java.util.concurrent.TimeUnit; -public class RollingOperationContext extends OperationContext { +public class RollingOperationContext extends PodControllerOperationContext { private boolean rolling; private long rollingTimeout; @@ -32,8 +31,8 @@ public class RollingOperationContext extends OperationContext { public RollingOperationContext() { } - public RollingOperationContext(OkHttpClient client, Config config, String plural, String namespace, String name, String apiGroupName, String apiGroupVersion, boolean cascading, Object item, Map labels, Map labelsNot, Map labelsIn, Map labelsNotIn, Map fields, Map fieldsNot, String resourceVersion, boolean reloadingFromServer, long gracePeriodSeconds, DeletionPropagation propagationPolicy, long watchRetryInitialBackoffMillis, double watchRetryBackoffMultiplier, boolean rolling, long rollingTimeout, TimeUnit rollingTimeUnit, boolean isNamespaceFromGlobalConfig, boolean dryRun) { - super(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading, item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, isNamespaceFromGlobalConfig, dryRun); + public RollingOperationContext(OkHttpClient client, Config config, String plural, String namespace, String name, String containerId, String apiGroupName, String apiGroupVersion, boolean cascading, Object item, Map labels, Map labelsNot, Map labelsIn, Map labelsNotIn, Map fields, Map fieldsNot, String resourceVersion, boolean reloadingFromServer, long gracePeriodSeconds, DeletionPropagation propagationPolicy, long watchRetryInitialBackoffMillis, double watchRetryBackoffMultiplier, boolean rolling, long rollingTimeout, TimeUnit rollingTimeUnit, boolean isNamespaceFromGlobalConfig, boolean dryRun) { + super(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading, item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, isNamespaceFromGlobalConfig, dryRun); this.rolling = rolling; this.rollingTimeout = rollingTimeout; this.rollingTimeUnit = rollingTimeUnit != null ? rollingTimeUnit : TimeUnit.MILLISECONDS; @@ -52,96 +51,100 @@ public TimeUnit getRollingTimeUnit() { } public RollingOperationContext withOkhttpClient(OkHttpClient client) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withConfig(Config config) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withPlural(String plural) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withNamespace(String namespace) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withName(String name) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withApiGroupName(String apiGroupName) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withApiGroupVersion(String apiGroupVersion) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } @Override public RollingOperationContext withItem(Object item) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withCascading(boolean cascading) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withLabels(Map labels) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withLabelsIn(Map labelsIn) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withLabelsNot(Map labelsNot) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withLabelsNotIn(Map labelsNotIn) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withFields(Map fields) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withFieldsNot(Map fieldsNot) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withResourceVersion(String resourceVersion) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withReloadingFromServer(boolean reloadingFromServer) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withGracePeriodSeconds(long gracePeriodSeconds) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withPropagationPolicy(DeletionPropagation propagationPolicy) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withRolling(boolean rolling) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withRollingTimeout(long rollingTimeout) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } public RollingOperationContext withRollingTimeUnit(TimeUnit rollingTimeUnit) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } @Override public RollingOperationContext withDryRun(boolean dryRun) { - return new RollingOperationContext(client, config, plural, namespace, name, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); + } + + public RollingOperationContext withContainerId(String containerId) { + return new RollingOperationContext(client, config, plural, namespace, name, containerId, apiGroupName, apiGroupVersion, cascading,item, labels, labelsNot, labelsIn, labelsNotIn, fields, fieldsNot, resourceVersion, reloadingFromServer, gracePeriodSeconds, propagationPolicy, watchRetryInitialBackoffMillis, watchRetryBackoffMultiplier, rolling, rollingTimeout, rollingTimeUnit, namespaceFromGlobalConfig, dryRun); } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/DeploymentOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/DeploymentOperationsImpl.java index 8a5e657ba16..601a7b7d6b9 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/DeploymentOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/DeploymentOperationsImpl.java @@ -27,6 +27,7 @@ import io.fabric8.kubernetes.client.dsl.base.PatchContext; import io.fabric8.kubernetes.client.dsl.internal.RollingOperationContext; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; +import io.fabric8.kubernetes.client.utils.PodOperationUtil; import io.fabric8.kubernetes.client.utils.Utils; import okhttp3.OkHttpClient; import io.fabric8.kubernetes.api.model.apps.Deployment; @@ -333,7 +334,7 @@ private List> doGetLog() { ReplicaSetOperationsImpl rsOperations = new ReplicaSetOperationsImpl( new RollingOperationContext(context.getClient(), context.getConfig(), context.getPlural(), context.getNamespace(), - null, context.getApiGroupName(), context.getApiGroupVersion(), context.getCascading(), null, context.getLabels(), + null, ((RollingOperationContext)context).getContainerId(), context.getApiGroupName(), context.getApiGroupVersion(), context.getCascading(), null, context.getLabels(), context.getLabelsNot(), context.getLabelsIn(), context.getLabelsNotIn(), context.getFields(), context.getFieldsNot(), context.getResourceVersion(), context.isReloadingFromServer(), context.getGracePeriodSeconds(), context.getPropagationPolicy(), context.getWatchRetryInitialBackoffMillis(), context.getWatchRetryBackoffMultiplier(), false, 0, null, @@ -356,9 +357,10 @@ private List> doGetLog() { @Override public Reader getLogReader() { List> podResources = doGetLog(); - if (podResources.size() > 1) { - throw new KubernetesClientException("Reading logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { + if (!podResources.isEmpty()) { + if (podResources.size() > 1) { + LOG.debug("Found {} pods, Using first one to get log reader", podResources.size()); + } return podResources.get(0).getLogReader(); } return null; @@ -371,11 +373,12 @@ public LogWatch watchLog() { @Override public LogWatch watchLog(OutputStream out) { - List> podResources = doGetLog(); - if (podResources.size() > 1) { - throw new KubernetesClientException("Watching logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).watchLog(out); + List> replicaSetResources = doGetLog(); + if (!replicaSetResources.isEmpty()) { + if (replicaSetResources.size() > 1) { + LOG.debug("Found {} pods, Using first one to get logs", replicaSetResources.size()); + } + return replicaSetResources.get(0).watchLog(out); } return null; } @@ -415,4 +418,9 @@ static Map getDeploymentSelectorLabels(Deployment deployment) { } return labels; } + + @Override + public Loggable inContainer(String id) { + return new DeploymentOperationsImpl(((RollingOperationContext) context).withContainerId(id)); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/ReplicaSetOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/ReplicaSetOperationsImpl.java index 018e481884b..5028ea831a7 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/ReplicaSetOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/ReplicaSetOperationsImpl.java @@ -35,6 +35,8 @@ import io.fabric8.kubernetes.client.utils.PodOperationUtil; import io.fabric8.kubernetes.client.dsl.internal.RollingOperationContext; import okhttp3.OkHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.OutputStream; import java.io.Reader; @@ -183,18 +185,13 @@ public String getLog() { } public String getLog(Boolean isPretty) { - StringBuilder stringBuilder = new StringBuilder(); - List> podOperationList = doGetLog(isPretty); - for (PodResource podOperation : podOperationList) { - stringBuilder.append(podOperation.getLog(isPretty)); - } - return stringBuilder.toString(); + return PodOperationUtil.getLog(doGetLog(isPretty), isPretty); } private List> doGetLog(boolean isPretty) { ReplicaSet replicaSet = requireFromServer(); return PodOperationUtil.getPodOperationsForController(context, replicaSet.getMetadata().getUid(), - getReplicaSetSelectorLabels(replicaSet), isPretty, podLogWaitTimeout); + getReplicaSetSelectorLabels(replicaSet), isPretty, podLogWaitTimeout, ((RollingOperationContext) context).getContainerId()); } /** @@ -203,13 +200,7 @@ private List> doGetLog(boolean isPretty) { */ @Override public Reader getLogReader() { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Reading logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).getLogReader(); - } - return null; + return PodOperationUtil.getLogReader(doGetLog(false)); } @Override @@ -219,13 +210,7 @@ public LogWatch watchLog() { @Override public LogWatch watchLog(OutputStream out) { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Watching logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).watchLog(out); - } - return null; + return PodOperationUtil.watchLog(doGetLog(false), out); } @Override @@ -246,4 +231,9 @@ static Map getReplicaSetSelectorLabels(ReplicaSet replicaSet) { } return labels; } + + @Override + public Loggable inContainer(String id) { + return newInstance(((RollingOperationContext) context).withContainerId(id)); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java index fbf978836ca..3dc695b9213 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/apps/v1/StatefulSetOperationsImpl.java @@ -38,6 +38,8 @@ import io.fabric8.kubernetes.client.utils.PodOperationUtil; import io.fabric8.kubernetes.client.dsl.internal.RollingOperationContext; import okhttp3.OkHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.OutputStream; @@ -169,19 +171,14 @@ public String getLog() { } public String getLog(Boolean isPretty) { - StringBuilder stringBuilder = new StringBuilder(); - List> podOperationList = doGetLog(isPretty); - for (PodResource podOperation : podOperationList) { - stringBuilder.append(podOperation.getLog(isPretty)); - } - return stringBuilder.toString(); + return PodOperationUtil.getLog(doGetLog(isPretty), isPretty); } private List> doGetLog(boolean isPretty) { StatefulSet statefulSet = requireFromServer(); return PodOperationUtil.getPodOperationsForController(context, statefulSet.getMetadata().getUid(), - getStatefulSetSelectorLabels(statefulSet), isPretty, podLogWaitTimeout); + getStatefulSetSelectorLabels(statefulSet), isPretty, podLogWaitTimeout, ((RollingOperationContext)context).getContainerId()); } /** @@ -190,13 +187,7 @@ private List> doGetLog(boolean isPretty) { */ @Override public Reader getLogReader() { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Reading logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).getLogReader(); - } - return null; + return PodOperationUtil.getLogReader(doGetLog(false)); } @Override @@ -206,13 +197,7 @@ public LogWatch watchLog() { @Override public LogWatch watchLog(OutputStream out) { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Watching logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).watchLog(out); - } - return null; + return PodOperationUtil.watchLog(doGetLog(false), out); } @Override @@ -295,4 +280,9 @@ static Map getStatefulSetSelectorLabels(StatefulSet statefulSet) } return labels; } + + @Override + public Loggable inContainer(String id) { + return newInstance(((RollingOperationContext) context).withContainerId(id)); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java index d813d551ca1..43f263fde4b 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/batch/v1/JobOperationsImpl.java @@ -22,6 +22,7 @@ import io.fabric8.kubernetes.client.dsl.Loggable; import io.fabric8.kubernetes.client.dsl.PodResource; import io.fabric8.kubernetes.client.dsl.base.OperationContext; +import io.fabric8.kubernetes.client.dsl.internal.PodControllerOperationContext; import io.fabric8.kubernetes.client.utils.PodOperationUtil; import okhttp3.OkHttpClient; import io.fabric8.kubernetes.api.model.batch.v1.Job; @@ -59,10 +60,10 @@ public JobOperationsImpl(OkHttpClient client, Config config) { } public JobOperationsImpl(OkHttpClient client, Config config, String namespace) { - this(new OperationContext().withOkhttpClient(client).withConfig(config).withNamespace(namespace).withPropagationPolicy(DEFAULT_PROPAGATION_POLICY)); + this(new PodControllerOperationContext().withOkhttpClient(client).withConfig(config).withNamespace(namespace).withPropagationPolicy(DEFAULT_PROPAGATION_POLICY)); } - public JobOperationsImpl(OperationContext context) { + public JobOperationsImpl(PodControllerOperationContext context) { super(context.withApiGroupName("batch") .withApiGroupVersion("v1") .withPlural("jobs")); @@ -71,21 +72,21 @@ public JobOperationsImpl(OperationContext context) { this.listType = JobList.class; } - private JobOperationsImpl(OperationContext context, Integer podLogWaitTimeout) { + private JobOperationsImpl(PodControllerOperationContext context, Integer podLogWaitTimeout) { this(context); this.podLogWaitTimeout = podLogWaitTimeout; } @Override public JobOperationsImpl newInstance(OperationContext context) { - return new JobOperationsImpl(context); + return new JobOperationsImpl(((PodControllerOperationContext)context)); } @Override public ScalableResource load(InputStream is) { try { Job item = unmarshal(is, Job.class); - return new JobOperationsImpl(context.withItem(item)); + return newInstance(context.withItem(item)); } catch (Throwable t) { throw KubernetesClientException.launderThrowable(t); } @@ -93,7 +94,7 @@ public ScalableResource load(InputStream is) { @Override public ScalableResource fromServer() { - return new JobOperationsImpl(context.withReloadingFromServer(true)); + return newInstance(context.withReloadingFromServer(true)); } @Override @@ -179,7 +180,7 @@ private List> doGetLog(boolean isPretty) { Job job = requireFromServer(); return PodOperationUtil.getPodOperationsForController(context, job.getMetadata().getUid(), - getJobPodLabels(job), isPretty, podLogWaitTimeout); + getJobPodLabels(job), isPretty, podLogWaitTimeout, ((PodControllerOperationContext)context).getContainerId()); } /** @@ -188,13 +189,7 @@ private List> doGetLog(boolean isPretty) { */ @Override public Reader getLogReader() { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Reading logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).getLogReader(); - } - return null; + return PodOperationUtil.getLogReader(doGetLog(false)); } @Override @@ -204,18 +199,12 @@ public LogWatch watchLog() { @Override public LogWatch watchLog(OutputStream out) { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Watching logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).watchLog(out); - } - return null; + return PodOperationUtil.watchLog(doGetLog(false), out); } @Override public Loggable withLogWaitTimeout(Integer logWaitTimeout) { - return new JobOperationsImpl(context, logWaitTimeout); + return new JobOperationsImpl(((PodControllerOperationContext) context), logWaitTimeout); } @Override @@ -250,4 +239,9 @@ static Map getJobPodLabels(Job job) { } return labels; } + + @Override + public Loggable inContainer(String id) { + return new JobOperationsImpl(((PodControllerOperationContext) context).withContainerId(id)); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/ReplicationControllerOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/ReplicationControllerOperationsImpl.java index dfd7ad902aa..cdb144c5fb0 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/ReplicationControllerOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/core/v1/ReplicationControllerOperationsImpl.java @@ -170,19 +170,14 @@ public String getLog() { } public String getLog(Boolean isPretty) { - StringBuilder stringBuilder = new StringBuilder(); - List> podOperationList = doGetLog(isPretty); - for (PodResource podOperation : podOperationList) { - stringBuilder.append(podOperation.getLog(isPretty)); - } - return stringBuilder.toString(); + return PodOperationUtil.getLog(doGetLog(isPretty), isPretty); } private List> doGetLog(boolean isPretty) { ReplicationController rc = requireFromServer(); return PodOperationUtil.getPodOperationsForController(context, rc.getMetadata().getUid(), - getReplicationControllerPodLabels(rc), isPretty, podLogWaitTimeout); + getReplicationControllerPodLabels(rc), isPretty, podLogWaitTimeout, ((RollingOperationContext)context).getContainerId()); } /** @@ -191,13 +186,7 @@ private List> doGetLog(boolean isPretty) { */ @Override public Reader getLogReader() { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Reading logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).getLogReader(); - } - return null; + return PodOperationUtil.getLogReader(doGetLog(false)); } @Override @@ -207,13 +196,7 @@ public LogWatch watchLog() { @Override public LogWatch watchLog(OutputStream out) { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Watching logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).watchLog(out); - } - return null; + return PodOperationUtil.watchLog(doGetLog(false), out); } @Override @@ -253,4 +236,9 @@ static Map getReplicationControllerPodLabels(ReplicationControll } return labels; } + + @Override + public Loggable inContainer(String id) { + return newInstance(((RollingOperationContext) context).withContainerId(id)); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/DeploymentOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/DeploymentOperationsImpl.java index 5f393356194..6441035352e 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/DeploymentOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/DeploymentOperationsImpl.java @@ -339,7 +339,7 @@ private List> doGetLog() { ReplicaSetOperationsImpl rsOperations = new ReplicaSetOperationsImpl( new RollingOperationContext(context.getClient(), context.getConfig(), context.getPlural(), context.getNamespace(), - null, context.getApiGroupName(), context.getApiGroupVersion(), context.getCascading(), null, context.getLabels(), + null, null, context.getApiGroupName(), context.getApiGroupVersion(), context.getCascading(), null, context.getLabels(), context.getLabelsNot(), context.getLabelsIn(), context.getLabelsNotIn(), context.getFields(), context.getFieldsNot(), context.getResourceVersion(), context.isReloadingFromServer(), context.getGracePeriodSeconds(), context.getPropagationPolicy(), context.getWatchRetryInitialBackoffMillis(), context.getWatchRetryBackoffMultiplier(), false, 0, null, @@ -363,9 +363,10 @@ private List> doGetLog() { @Override public Reader getLogReader() { List> podResources = doGetLog(); - if (podResources.size() > 1) { - throw new KubernetesClientException("Reading logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { + if (!podResources.isEmpty()) { + if (podResources.size() > 1) { + LOG.debug("Found {} pods, Using first one to get log reader", podResources.size()); + } return podResources.get(0).getLogReader(); } return null; @@ -379,9 +380,10 @@ public LogWatch watchLog() { @Override public LogWatch watchLog(OutputStream out) { List> podResources = doGetLog(); - if (podResources.size() > 1) { - throw new KubernetesClientException("Watching logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { + if (!podResources.isEmpty()) { + if (podResources.size() > 1) { + LOG.debug("Found {} pods, Using first one to get logs", podResources.size()); + } return podResources.get(0).watchLog(out); } return null; @@ -422,4 +424,9 @@ static Map getDeploymentSelectorLabels(Deployment deployment) { } return labels; } + + @Override + public Loggable inContainer(String id) { + return newInstance(((RollingOperationContext)context).withContainerId(id)); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/ReplicaSetOperationsImpl.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/ReplicaSetOperationsImpl.java index de7bca796ba..b5c632c3e4f 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/ReplicaSetOperationsImpl.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/dsl/internal/extensions/v1beta1/ReplicaSetOperationsImpl.java @@ -197,7 +197,7 @@ public String getLog(Boolean isPretty) { private List> doGetLog(boolean isPretty) { ReplicaSet replicaSet = requireFromServer(); return PodOperationUtil.getPodOperationsForController(context, replicaSet.getMetadata().getUid(), - getReplicaSetSelectorLabels(replicaSet), isPretty, podLogWaitTimeout); + getReplicaSetSelectorLabels(replicaSet), isPretty, podLogWaitTimeout, ((RollingOperationContext)context).getContainerId()); } /** @@ -206,13 +206,7 @@ private List> doGetLog(boolean isPretty) { */ @Override public Reader getLogReader() { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Reading logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).getLogReader(); - } - return null; + return PodOperationUtil.getLogReader(doGetLog(false)); } @Override @@ -222,13 +216,7 @@ public LogWatch watchLog() { @Override public LogWatch watchLog(OutputStream out) { - List> podResources = doGetLog(false); - if (podResources.size() > 1) { - throw new KubernetesClientException("Watching logs is not supported for multicontainer jobs"); - } else if (podResources.size() == 1) { - return podResources.get(0).watchLog(out); - } - return null; + return PodOperationUtil.watchLog(doGetLog(false), out); } @Override @@ -249,4 +237,9 @@ static Map getReplicaSetSelectorLabels(ReplicaSet replicaSet) { } return labels; } + + @Override + public Loggable inContainer(String id) { + return newInstance(((RollingOperationContext)context).withContainerId(id)); + } } diff --git a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/PodOperationUtil.java b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/PodOperationUtil.java index c6456b862de..c6b407bf467 100644 --- a/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/PodOperationUtil.java +++ b/kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/PodOperationUtil.java @@ -18,6 +18,7 @@ import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodList; +import io.fabric8.kubernetes.client.dsl.LogWatch; import io.fabric8.kubernetes.client.dsl.PodResource; import io.fabric8.kubernetes.client.dsl.base.OperationContext; import io.fabric8.kubernetes.client.dsl.internal.PodOperationContext; @@ -25,6 +26,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.OutputStream; +import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -53,19 +56,47 @@ public static List> getFilteredPodsForLogs(PodOperationsImpl po return pods; } - public static PodOperationsImpl getGenericPodOperations(OperationContext context, boolean isPretty, Integer podLogWaitTimeout) { + public static PodOperationsImpl getGenericPodOperations(OperationContext context, boolean isPretty, Integer podLogWaitTimeout, String containerId) { return new PodOperationsImpl(new PodOperationContext(context.getClient(), context.getConfig(), context.getPlural(), context.getNamespace(), null, null, "v1", context.getCascading(), context.getItem(), context.getLabels(), context.getLabelsNot(), context.getLabelsIn(), context.getLabelsNotIn(), context.getFields(), context.getFieldsNot(), context.getResourceVersion(), context.isReloadingFromServer(), context.getGracePeriodSeconds(), context.getPropagationPolicy(), - context.getWatchRetryInitialBackoffMillis(), context.getWatchRetryBackoffMultiplier(), context.isNamespaceFromGlobalConfig(), context.getDryRun(), null, null, null, null, null, + context.getWatchRetryInitialBackoffMillis(), context.getWatchRetryBackoffMultiplier(), context.isNamespaceFromGlobalConfig(), context.getDryRun(), containerId, null, null, null, null, null, null, null, null, false, false, false, null, null, null, isPretty, null, null, null, null, null, podLogWaitTimeout)); } - public static List> getPodOperationsForController(OperationContext context, String controllerUid, Map selectorLabels, boolean isPretty, Integer podLogWaitTimeout) { - return getPodOperationsForController(PodOperationUtil.getGenericPodOperations(context, isPretty, podLogWaitTimeout), controllerUid, selectorLabels); + public static List> getPodOperationsForController(OperationContext context, String controllerUid, Map selectorLabels, boolean isPretty, Integer podLogWaitTimeout, String containerId) { + return getPodOperationsForController(PodOperationUtil.getGenericPodOperations(context, isPretty, podLogWaitTimeout, containerId), controllerUid, selectorLabels); + } + + public static LogWatch watchLog(List> podResources, OutputStream out) { + if (!podResources.isEmpty()) { + if (podResources.size() > 1) { + LOG.debug("Found {} pods, Using first one to watch logs", podResources.size()); + } + return podResources.get(0).watchLog(out); + } + return null; + } + + public static Reader getLogReader(List> podResources) { + if (!podResources.isEmpty()) { + if (podResources.size() > 1) { + LOG.debug("Found {} pods, Using first one to get log reader", podResources.size()); + } + return podResources.get(0).getLogReader(); + } + return null; + } + + public static String getLog(List> podOperationList, Boolean isPretty) { + StringBuilder stringBuilder = new StringBuilder(); + for (PodResource podOperation : podOperationList) { + stringBuilder.append(podOperation.getLog(isPretty)); + } + return stringBuilder.toString(); } static List> getPodOperationsForController(PodOperationsImpl podOperations, String controllerUid, Map selectorLabels) { diff --git a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/PodOperationUtilTest.java b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/PodOperationUtilTest.java index 7ea703326c9..861651edf4e 100644 --- a/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/PodOperationUtilTest.java +++ b/kubernetes-client/src/test/java/io/fabric8/kubernetes/client/utils/PodOperationUtilTest.java @@ -21,6 +21,7 @@ import io.fabric8.kubernetes.api.model.PodListBuilder; import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable; import io.fabric8.kubernetes.client.dsl.Gettable; +import io.fabric8.kubernetes.client.dsl.LogWatch; import io.fabric8.kubernetes.client.dsl.PodResource; import io.fabric8.kubernetes.client.dsl.base.OperationContext; import io.fabric8.kubernetes.client.dsl.internal.core.v1.PodOperationsImpl; @@ -30,15 +31,19 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import java.io.ByteArrayOutputStream; +import java.io.Reader; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -71,11 +76,12 @@ void testGetFilteredPodsForLogs() { @Test void testGetGenericPodOperations() { // When - PodOperationsImpl podOperations = PodOperationUtil.getGenericPodOperations(operationContext, false, 5); + PodOperationsImpl podOperations = PodOperationUtil.getGenericPodOperations(operationContext, false, 5, "container1"); // Then - assertNotNull(podOperations); - assertNull(podOperations.getName()); + assertThat(podOperations).isNotNull(); + assertThat(podOperations.getName()).isNull(); + assertThat(podOperations.getContext().getContainerId()).isEqualTo("container1"); } @Test @@ -112,6 +118,78 @@ void testGetPodOperationsForController() { assertEquals(1, podResources.size()); } + @Test + void testWatchLogSinglePod() { + // Given + PodResource podResource = Mockito.mock(PodResource.class, Mockito.RETURNS_DEEP_STUBS); + ByteArrayOutputStream byteArrayOutputStream = Mockito.mock(ByteArrayOutputStream.class, Mockito.RETURNS_DEEP_STUBS); + + // When + LogWatch logWatch = PodOperationUtil.watchLog(createMockPodResourceList(podResource), byteArrayOutputStream); + + // Then + assertThat(logWatch).isNotNull(); + verify(podResource, times(1)).watchLog(byteArrayOutputStream); + } + + @Test + void testWatchLogMultiplePodReplicasPicksFirstPod() { + // Given + PodResource p1 = Mockito.mock(PodResource.class, Mockito.RETURNS_DEEP_STUBS); + PodResource p2 = Mockito.mock(PodResource.class, Mockito.RETURNS_DEEP_STUBS); + ByteArrayOutputStream byteArrayOutputStream = Mockito.mock(ByteArrayOutputStream.class, Mockito.RETURNS_DEEP_STUBS); + + // When + LogWatch logWatch = PodOperationUtil.watchLog(createMockPodResourceList(p1, p2), byteArrayOutputStream); + + // Then + assertThat(logWatch).isNotNull(); + verify(p1, times(1)).watchLog(byteArrayOutputStream); + verify(p2, times(0)).watchLog(byteArrayOutputStream); + } + + @Test + void testWatchLogEmptyPodResourceList() { + assertThat(PodOperationUtil.watchLog(Collections.emptyList(), null)).isNull(); + } + + @Test + void testGetLogReaderEmptyPodResourceList() { + assertThat(PodOperationUtil.getLogReader(Collections.emptyList())).isNull(); + } + + @Test + void testGetLogReaderMultiplePodReplicasPicksFirstPod() { + // Given + PodResource p1 = Mockito.mock(PodResource.class, Mockito.RETURNS_DEEP_STUBS); + PodResource p2 = Mockito.mock(PodResource.class, Mockito.RETURNS_DEEP_STUBS); + + // When + Reader reader = PodOperationUtil.getLogReader(createMockPodResourceList(p1, p2)); + + // Then + assertThat(reader).isNotNull(); + verify(p1, times(1)).getLogReader(); + verify(p2, times(0)).getLogReader(); + } + + @Test + void testGetLog() { + // Given + PodResource p1 = Mockito.mock(PodResource.class, Mockito.RETURNS_DEEP_STUBS); + PodResource p2 = Mockito.mock(PodResource.class, Mockito.RETURNS_DEEP_STUBS); + when(p1.getLog(anyBoolean())).thenReturn("p1-log"); + when(p2.getLog(anyBoolean())).thenReturn("p2-log"); + + // When + String result = PodOperationUtil.getLog(createMockPodResourceList(p1, p2), false); + + // Then + assertThat(result).isNotNull().isEqualTo("p1-logp2-log"); + verify(p1, times(1)).getLog(false); + verify(p2, times(1)).getLog(false); + } + private PodList getMockPodList(String controllerUid) { return new PodListBuilder() .addToItems( @@ -138,4 +216,11 @@ public PodList answer(InvocationOnMock invocation) throws Throwable { }); return result; } + + @SafeVarargs + private final List> createMockPodResourceList(PodResource... podResources) { + List> podResourceList = new ArrayList<>(); + Collections.addAll(podResourceList, podResources); + return podResourceList; + } } diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DeploymentTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DeploymentTest.java index be670a31756..f386101f11d 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DeploymentTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/DeploymentTest.java @@ -466,9 +466,9 @@ void testRolloutUpdateSingleImage() throws InterruptedException { // Given String imageToUpdate = "nginx:latest"; server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(imageToUpdate) .endContainer().endSpec().endTemplate().endSpec() @@ -492,9 +492,9 @@ void testRolloutUpdateImage() throws InterruptedException { // Given Map containerToImageMap = Collections.singletonMap("nginx", "nginx:latest"); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(containerToImageMap.get("nginx")) .endContainer().endSpec().endTemplate().endSpec() @@ -517,9 +517,9 @@ void testRolloutUpdateImage() throws InterruptedException { void testRolloutPause() throws InterruptedException { // Given server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).once(); // When Deployment deployment = client.apps().deployments().inNamespace("ns1").withName("deploy1") @@ -536,9 +536,9 @@ void testRolloutPause() throws InterruptedException { void testRolloutResume() throws InterruptedException { // Given server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).once(); // When Deployment deployment = client.apps().deployments().inNamespace("ns1").withName("deploy1") @@ -556,9 +556,9 @@ void testRolloutResume() throws InterruptedException { void testRolloutRestart() throws InterruptedException { // Given server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).once(); // When Deployment deployment = client.apps().deployments().inNamespace("ns1").withName("deploy1") @@ -627,9 +627,9 @@ void testRolloutUndo() throws InterruptedException { server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets?labelSelector=" + Utils.toUrlEncoded("app=nginx")) .andReturn(HttpURLConnection.HTTP_OK, new ReplicaSetListBuilder().withItems(replicaSetRevision1, replicaSetRevision2).build()).once(); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()).once(); // When Deployment deployment = client.apps().deployments().inNamespace("ns1").withName("deploy1") @@ -646,44 +646,10 @@ void testRolloutUndo() throws InterruptedException { @DisplayName("Should get logs for a Deployment") void testDeploymentGetLog() { // Given - ReplicaSet replicaSet = new ReplicaSetBuilder() - .withNewMetadata() - .withOwnerReferences( - new OwnerReferenceBuilder() - .withApiVersion("apps/v1") - .withBlockOwnerDeletion(true) - .withController(true) - .withKind("Deployment") - .withName("deploy1") - .withUid("136581bf-82c2-4675-af05-63c55500b378") - .build() - ) - .withName("deploy1-hk9nf") - .addToLabels("app", "nginx") - .withUid("3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") - .endMetadata() - .withNewSpec() - .withNewSelector() - .addToMatchLabels("app", "nginx") - .endSelector() - .endSpec() - .build(); - - Pod deployPod = new PodBuilder() - .withNewMetadata() - .withOwnerReferences(new OwnerReferenceBuilder().withApiVersion("apps/v1") - .withBlockOwnerDeletion(true) - .withController(true) - .withKind("ReplicaSet") - .withName("1") - .withUid("3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") - .build()) - .withName("deploy1-hk9nf").addToLabels("controller-uid", "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") - .endMetadata() - .build(); - + ReplicaSet replicaSet = createMockReplicaSet("deploy1", "136581bf-82c2-4675-af05-63c55500b378", "deploy1-hk9nf", Collections.singletonMap("app", "nginx"), "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4"); + Pod deployPod = createMockPod("1", "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4", "deploy1-hk9nf", Collections.singletonMap("controller-uid", "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4")); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy1") - .andReturn(HttpURLConnection.HTTP_OK, getDeploymentBuilder().build()) + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().build()) .always(); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets?labelSelector=app%3Dnginx") @@ -707,7 +673,56 @@ void testDeploymentGetLog() { assertEquals("hello", log); } - private DeploymentBuilder getDeploymentBuilder() { + @Test + void testDeploymentGetLogMultiContainer() { + // Given + ReplicaSet replicaSet = createMockReplicaSet("deploy-multi1", "93b8b619-731a-435a-bcb0-4b0c19f07f2f", "multi-container-deploy-5dfdf5ddfc", Collections.singletonMap("app", "nginx"), "f9ed6d37-9256-44aa-93b0-4af70e046348"); + Pod deployPod = createMockPod("multi-container-deploy-5dfdf5ddfc", "f9ed6d37-9256-44aa-93b0-4af70e046348", "multi-container-deploy-5dfdf5ddfc-r6q4j", Collections.singletonMap("controller-uid", "f9ed6d37-9256-44aa-93b0-4af70e046348")); + + server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/deployments/deploy-multi1") + .andReturn(HttpURLConnection.HTTP_OK, createDeploymentBuilder().editMetadata() + .withName("deploy-multi1") + .withUid("93b8b619-731a-435a-bcb0-4b0c19f07f2f") + .endMetadata().build()) + .always(); + + server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets?labelSelector=app%3Dnginx") + .andReturn(HttpURLConnection.HTTP_OK, new ReplicaSetListBuilder().withItems(replicaSet).build()) + .once(); + server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets/multi-container-deploy-5dfdf5ddfc") + .andReturn(HttpURLConnection.HTTP_OK, replicaSet) + .once(); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=app%3Dnginx") + .andReturn(HttpURLConnection.HTTP_OK, new PodListBuilder().withItems(deployPod).build()) + .once(); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods/multi-container-deploy-5dfdf5ddfc-r6q4j/log?pretty=false&container=container1") + .andReturn(HttpURLConnection.HTTP_OK, "hello") + .once(); + + // When + String log = client.apps().deployments().inNamespace("ns1").withName("deploy-multi1").inContainer("container1").getLog(); + + // Then + assertNotNull(log); + assertEquals("hello", log); + } + + @Test + void testDeploymentLoadWithoutApiVersion() { + // Given + + // When + List list = client.load(getClass().getResourceAsStream("/valid-deployment-without-apiversion.json")).get(); + Deployment deployment = (Deployment) list.get(0); + + // Then + assertNotNull(deployment); + assertEquals("test", deployment.getMetadata().getName()); + assertEquals(1, deployment.getSpec().getReplicas()); + assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); + } + + private DeploymentBuilder createDeploymentBuilder() { return new DeploymentBuilder() .withNewMetadata() .withName("deploy1") @@ -733,19 +748,44 @@ private DeploymentBuilder getDeploymentBuilder() { .endSpec(); } - @Test - void testDeploymentLoadWithoutApiVersion() { - // Given - - // When - List list = client.load(getClass().getResourceAsStream("/valid-deployment-without-apiversion.json")).get(); - Deployment deployment = (Deployment) list.get(0); + private ReplicaSet createMockReplicaSet(String ownerDeploymentName, String deploymentUid, String name, Map labels, String uid) { + return new ReplicaSetBuilder() + .withNewMetadata() + .withOwnerReferences( + new OwnerReferenceBuilder() + .withApiVersion("apps/v1") + .withBlockOwnerDeletion(true) + .withController(true) + .withKind("Deployment") + .withName(ownerDeploymentName) + .withUid(deploymentUid) + .build() + ) + .withName(name) + .addToLabels(labels) + .withUid(uid) + .endMetadata() + .withNewSpec() + .withNewSelector() + .withMatchLabels(labels) + .endSelector() + .endSpec() + .build(); + } - // Then - assertNotNull(deployment); - assertEquals("test", deployment.getMetadata().getName()); - assertEquals(1, deployment.getSpec().getReplicas()); - assertEquals(1, deployment.getSpec().getTemplate().getSpec().getContainers().size()); + private Pod createMockPod(String replicaSetName, String replicaSetUid, String name, Map labels) { + return new PodBuilder() + .withNewMetadata() + .withOwnerReferences(new OwnerReferenceBuilder().withApiVersion("apps/v1") + .withBlockOwnerDeletion(true) + .withController(true) + .withKind("ReplicaSet") + .withName(replicaSetName) + .withUid(replicaSetUid) + .build()) + .withName(name).addToLabels(labels) + .endMetadata() + .build(); } } diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/JobTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/JobTest.java index 7b78e1fabab..f7ccefb7640 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/JobTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/JobTest.java @@ -244,7 +244,7 @@ public void testCreateWithNameMismatch() { @DisplayName("Should append Selector and MatchLabels from exiting job instance while patching a Job") public void testCreateOrReplaceWithExistingJob() { // Given - Job jobExistingInServer = getJobBuilder() + Job jobExistingInServer = createJobBuilder() .editSpec() .editOrNewTemplate().editOrNewMetadata() .addToLabels("controller-uid", "df842342-33bb-4f6c-9707-f76a86748ee6") @@ -260,7 +260,7 @@ public void testCreateOrReplaceWithExistingJob() { server.expect().post().withPath("/apis/batch/v1/namespaces/test/jobs") .andReturn(HttpURLConnection.HTTP_CONFLICT, jobExistingInServer).once(); server.expect().put().withPath("/apis/batch/v1/namespaces/test/jobs/job1") - .andReturn(HttpURLConnection.HTTP_OK, getJobBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createJobBuilder() .editOrNewMetadata().addToLabels("foo", "bar").addToLabels("foo1", "bar1").endMetadata() .editSpec() .editOrNewTemplate().editOrNewMetadata() @@ -272,7 +272,7 @@ public void testCreateOrReplaceWithExistingJob() { .endSpec() .build()).once(); - Job job = getJobBuilder() + Job job = createJobBuilder() .editOrNewMetadata().addToLabels("foo", "bar").addToLabels("foo1", "bar1").endMetadata() .build(); @@ -293,21 +293,10 @@ public void testCreateOrReplaceWithExistingJob() { @DisplayName("Should get logs for a job") void testJobGetLog() { // Given - Pod jobPod = new PodBuilder() - .withNewMetadata() - .withOwnerReferences(new OwnerReferenceBuilder().withApiVersion("batch/v1") - .withBlockOwnerDeletion(true) - .withController(true) - .withKind("Job") - .withName("pi") - .withUid("3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") - .build()) - .withName("job1-hk9nf").addToLabels("controller-uid", "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") - .endMetadata() - .build(); + Pod jobPod = createJobPod(); server.expect().get().withPath("/apis/batch/v1/namespaces/ns1/jobs/job1") - .andReturn(HttpURLConnection.HTTP_OK, getJobBuilder().build()) + .andReturn(HttpURLConnection.HTTP_OK, createJobBuilder().build()) .always(); server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=controller-uid%3D3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") @@ -325,7 +314,47 @@ void testJobGetLog() { assertEquals("hello", log); } - private JobBuilder getJobBuilder() { + @Test + @DisplayName("Should get logs for a multi-container job") + void testJobGetLogMultiContainer() { + // Given + Pod jobPod = createJobPod(); + + server.expect().get().withPath("/apis/batch/v1/namespaces/ns1/jobs/job1") + .andReturn(HttpURLConnection.HTTP_OK, createJobBuilder().build()) + .always(); + + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=controller-uid%3D3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") + .andReturn(HttpURLConnection.HTTP_OK, new PodListBuilder().withItems(jobPod).build()) + .once(); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods/job1-hk9nf/log?pretty=false&container=c1") + .andReturn(HttpURLConnection.HTTP_OK, "hello") + .once(); + + // When + String log = client.batch().v1().jobs().inNamespace("ns1").withName("job1").inContainer("c1").getLog(); + + // Then + assertNotNull(log); + assertEquals("hello", log); + } + + private Pod createJobPod() { + return new PodBuilder() + .withNewMetadata() + .withOwnerReferences(new OwnerReferenceBuilder().withApiVersion("batch/v1") + .withBlockOwnerDeletion(true) + .withController(true) + .withKind("Job") + .withName("pi") + .withUid("3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") + .build()) + .withName("job1-hk9nf").addToLabels("controller-uid", "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") + .endMetadata() + .build(); + } + + private JobBuilder createJobBuilder() { return new JobBuilder() .withApiVersion("batch/v1") .withNewMetadata() diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicaSetTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicaSetTest.java index c5b767d8ee3..3c1ecc35c2c 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicaSetTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicaSetTest.java @@ -28,7 +28,6 @@ import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.kubernetes.client.utils.Utils; -import okhttp3.mockwebserver.RecordedRequest; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -272,9 +271,9 @@ void testRolloutUpdateSingleImage() throws InterruptedException { // Given String imageToUpdate = "nginx:latest"; server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets/replicaset1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicaSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createReplicaSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/replicasets/replicaset1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicaSetBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createReplicaSetBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(imageToUpdate) .endContainer().endSpec().endTemplate().endSpec() @@ -297,9 +296,9 @@ void testRolloutUpdateImage() throws InterruptedException { // Given Map containerToImageMap = Collections.singletonMap("nginx", "nginx:latest"); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets/replicaset1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicaSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createReplicaSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/replicasets/replicaset1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicaSetBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createReplicaSetBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(containerToImageMap.get("nginx")) .endContainer().endSpec().endTemplate().endSpec() @@ -317,7 +316,7 @@ void testRolloutUpdateImage() throws InterruptedException { @Test void testGetLog() { - ReplicaSet replicaSet = getReplicaSetBuilder().build(); + ReplicaSet replicaSet = createReplicaSetBuilder().build(); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets/replicaset1") .andReturn(HttpURLConnection.HTTP_OK, replicaSet).times(3); server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=" + Utils.toUrlEncoded("app=nginx")) @@ -333,7 +332,25 @@ void testGetLog() { assertEquals("testlog", log); } - private ReplicaSetBuilder getReplicaSetBuilder() { + @Test + void testGetLogMultiContainer() { + ReplicaSet replicaSet = createReplicaSetBuilder().build(); + server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/replicasets/replicaset1") + .andReturn(HttpURLConnection.HTTP_OK, replicaSet).times(3); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=" + Utils.toUrlEncoded("app=nginx")) + .andReturn(HttpURLConnection.HTTP_OK, getReplicaSetPodList(replicaSet)).once(); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods/pod1/log?pretty=true&container=c1") + .andReturn(HttpURLConnection.HTTP_OK, "testlog").once(); + + // When + String log = client.apps().replicaSets().inNamespace("ns1").withName("replicaset1").inContainer("c1").getLog(true); + + // Then + assertNotNull(log); + assertEquals("testlog", log); + } + + private ReplicaSetBuilder createReplicaSetBuilder() { return new ReplicaSetBuilder() .withNewMetadata() .withName("replicaset1") diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicationControllerTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicationControllerTest.java index 9d94abccab9..d77803dbf2f 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicationControllerTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/ReplicationControllerTest.java @@ -28,7 +28,6 @@ import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer; import io.fabric8.kubernetes.client.utils.Utils; -import okhttp3.mockwebserver.RecordedRequest; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -245,9 +244,9 @@ void testRolloutUpdateSingleImage() throws InterruptedException { // Given String imageToUpdate = "nginx:latest"; server.expect().get().withPath("/api/v1/namespaces/ns1/replicationcontrollers/replicationcontroller1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicationControllerBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createReplicationControllerBuilder().build()).times(3); server.expect().patch().withPath("/api/v1/namespaces/ns1/replicationcontrollers/replicationcontroller1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicationControllerBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createReplicationControllerBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(imageToUpdate) .endContainer().endSpec().endTemplate().endSpec() @@ -269,9 +268,9 @@ void testRolloutUpdateImage() throws InterruptedException { // Given Map containerToImageMap = Collections.singletonMap("nginx", "nginx:latest"); server.expect().get().withPath("/api/v1/namespaces/ns1/replicationcontrollers/replicationcontroller1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicationControllerBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createReplicationControllerBuilder().build()).times(3); server.expect().patch().withPath("/api/v1/namespaces/ns1/replicationcontrollers/replicationcontroller1") - .andReturn(HttpURLConnection.HTTP_OK, getReplicationControllerBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createReplicationControllerBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(containerToImageMap.get("nginx")) .endContainer().endSpec().endTemplate().endSpec() @@ -290,7 +289,7 @@ void testRolloutUpdateImage() throws InterruptedException { @Test void testGetLog() { // Given - ReplicationController replicationController = getReplicationControllerBuilder().build(); + ReplicationController replicationController = createReplicationControllerBuilder().build(); server.expect().get().withPath("/api/v1/namespaces/ns1/replicationcontrollers/replicationcontroller1") .andReturn(HttpURLConnection.HTTP_OK, replicationController).times(3); server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=" + Utils.toUrlEncoded("app=nginx")) @@ -306,7 +305,26 @@ void testGetLog() { assertEquals("testlog", log); } - private ReplicationControllerBuilder getReplicationControllerBuilder() { + @Test + void testGetLogMultiContainer() { + // Given + ReplicationController replicationController = createReplicationControllerBuilder().build(); + server.expect().get().withPath("/api/v1/namespaces/ns1/replicationcontrollers/replicationcontroller1") + .andReturn(HttpURLConnection.HTTP_OK, replicationController).times(3); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=" + Utils.toUrlEncoded("app=nginx")) + .andReturn(HttpURLConnection.HTTP_OK, getReplicationControllerPodList(replicationController)).once(); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods/pod1/log?pretty=false&container=c1") + .andReturn(HttpURLConnection.HTTP_OK, "testlog").once(); + + // When + String log = client.replicationControllers().inNamespace("ns1").withName("replicationcontroller1").inContainer("c1").getLog(); + + // Then + assertNotNull(log); + assertEquals("testlog", log); + } + + private ReplicationControllerBuilder createReplicationControllerBuilder() { return new ReplicationControllerBuilder() .withNewMetadata() .withName("replicationcontroller1") diff --git a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/StatefulSetTest.java b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/StatefulSetTest.java index 63f7627a577..5019f7d7993 100644 --- a/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/StatefulSetTest.java +++ b/kubernetes-tests/src/test/java/io/fabric8/kubernetes/client/mock/StatefulSetTest.java @@ -260,9 +260,9 @@ void testRolloutUpdateSingleImage() throws InterruptedException { // Given String imageToUpdate = "nginx:latest"; server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(imageToUpdate) .endContainer().endSpec().endTemplate().endSpec() @@ -286,9 +286,9 @@ void testRolloutUpdateImage() throws InterruptedException { // Given Map containerToImageMap = Collections.singletonMap("nginx", "nginx:latest"); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder() + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder() .editSpec().editTemplate().editSpec().editContainer(0) .withImage(containerToImageMap.get("nginx")) .endContainer().endSpec().endTemplate().endSpec() @@ -309,9 +309,9 @@ void testRolloutUpdateImage() throws InterruptedException { void testRolloutPause() throws InterruptedException { // Given server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).once(); // When StatefulSet deployment = client.apps().statefulSets().inNamespace("ns1").withName("statefulset1") @@ -328,9 +328,9 @@ void testRolloutPause() throws InterruptedException { void testRolloutResume() throws InterruptedException { // Given server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).once(); // When StatefulSet deployment = client.apps().statefulSets().inNamespace("ns1").withName("statefulset1") @@ -347,9 +347,9 @@ void testRolloutResume() throws InterruptedException { void testRolloutRestart() throws InterruptedException { // Given server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).once(); // When StatefulSet deployment = client.apps().statefulSets().inNamespace("ns1").withName("statefulset1") @@ -424,9 +424,9 @@ void testRolloutUndo() throws InterruptedException { server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/controllerrevisions?labelSelector=" + Utils.toUrlEncoded("app=nginx")) .andReturn(HttpURLConnection.HTTP_OK, new ControllerRevisionListBuilder().withItems(controllerRevision1, controllerRevision2).build()).once(); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).times(3); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).times(3); server.expect().patch().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()).once(); + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()).once(); // When StatefulSet deployment = client.apps().statefulSets().inNamespace("ns1").withName("statefulset1") @@ -442,21 +442,10 @@ void testRolloutUndo() throws InterruptedException { @DisplayName("Should test get logs from statefulset") void testGetLogStatefulSet() { // Given - Pod jobPod = new PodBuilder() - .withNewMetadata() - .withOwnerReferences(new OwnerReferenceBuilder().withApiVersion("apps/v1") - .withBlockOwnerDeletion(true) - .withController(true) - .withKind("StatefulSet") - .withName("pi") - .withUid("3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") - .build()) - .withName("ss-hk9nf").addToLabels("controller-uid", "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") - .endMetadata() - .build(); + Pod jobPod = createPod(); server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") - .andReturn(HttpURLConnection.HTTP_OK, getStatefulSetBuilder().build()) + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()) .always(); server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=app%3Dnginx") @@ -474,7 +463,47 @@ void testGetLogStatefulSet() { assertEquals("hello", log); } - private StatefulSetBuilder getStatefulSetBuilder() { + @Test + @DisplayName("Should test get logs from multi-container statefulset") + void testGetLogStatefulSetMultiContainer() { + // Given + Pod jobPod = createPod(); + + server.expect().get().withPath("/apis/apps/v1/namespaces/ns1/statefulsets/statefulset1") + .andReturn(HttpURLConnection.HTTP_OK, createStatefulSetBuilder().build()) + .always(); + + server.expect().get().withPath("/api/v1/namespaces/ns1/pods?labelSelector=app%3Dnginx") + .andReturn(HttpURLConnection.HTTP_OK, new PodListBuilder().withItems(jobPod).build()) + .once(); + server.expect().get().withPath("/api/v1/namespaces/ns1/pods/ss-hk9nf/log?pretty=false&container=c1") + .andReturn(HttpURLConnection.HTTP_OK, "hello") + .once(); + + // When + String log = client.apps().statefulSets().inNamespace("ns1").withName("statefulset1").inContainer("c1").getLog(); + + // Then + assertNotNull(log); + assertEquals("hello", log); + } + + private Pod createPod() { + return new PodBuilder() + .withNewMetadata() + .withOwnerReferences(new OwnerReferenceBuilder().withApiVersion("apps/v1") + .withBlockOwnerDeletion(true) + .withController(true) + .withKind("StatefulSet") + .withName("pi") + .withUid("3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") + .build()) + .withName("ss-hk9nf").addToLabels("controller-uid", "3Dc4c8746c-94fd-47a7-ac01-11047c0323b4") + .endMetadata() + .build(); + } + + private StatefulSetBuilder createStatefulSetBuilder() { return new StatefulSetBuilder() .withNewMetadata() .withName("statefulset1") diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java index 687fe63b7b9..8b4dab6e465 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/apps/DeploymentConfigOperationsImpl.java @@ -227,7 +227,7 @@ public String getLog() { @Override public String getLog(Boolean isPretty) { - try(ResponseBody body = doGetLog(isPretty)) { + try { return doGetLog(isPretty).string(); } catch (IOException e) { throw KubernetesClientException.launderThrowable(forOperationType("getLog"), e); @@ -301,7 +301,7 @@ public DeploymentConfig edit(Visitor... visitors) { private void waitUntilDeploymentConfigPodBecomesReady(DeploymentConfig deploymentConfig) { List> podOps = PodOperationUtil.getPodOperationsForController(context, deploymentConfig.getMetadata().getUid(), - getDeploymentConfigPodLabels(deploymentConfig), false, podLogWaitTimeout); + getDeploymentConfigPodLabels(deploymentConfig), false, podLogWaitTimeout, ((RollingOperationContext)context).getContainerId()); waitForBuildPodToBecomeReady(podOps, podLogWaitTimeout != null ? podLogWaitTimeout : DEFAULT_POD_LOG_WAIT_TIMEOUT); } @@ -319,4 +319,9 @@ static Map getDeploymentConfigPodLabels(DeploymentConfig deploym } return labels; } + + @Override + public Loggable inContainer(String id) { + return newInstance(((RollingOperationContext) context).withContainerId(id)); + } } diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildOperationsImpl.java index e87417d2351..65146db00af 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildOperationsImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/build/BuildOperationsImpl.java @@ -256,7 +256,7 @@ public BytesLimitTerminateTimeTailPrettyLoggable usingTimestamps() { private void waitUntilBuildPodBecomesReady(Build build) { List> podOps = PodOperationUtil.getPodOperationsForController(context, build.getMetadata().getUid(), - getBuildPodLabels(build), withPrettyOutput, podLogWaitTimeout); + getBuildPodLabels(build), withPrettyOutput, podLogWaitTimeout, null); waitForBuildPodToBecomeReady(podOps, podLogWaitTimeout != null ? podLogWaitTimeout : DEFAULT_POD_LOG_WAIT_TIMEOUT); }