8000 Added new unit test for OWLS-87553 and modified existing managed server startup unit tests by ankedia · Pull Request #2213 · oracle/weblogic-kubernetes-operator · GitHub
[go: up one dir, main page]

Skip to content

Added new unit test for OWLS-87553 and modified existing managed server startup unit tests #2213

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
8000 Jump to file
Failed to load files.
Loading
Diff view
Diff view
8000
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.kubernetes.client.openapi.models.V1PodStatus;
import io.kubernetes.client.util.Watch;
import oracle.kubernetes.operator.builders.StubWatchFactory;
import oracle.kubernetes.operator.helpers.DomainPresenceInfo;
import oracle.kubernetes.operator.helpers.KubernetesTestSupport;
import oracle.kubernetes.operator.watcher.WatchListener;
import oracle.kubernetes.operator.work.Step;
Expand Down Expand Up @@ -237,6 +238,13 @@ public void whenPodReadyLater_runNextStep() {
assertThat(terminalStep.wasRun(), is(true));
}

@Test
public void whenPodCreatedAndReadyLater_runNextStep() {
sendPodModifiedWatchAfterResourceCreatedAndWaitForReady(this::markPodReady);

assertThat(terminalStep.wasRun(), is(true));
}

@Test
public void whenPodNotReadyLater_dontRunNextStep() {
sendPodModifiedWatchAfterWaitForReady(this::dontChangePod);
Expand Down Expand Up @@ -293,6 +301,23 @@ private void sendPodModifiedWatchAfterWaitForReady(Function<V1Pod,V1Pod>... modi
}
}

// Starts the waitForReady step with an uncreated pod and sends a watch indicating that the pod has changed
@SafeVarargs
private void sendPodModifiedWatchAfterResourceCreatedAndWaitForReady(Function<V1Pod,V1Pod>... modifiers) {
AtomicBoolean stopping = new AtomicBoolean(false);
PodWatcher watcher = createWatcher(stopping);

try {
testSupport.addDomainPresenceInfo(new DomainPresenceInfo(NS, "domain1"));
testSupport.runSteps(watcher.waitForReady(NAME, terminalStep));
for (Function<V1Pod,V1Pod> modifier : modifiers) {
watcher.receivedResponse(new Watch.Response<>("MODIFIED", modifier.apply(createPod())));
}
} finally {
stopping.set(true);
}
}

// Simulates a pod that is ready but where Kubernetes has failed to send the watch event
@SafeVarargs
private void makeModifiedPodReadyWithNoWatchEvent(Function<V1Pod,V1Pod>... modifiers) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public Thread newThread(@Nonnull Runnable r) {
return thread;
}

void shutDownThreads() {
protected void shutDownThreads() {
for (Thread thread : threads) {
shutDown(thread);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package oracle.kubernetes.operator.steps;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -11,6 +12,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nonnull;
Expand All @@ -23,14 +25,21 @@
import io.kubernetes.client.openapi.models.V1PodSpec;
import io.kubernetes.client.openapi.models.V1PodStatus;
import io.kubernetes.client.openapi.models.V1SecretReference;
import io.kubernetes.client.util.Watch;
import oracle.kubernetes.operator.KubernetesConstants;
import oracle.kubernetes.operator.PodAwaiterStepFactory;
import oracle.kubernetes.operator.PodWatcher;
import oracle.kubernetes.operator.ProcessingConstants;
import oracle.kubernetes.operator.ThreadFactoryTestBase;
import oracle.kubernetes.operator.TuningParameters;
import oracle.kubernetes.operator.builders.StubWatchFactory;
import oracle.kubernetes.operator.helpers.DomainPresenceInfo;
import oracle.kubernetes.operator.helpers.DomainPresenceInfo.ServerStartupInfo;
import oracle.kubernetes.operator.helpers.KubernetesTestSupport;
import oracle.kubernetes.operator.helpers.LegalNames;
import oracle.kubernetes.operator.helpers.TuningParametersStub;
import oracle.kubernetes.operator.utils.WlsDomainConfigSupport;
import oracle.kubernetes.operator.watcher.WatchListener;
import oracle.kubernetes.operator.wlsconfig.WlsClusterConfig;
import oracle.kubernetes.operator.wlsconfig.WlsDomainConfig;
import oracle.kubernetes.operator.wlsconfig.WlsServerConfig;
Expand All @@ -48,14 +57,16 @@

import static oracle.kubernetes.operator.LabelConstants.CLUSTERNAME_LABEL;
import static oracle.kubernetes.operator.LabelConstants.SERVERNAME_LABEL;
import static oracle.kubernetes.operator.helpers.KubernetesTestSupport.POD;
import static oracle.kubernetes.operator.steps.ManagedServerUpIteratorStep.SCHEDULING_DETECTION_DELAY;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.junit.MatcherAssert.assertThat;

public class ManagedServerUpIteratorStepTest {
public class ManagedServerUpIteratorStepTest extends ThreadFactoryTestBase implements WatchListener<V1Pod>,
StubWatchFactory.AllWatchesClosedListener {

< 8000 /td> protected static final String DOMAIN_NAME = "domain1";
private static final String NS = "namespace";
Expand All @@ -81,6 +92,10 @@ public class ManagedServerUpIteratorStepTest {
private static final String[] MANAGED_SERVER_NAMES =
IntStream.rangeClosed(1, MAX_SERVERS)
.mapToObj(ManagedServerUpIteratorStepTest::getManagedServerName).toArray(String[]::new);
private final AtomicBoolean stopping = new AtomicBoolean(false);
private static final BigInteger INITIAL_RESOURCE_VERSION = new BigInteger("234");
private final PodWatcher watcher = createWatcher(NS, stopping, INITIAL_RESOURCE_VERSION);
final TuningParameters.WatchTuning tuning = new TuningParameters.WatchTuning(30, 0, 5);

@Nonnull
private static String getManagedServerName(int n) {
Expand Down Expand Up @@ -158,32 +173,39 @@ private static V1ObjectMeta withNames(V1ObjectMeta objectMeta, String serverName

@Before
public void setUp() throws NoSuchFieldException {
mementos.add(TestUtils.silenceOperatorLogger().ignoringLoggedExceptions(ApiException.class));
mementos.add(TestUtils.silenceOperatorLogger()
.ignoringLoggedExceptions(ApiException.class, InterruptedException.class));
mementos.add(TuningParametersStub.install());
mementos.add(testSupport.install());
mementos.add(StubWatchFactory.install());
StubWatchFactory.setListener(this);

testSupport.defineResources(domain);
testSupport
.addToPacket(ProcessingConstants.DOMAIN_TOPOLOGY, domainConfig)
.addDomainPresenceInfo(domainPresenceInfo);
testSupport.doOnCreate(KubernetesTestSupport.POD, p -> schedulePodUpdates((V1Pod) p));
testSupport.doOnCreate(POD, p -> schedulePodUpdates((V1Pod) p));
testSupport.addComponent(
ProcessingConstants.PODWATCHER_COMPONENT_NAME,
PodAwaiterStepFactory.class,
watcher);
}

// Invoked when a pod is created to simulate the Kubernetes behavior in which a pod is scheduled on a node
// very quickly, and then takes much longer actually to become ready.
void schedulePodUpdates(V1Pod pod) {
testSupport.schedule(() -> setPodScheduled(getServerName(pod)), SCHEDULING_DELAY_MSEC, TimeUnit.MILLISECONDS);
testSupport.schedule(() -> setPodReady(getServerName(pod)), POD_READY_DELAY_SEC, TimeUnit.SECONDS);
testSupport.schedule(() -> setPodScheduled(pod), SCHEDULING_DELAY_MSEC, TimeUnit.MILLISECONDS);
testSupport.schedule(() -> setPodReady(pod), POD_READY_DELAY_SEC, TimeUnit.SECONDS);
}

// Marks the pod with the specified server name as having been scheduled on a Kubernetes node.
private void setPodScheduled(String serverName) {
Objects.requireNonNull(domainPresenceInfo.getServerPod(serverName).getSpec()).setNodeName("aNode");
// Marks the specified pod as having been scheduled on a Kubernetes node.
private void setPodScheduled(V1Pod pod) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good choice to simplify this.

Objects.requireNonNull(pod.getSpec()).setNodeName("aNode");
}

// Marks the pod with the specified server name as having become ready.
private void setPodReady(String serverName) {
domainPresenceInfo.getServerPod(serverName).status(createPodReadyStatus());
// Marks the specified pod as having become ready.
private void setPodReady(V1Pod pod) {
pod.status(createPodReadyStatus());
}

private V1PodStatus createPodReadyStatus() {
Expand All @@ -194,11 +216,16 @@ private V1PodStatus createPodReadyStatus() {

@After
public void tearDown() throws Exception {
shutDownThreads();
mementos.forEach(Memento::revert);

testSupport.throwOnCompletionFailure();
}

protected PodWatcher createWatcher(String ns, AtomicBoolean stopping, BigInteger rv) {
return PodWatcher.create(this, ns, rv.toString(), tuning, this, stopping);
}

@Test
public void withMultipleServersAvailableToStart_onlyOneForEachClusterInitiallyStarts() {
configureCluster(CLUSTER1).withMaxConcurrentStartup(0);
Expand Down Expand Up @@ -358,4 +385,13 @@ private void addWlsCluster(String clusterName, String... serverNames) {
);

}

@Override
public void receivedResponse(Watch.Response<V1Pod> response) {
}

@Override
public void allWatchesClosed() {
stopping.set(true);
}
}
0