Skip to content

Commit 480fb7b

Browse files
committed
Add unit test for scaling down cluster
1 parent 420d3c8 commit 480fb7b

File tree

6 files changed

+132
-29
lines changed

6 files changed

+132
-29
lines changed

operator/src/main/java/oracle/kubernetes/operator/helpers/AnnotationHelper.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@ static void annotateForPrometheus(V1ObjectMeta meta, int httpPort) {
3333
meta.putAnnotationsItem("prometheus.io/scrape", "true");
3434
}
3535

36-
static V1Pod withSha256Hash(V1Pod pod) {
36+
public static V1Pod withSha256Hash(V1Pod pod) {
3737
return DEBUG ? addHashAndDebug(pod) : addHash(pod);
3838
}
3939

40+
public static V1Service withSha256Hash(V1Service service) {
41+
return addHash(service);
42+
}
43+
4044
private static V1Pod addHashAndDebug(V1Pod pod) {
4145
String dump = Yaml.dump(pod);
4246
addHash(pod);
@@ -49,21 +53,17 @@ private static V1Pod addHash(V1Pod pod) {
4953
return pod;
5054
}
5155

52-
static String getHash(V1Pod pod) {
53-
return pod.getMetadata().getAnnotations().get(SHA256_ANNOTATION);
56+
private static V1Service addHash(V1Service service) {
57+
service.getMetadata().putAnnotationsItem(SHA256_ANNOTATION, HASH_FUNCTION.apply(service));
58+
return service;
5459
}
5560

5661
static String getDebugString(V1Pod pod) {
5762
return pod.getMetadata().getAnnotations().get(HASHED_STRING);
5863
}
5964

60-
static V1Service withSha256Hash(V1Service service) {
61-
return addHash(service);
62-
}
63-
64-
private static V1Service addHash(V1Service service) {
65-
service.getMetadata().putAnnotationsItem(SHA256_ANNOTATION, HASH_FUNCTION.apply(service));
66-
return service;
65+
static String getHash(V1Pod pod) {
66+
return pod.getMetadata().getAnnotations().get(SHA256_ANNOTATION);
6767
}
6868

6969
static String getHash(V1Service service) {

operator/src/main/java/oracle/kubernetes/operator/helpers/DomainPresenceInfo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ public V1Service getServerService(String serverName) {
7676
return getSko(serverName).getService().get();
7777
}
7878

79+
V1Service[] getServiceServices() {
80+
return servers.values().stream()
81+
.map(ServerKubernetesObjects::getService)
82+
.map(AtomicReference::get)
83+
.toArray(V1Service[]::new);
84+
}
85+
7986
public V1Pod getServerPod(String serverName) {
8087
return getSko(serverName).getPod().get();
8188
}

operator/src/main/java/oracle/kubernetes/operator/helpers/KubernetesServiceType.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ boolean matches(V1Service service) {
2828
boolean deleteFromEvent(DomainPresenceInfo info, V1Service event) {
2929
return info.deleteServerServiceFromEvent(ServiceHelper.getServerName(event), event);
3030
}
31+
32+
@Override
33+
V1Service[] getServices(DomainPresenceInfo presenceInfo) {
34+
return presenceInfo.getServiceServices();
35+
}
3136
},
3237
EXTERNAL {
3338
@Override
@@ -103,4 +108,8 @@ public V1Service withTypeLabel(V1Service service) {
103108
boolean deleteFromEvent(DomainPresenceInfo info, V1Service service) {
104109
return false;
105110
}
111+
112+
V1Service[] getServices(DomainPresenceInfo info) {
113+
return new V1Service[0];
114+
}
106115
}

operator/src/main/java/oracle/kubernetes/operator/helpers/KubernetesUtils.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Map;
1010
import java.util.Objects;
1111
import javax.json.JsonPatchBuilder;
12+
import oracle.kubernetes.operator.LabelConstants;
1213
import org.apache.commons.collections.MapUtils;
1314
import org.joda.time.DateTime;
1415

@@ -129,4 +130,9 @@ public static boolean isFirstNewer(V1ObjectMeta first, V1ObjectMeta second) {
129130
private static int getResourceVersion(V1ObjectMeta metadata) {
130131
return Integer.parseInt(metadata.getResourceVersion());
131132
}
133+
134+
public static V1ObjectMeta withOperatorLabels(V1ObjectMeta meta, String uid) {
135+
return meta.putLabelsItem(LabelConstants.DOMAINUID_LABEL, uid)
136+
.putLabelsItem(LabelConstants.CREATEDBYOPERATOR_LABEL, "true");
137+
}
132138
}

operator/src/main/java/oracle/kubernetes/operator/helpers/ServiceHelper.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ public static void updatePresenceFromEvent(DomainPresenceInfo info, V1Service se
8181
KubernetesServiceType.getType(service).updateFromEvent(info, service);
8282
}
8383

84+
public static V1Service[] getServerServices(DomainPresenceInfo info) {
85+
return KubernetesServiceType.SERVER.getServices(info);
86+
}
87+
88+
public static boolean isServerService(V1Service service) {
89+
return KubernetesServiceType.getType(service) == KubernetesServiceType.SERVER;
90+
}
91+
8492
public static boolean deleteFromEvent(DomainPresenceInfo info, V1Service service) {
8593
return KubernetesServiceType.getType(service).deleteFromEvent(info, service);
8694
}

operator/src/test/java/oracle/kubernetes/operator/DomainProcessorTest.java

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
import static com.meterware.simplestub.Stub.createStrictStub;
88
import static oracle.kubernetes.operator.KubernetesConstants.INTROSPECTOR_CONFIG_MAP_NAME_SUFFIX;
9-
import static oracle.kubernetes.operator.ProcessingConstants.DOMAIN_TOPOLOGY;
9+
import static oracle.kubernetes.operator.LabelConstants.SERVERNAME_LABEL;
1010
import static oracle.kubernetes.operator.ProcessingConstants.JOB_POD_NAME;
11+
import static org.hamcrest.Matchers.equalTo;
1112
import static org.hamcrest.Matchers.notNullValue;
1213
import static org.hamcrest.junit.MatcherAssert.assertThat;
1314

@@ -20,28 +21,36 @@
2021
import io.kubernetes.client.models.V1JobStatus;
2122
import io.kubernetes.client.models.V1ObjectMeta;
2223
import io.kubernetes.client.models.V1Pod;
24+
import io.kubernetes.client.models.V1PodSpec;
2325
import io.kubernetes.client.models.V1SecretReference;
26+
import io.kubernetes.client.models.V1Service;
2427
import java.util.ArrayList;
28+
import java.util.Arrays;
2529
import java.util.HashMap;
2630
import java.util.List;
2731
import java.util.Map;
2832
import java.util.concurrent.ScheduledFuture;
2933
import java.util.concurrent.TimeUnit;
34+
import java.util.stream.IntStream;
35+
import java.util.stream.Stream;
3036
import oracle.kubernetes.TestUtils;
37+
import oracle.kubernetes.operator.helpers.AnnotationHelper;
3138
import oracle.kubernetes.operator.helpers.DomainPresenceInfo;
3239
import oracle.kubernetes.operator.helpers.KubernetesTestSupport;
40+
import oracle.kubernetes.operator.helpers.KubernetesUtils;
3341
import oracle.kubernetes.operator.helpers.KubernetesVersion;
3442
import oracle.kubernetes.operator.helpers.LegalNames;
43+
import oracle.kubernetes.operator.helpers.ServiceHelper;
3544
import oracle.kubernetes.operator.helpers.TuningParametersStub;
3645
import oracle.kubernetes.operator.helpers.UnitTestHash;
3746
import oracle.kubernetes.operator.utils.InMemoryCertificates;
38-
import oracle.kubernetes.operator.utils.WlsDomainConfigSupport;
3947
import oracle.kubernetes.operator.work.FiberGate;
4048
import oracle.kubernetes.operator.work.FiberTestSupport;
4149
import oracle.kubernetes.weblogic.domain.DomainConfigurator;
4250
import oracle.kubernetes.weblogic.domain.DomainConfiguratorFactory;
4351
import oracle.kubernetes.weblogic.domain.model.Domain;
4452
import oracle.kubernetes.weblogic.domain.model.DomainSpec;
53+
import org.joda.time.DateTime;
4554
import org.junit.After;
4655
import org.junit.Before;
4756
import org.junit.Test;
@@ -53,22 +62,31 @@ public class DomainProcessorTest {
5362
private static final String INTROSPECTION_JOB = "jobPod";
5463
private static final String CLUSTER = "cluster";
5564
private static final int MAX_SERVERS = 5;
65+
private static final String MS_PREFIX = "managed-server";
66+
private static final int MIN_REPLICAS = 2;
67+
private static final int NUM_ADMIN_SERVERS = 1;
68+
private static final int NUM_JOB_PODS = 1;
5669

5770
private List<Memento> mementos = new ArrayList<>();
5871
private KubernetesTestSupport testSupport = new KubernetesTestSupport();
5972
private DomainConfigurator domainConfigurator;
60-
private String[] managedServerNames = new String[MAX_SERVERS];
73+
private String[] managedServerNames =
74+
IntStream.rangeClosed(1, MAX_SERVERS).mapToObj(n -> MS_PREFIX + n).toArray(String[]::new);
6175
private Map<String, DomainPresenceInfo> presenceInfoMap = new HashMap<>();
6276
private DomainProcessorDelegateStub delegate =
6377
createStrictStub(DomainProcessorDelegateStub.class, testSupport);
6478
private DomainProcessorImpl processor = new DomainProcessorImpl(delegate);
6579
private Domain domain =
6680
new Domain()
67-
.withMetadata(new V1ObjectMeta().name(UID).namespace(NS))
81+
.withMetadata(withTimestamps(new V1ObjectMeta().name(UID).namespace(NS)))
6882
.withSpec(
6983
new DomainSpec()
7084
.withWebLogicCredentialsSecret(new V1SecretReference().name("secret-name")));
7185

86+
private static V1ObjectMeta withTimestamps(V1ObjectMeta meta) {
87+
return meta.creationTimestamp(DateTime.now()).resourceVersion("1");
88+
}
89+
7290
@Before
7391
public void setUp() throws Exception {
7492
mementos.add(TestUtils.silenceOperatorLogger());
@@ -78,16 +96,6 @@ public void setUp() throws Exception {
7896
mementos.add(InMemoryCertificates.install());
7997
mementos.add(UnitTestHash.install());
8098

81-
WlsDomainConfigSupport configSupport =
82-
new WlsDomainConfigSupport(UID).withAdminServerName(ADMIN_SERVER_NAME);
83-
configSupport.addWlsServer(ADMIN_SERVER_NAME, 7001);
84-
85-
for (int num = 0; num < MAX_SERVERS; num++)
86-
configSupport.addWlsServer(
87-
managedServerNames[num] = "managed-server" + (num + 1), 8001 + num);
88-
configSupport.addWlsCluster(CLUSTER, managedServerNames);
89-
testSupport.addToPacket(DOMAIN_TOPOLOGY, configSupport.createDomainConfig());
90-
9199
domainConfigurator = DomainConfiguratorFactory.forDomain(domain);
92100
testSupport.addToPacket(JOB_POD_NAME, INTROSPECTION_JOB);
93101
testSupport.doOnCreate(
@@ -132,6 +140,61 @@ public void whenDomainConfiguredForMaxServers_establishMatchingPresence() {
132140
assertThat(info.getClusterService(CLUSTER), notNullValue());
133141
}
134142

143+
@Test
144+
public void whenDomainScaledDown_removeExcessPodsAndServices() {
145+
defineServerResources(ADMIN_SERVER_NAME);
146+
Arrays.stream(managedServerNames).forEach(this::defineServerResources);
147+
148+
domainConfigurator.configureCluster(CLUSTER).withReplicas(MIN_REPLICAS);
149+
DomainPresenceInfo info = new DomainPresenceInfo(domain);
150+
processor.makeRightDomainPresence(info, true, false, false);
151+
152+
assertThat((int) getServerServices().count(), equalTo(MIN_REPLICAS + NUM_ADMIN_SERVERS));
153+
assertThat(getRunningPods().size(), equalTo(MIN_REPLICAS + NUM_ADMIN_SERVERS + NUM_JOB_PODS));
154+
}
155+
156+
private Stream<V1Service> getServerServices() {
157+
return getRunningServices().stream().filter(ServiceHelper::isServerService);
158+
}
159+
160+
private List<V1Service> getRunningServices() {
161+
return testSupport.getResources(KubernetesTestSupport.SERVICE);
162+
}
163+
164+
private List<V1Pod> getRunningPods() {
165+
return testSupport.getResources(KubernetesTestSupport.POD);
166+
}
167+
168+
private void defineServerResources(String serverName) {
169+
testSupport.defineResources(createServerPod(serverName), createServerService(serverName));
170+
}
171+
172+
private V1Pod createServerPod(String serverName) {
173+
return AnnotationHelper.withSha256Hash(
174+
new V1Pod()
175+
.metadata(
176+
withServerLabels(
177+
new V1ObjectMeta().name(LegalNames.toServerName(UID, serverName)).namespace(NS),
178+
serverName))
179+
.spec(new V1PodSpec()));
180+
}
181+
182+
private V1ObjectMeta withServerLabels(V1ObjectMeta meta, String serverName) {
183+
return KubernetesUtils.withOperatorLabels(meta, UID)
184+
.putLabelsItem(SERVERNAME_LABEL, serverName);
185+
}
186+
187+
private V1Service createServerService(String serverName) {
188+
return AnnotationHelper.withSha256Hash(
189+
new V1Service()
190+
.metadata(
191+
withServerLabels(
192+
new V1ObjectMeta()
193+
.name(LegalNames.toServerServiceName(UID, serverName))
194+
.namespace(NS),
195+
serverName)));
196+
}
197+
135198
private void assertServerPodAndServicePresent(DomainPresenceInfo info, String serverName) {
136199
assertThat(serverName + " server service", info.getServerService(serverName), notNullValue());
137200
assertThat(serverName + " pod", info.getServerPod(serverName), notNullValue());
@@ -183,19 +246,29 @@ public ScheduledFuture<?> scheduleWithFixedDelay(
183246
+ CLUSTER
184247
+ "\"\n"
185248
+ " servers:\n"
186-
+ " - name: \"managed-server1\"\n"
249+
+ " - name: \""
250+
+ MS_PREFIX
251+
+ "1\"\n"
187252
+ " listenPort: 8001\n"
188253
+ " listenAddress: \"domain1-managed-server1\"\n"
189-
+ " - name: \"managed-server2\"\n"
254+
+ " - name: \""
255+
+ MS_PREFIX
256+
+ "2\"\n"
190257
+ " listenPort: 8001\n"
191258
+ " listenAddress: \"domain1-managed-server2\"\n"
192-
+ " - name: \"managed-server3\"\n"
259+
+ " - name: \""
260+
+ MS_PREFIX
261+
+ "3\"\n"
193262
+ " listenPort: 8001\n"
194263
+ " listenAddress: \"domain1-managed-server3\"\n"
195-
+ " - name: \"managed-server4\"\n"
264+
+ " - name: \""
265+
+ MS_PREFIX
266+
+ "4\"\n"
196267
+ " listenPort: 8001\n"
197268
+ " listenAddress: \"domain1-managed-server4\"\n"
198-
+ " - name: \"managed-server5\"\n"
269+
+ " - name: \""
270+
+ MS_PREFIX
271+
+ "5\"\n"
199272
+ " listenPort: 8001\n"
200273
+ " listenAddress: \"domain1-managed-server5\"\n"
201274
+ " servers:\n"

0 commit comments

Comments
 (0)