Skip to content

Commit d9a8a76

Browse files
authored
Merge pull request #948 from oracle/cluster_scaling
Cluster scaling
2 parents ee417b8 + 0d6fc55 commit d9a8a76

20 files changed

+1112
-698
lines changed

model/src/main/java/oracle/kubernetes/operator/LabelConstants.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017,2018, Oracle Corporation and/or its affiliates. All rights reserved.
1+
// Copyright 2017, 2019, Oracle Corporation and/or its affiliates. All rights reserved.
22
// Licensed under the Universal Permissive License v 1.0 as shown at
33
// http://oss.oracle.com/licenses/upl.
44

@@ -11,7 +11,6 @@ public interface LabelConstants {
1111
String DOMAINNAME_LABEL = "weblogic.domainName";
1212
String DOMAINHOME_LABEL = "weblogic.domainHome";
1313
String SERVERNAME_LABEL = "weblogic.serverName";
14-
String CHANNELNAME_LABEL = "weblogic.channelName";
1514
String CLUSTERNAME_LABEL = "weblogic.clusterName";
1615
String CREATEDBYOPERATOR_LABEL = "weblogic.createdByOperator";
1716
String OPERATORNAME_LABEL = "weblogic.operatorName";

operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java

Lines changed: 33 additions & 233 deletions
Large diffs are not rendered by default.

operator/src/main/java/oracle/kubernetes/operator/Main.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import oracle.kubernetes.operator.helpers.KubernetesVersion;
4545
import oracle.kubernetes.operator.helpers.ResponseStep;
4646
import oracle.kubernetes.operator.helpers.ServerKubernetesObjects;
47+
import oracle.kubernetes.operator.helpers.ServiceHelper;
4748
import oracle.kubernetes.operator.logging.LoggingFacade;
4849
import oracle.kubernetes.operator.logging.LoggingFactory;
4950
import oracle.kubernetes.operator.logging.MessageKeys;
@@ -630,24 +631,11 @@ public NextAction onSuccess(Packet packet, CallResponse<V1ServiceList> callRespo
630631

631632
if (result != null) {
632633
for (V1Service service : result.getItems()) {
633-
String domainUID = ServiceWatcher.getServiceDomainUID(service);
634-
String serverName = ServiceWatcher.getServiceServerName(service);
635-
String channelName = ServiceWatcher.getServiceChannelName(service);
636-
String clusterName = ServiceWatcher.getServiceClusterName(service);
634+
String domainUID = ServiceHelper.getServiceDomainUID(service);
637635
if (domainUID != null) {
638636
DomainPresenceInfo info =
639637
dpis.computeIfAbsent(domainUID, k -> new DomainPresenceInfo(ns, domainUID));
640-
if (clusterName != null) {
641-
info.setClusterService(clusterName, service);
642-
} else if (serverName != null) {
643-
ServerKubernetesObjects sko =
644-
info.getServers().computeIfAbsent(serverName, k -> new ServerKubernetesObjects());
645-
if (channelName != null) {
646-
sko.getChannels().put(channelName, service);
647-
} else {
648-
sko.getService().set(service);
649-
}
650-
}
638+
ServiceHelper.addToPresence(info, service);
651639
}
652640
}
653641
}
Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
// Copyright 2018, Oracle Corporation and/or its affiliates. All rights reserved.
1+
// Copyright 2018, 2019, Oracle Corporation and/or its affiliates. All rights reserved.
22
// Licensed under the Universal Permissive License v 1.0 as shown at
33
// http://oss.oracle.com/licenses/upl.
44

55
package oracle.kubernetes.operator;
66

77
import io.kubernetes.client.ApiException;
8-
import io.kubernetes.client.models.V1ObjectMeta;
98
import io.kubernetes.client.models.V1Service;
10-
import java.util.Map;
119
import java.util.concurrent.ThreadFactory;
1210
import java.util.concurrent.atomic.AtomicBoolean;
1311
import oracle.kubernetes.operator.TuningParameters.WatchTuning;
@@ -51,40 +49,4 @@ public WatchI<V1Service> initiateWatch(WatchBuilder watchBuilder) throws ApiExce
5149
.withLabelSelectors(LabelConstants.DOMAINUID_LABEL, LabelConstants.CREATEDBYOPERATOR_LABEL)
5250
.createServiceWatch(ns);
5351
}
54-
55-
static String getServiceDomainUID(V1Service service) {
56-
V1ObjectMeta meta = service.getMetadata();
57-
Map<String, String> labels = meta.getLabels();
58-
if (labels != null) {
59-
return labels.get(LabelConstants.DOMAINUID_LABEL);
60-
}
61-
return null;
62-
}
63-
64-
static String getServiceServerName(V1Service service) {
65-
V1ObjectMeta meta = service.getMetadata();
66-
Map<String, String> labels = meta.getLabels();
67-
if (labels != null) {
68-
return labels.get(LabelConstants.SERVERNAME_LABEL);
69-
}
70-
return null;
71-
}
72-
73-
static String getServiceChannelName(V1Service service) {
74-
V1ObjectMeta meta = service.getMetadata();
75-
Map<String, String> labels = meta.getLabels();
76-
if (labels != null) {
77-
return labels.get(LabelConstants.CHANNELNAME_LABEL);
78-
}
79-
return null;
80-
}
81-
82-
static String getServiceClusterName(V1Service service) {
83-
V1ObjectMeta meta = service.getMetadata();
84-
Map<String, String> labels = meta.getLabels();
85-
if (labels != null) {
86-
return labels.get(LabelConstants.CLUSTERNAME_LABEL);
87-
}
88-
return null;
89-
}
9052
}

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

Lines changed: 79 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@
55
package oracle.kubernetes.operator.helpers;
66

77
import io.kubernetes.client.models.V1EnvVar;
8+
import io.kubernetes.client.models.V1ObjectMeta;
89
import io.kubernetes.client.models.V1Service;
910
import java.util.Collection;
1011
import java.util.Collections;
1112
import java.util.List;
13+
import java.util.Objects;
1214
import java.util.Optional;
1315
import java.util.concurrent.ConcurrentHashMap;
1416
import java.util.concurrent.ConcurrentMap;
1517
import java.util.concurrent.atomic.AtomicBoolean;
1618
import java.util.concurrent.atomic.AtomicInteger;
1719
import java.util.concurrent.atomic.AtomicReference;
20+
import java.util.function.Predicate;
1821
import oracle.kubernetes.operator.wlsconfig.WlsServerConfig;
1922
import oracle.kubernetes.weblogic.domain.model.Domain;
2023
import oracle.kubernetes.weblogic.domain.model.ServerSpec;
21-
import org.joda.time.DateTime;
2224

2325
/**
2426
* Operator's mapping between custom resource Domain and runtime details about that domain,
@@ -36,8 +38,6 @@ public class DomainPresenceInfo {
3638
private final ConcurrentMap<String, ServerKubernetesObjects> servers = new ConcurrentHashMap<>();
3739
private final ConcurrentMap<String, V1Service> clusters = new ConcurrentHashMap<>();
3840

39-
private DateTime lastCompletionTime;
40-
4141
/**
4242
* Create presence for a domain.
4343
*
@@ -71,28 +71,95 @@ private ServerKubernetesObjects getSko(String serverName) {
7171
return getServers().computeIfAbsent(serverName, (n -> new ServerKubernetesObjects()));
7272
}
7373

74-
V1Service getServerService(String serverName) {
74+
public V1Service getServerService(String serverName) {
7575
return getSko(serverName).getService().get();
7676
}
7777

78+
void setServerServiceFromEvent(String serverName, V1Service event) {
79+
getSko(serverName).getService().accumulateAndGet(event, this::getNewerService);
80+
}
81+
82+
boolean deleteServerServiceFromEvent(String serverName, V1Service event) {
83+
if (serverName == null) return false;
84+
V1Service deletedService =
85+
getSko(serverName).getService().getAndAccumulate(event, this::getNewerCurrentOrNull);
86+
return deletedService != null;
87+
}
88+
89+
/**
90+
* Computes the result of a delete attempt. If the current service is newer than the one
91+
* associated with the delete event, returns it; otherwise returns null, thus deleting the value.
92+
*
93+
* @param service the current service
94+
* @param event the service associated with the delete event
95+
* @return the new value for the service.
96+
*/
97+
private V1Service getNewerCurrentOrNull(V1Service service, V1Service event) {
98+
return KubernetesUtils.isFirstNewer(getMetadata(service), getMetadata(event)) ? service : null;
99+
}
100+
78101
void removeClusterService(String clusterName) {
79-
getClusters().remove(clusterName);
102+
clusters.remove(clusterName);
80103
}
81104

82105
V1Service getClusterService(String clusterName) {
83-
return getClusters().get(clusterName);
106+
return clusters.get(clusterName);
107+
}
108+
109+
void setClusterService(String clusterName, V1Service service) {
110+
clusters.put(clusterName, service);
111+
}
112+
113+
void setClusterServiceFromEvent(String clusterName, V1Service event) {
114+
if (clusterName == null) return;
115+
116+
clusters.compute(clusterName, (k, s) -> getNewerService(s, event));
117+
}
118+
119+
boolean deleteClusterServiceFromEvent(String clusterName, V1Service event) {
120+
return removeIfPresentAnd(
121+
clusters,
122+
clusterName,
123+
s -> !KubernetesUtils.isFirstNewer(getMetadata(s), getMetadata(event)));
124+
}
125+
126+
private static <K, V> boolean removeIfPresentAnd(
127+
ConcurrentMap<K, V> map, K key, Predicate<? super V> predicateFunction) {
128+
Objects.requireNonNull(predicateFunction);
129+
for (V oldValue; (oldValue = map.get(key)) != null; ) {
130+
if (!predicateFunction.test(oldValue)) return false;
131+
else if (map.remove(key, oldValue)) return true;
132+
}
133+
return false;
84134
}
85135

86-
public void setClusterService(String clusterName, V1Service service) {
87-
getClusters().put(clusterName, service);
136+
private V1Service getNewerService(V1Service first, V1Service second) {
137+
return KubernetesUtils.isFirstNewer(getMetadata(first), getMetadata(second)) ? first : second;
138+
}
139+
140+
private V1ObjectMeta getMetadata(V1Service service) {
141+
return service == null ? null : service.getMetadata();
88142
}
89143

90144
V1Service getExternalService(String serverName) {
91-
return getSko(serverName).getExternalService();
145+
return getSko(serverName).getExternalService().get();
92146
}
93147

94148
void setExternalService(String serverName, V1Service service) {
95-
getSko(serverName).setExternalService(service);
149+
getSko(serverName).getExternalService().set(service);
150+
}
151+
152+
void setExternalServiceFromEvent(String serverName, V1Service event) {
153+
getSko(serverName).getExternalService().accumulateAndGet(event, this::getNewerService);
154+
}
155+
156+
boolean deleteExternalServiceFromEvent(String serverName, V1Service event) {
157+
if (serverName == null) return false;
158+
V1Service deletedService =
159+
getSko(serverName)
160+
.getExternalService()
161+
.getAndAccumulate(event, this::getNewerCurrentOrNull);
162+
return deletedService != null;
96163
}
97164

98165
public boolean isDeleting() {
@@ -111,30 +178,20 @@ public void setPopulated(boolean populated) {
111178
isPopulated.set(populated);
112179
}
113180

114-
public void resetFailureCount() {
181+
private void resetFailureCount() {
115182
retryCount.set(0);
116183
}
117184

118185
public int incrementAndGetFailureCount() {
119186
return retryCount.incrementAndGet();
120187
}
121188

122-
public int getRetryCount() {
189+
int getRetryCount() {
123190
return retryCount.get();
124191
}
125192

126-
/**
127-
* Last completion time.
128-
*
129-
* @return Last completion time
130-
*/
131-
public DateTime getLastCompletionTime() {
132-
return lastCompletionTime;
133-
}
134-
135193
/** Sets the last completion time to now. */
136194
public void complete() {
137-
this.lastCompletionTime = new DateTime();
138195
resetFailureCount();
139196
}
140197

@@ -183,15 +240,6 @@ public ConcurrentMap<String, ServerKubernetesObjects> getServers() {
183240
return servers;
184241
}
185242

186-
/**
187-
* Map from cluster name to Service objects.
188-
*
189-
* @return Cluster object map
190-
*/
191-
public ConcurrentMap<String, V1Service> getClusters() {
192-
return clusters;
193-
}
194-
195243
/**
196244
* Server startup info.
197245
*
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright 2019, Oracle Corporation and/or its affiliates. All rights reserved.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at
3+
// http://oss.oracle.com/licenses/upl.
4+
5+
package oracle.kubernetes.operator.helpers;
6+
7+
import io.kubernetes.client.models.V1Service;
8+
import java.util.Optional;
9+
10+
public enum KubernetesServiceType {
11+
SERVER {
12+
@Override
13+
void addToPresence(DomainPresenceInfo presenceInfo, V1Service service) {
14+
presenceInfo.setServerService(ServiceHelper.getServerName(service), service);
15+
}
16+
17+
@Override
18+
void updateFromEvent(DomainPresenceInfo presenceInfo, V1Service event) {
19+
presenceInfo.setServerServiceFromEvent(ServiceHelper.getServerName(event), event);
20+
}
21+
22+
@Override
23+
boolean matches(V1Service service) {
24+
return ServiceHelper.getServerName(service) != null;
25+
}
26+
27+
@Override
28+
boolean deleteFromEvent(DomainPresenceInfo info, V1Service event) {
29+
return info.deleteServerServiceFromEvent(ServiceHelper.getServerName(event), event);
30+
}
31+
},
32+
EXTERNAL {
33+
@Override
34+
void addToPresence(DomainPresenceInfo presenceInfo, V1Service service) {
35+
presenceInfo.setExternalService(ServiceHelper.getServerName(service), service);
36+
}
37+
38+
@Override
39+
void updateFromEvent(DomainPresenceInfo presenceInfo, V1Service service) {
40+
presenceInfo.setExternalServiceFromEvent(ServiceHelper.getServerName(service), service);
41+
}
42+
43+
@Override
44+
boolean deleteFromEvent(DomainPresenceInfo info, V1Service event) {
45+
return info.deleteExternalServiceFromEvent(ServiceHelper.getServerName(event), event);
46+
}
47+
},
48+
CLUSTER {
49+
@Override
50+
boolean matches(V1Service service) {
51+
return ServiceHelper.getClusterName(service) != null;
52+
}
53+
54+
@Override
55+
void addToPresence(DomainPresenceInfo presenceInfo, V1Service service) {
56+
presenceInfo.setClusterService(ServiceHelper.getClusterName(service), service);
57+
}
58+
59+
@Override
60+
void updateFromEvent(DomainPresenceInfo presenceInfo, V1Service service) {
61+
presenceInfo.setClusterServiceFromEvent(ServiceHelper.getClusterName(service), service);
62+
}
63+
64+
@Override
65+
boolean deleteFromEvent(DomainPresenceInfo info, V1Service event) {
66+
return info.deleteClusterServiceFromEvent(ServiceHelper.getClusterName(event), event);
67+
}
68+
},
69+
UNKNOWN {
70+
@Override
71+
boolean matches(V1Service service) {
72+
return true;
73+
}
74+
};
75+
76+
private static final String SERVICE_TYPE = "serviceType";
77+
78+
static KubernetesServiceType getType(V1Service service) {
79+
String type = ServiceHelper.getLabelValue(service, SERVICE_TYPE);
80+
if (type != null) return KubernetesServiceType.valueOf(type);
81+
82+
for (KubernetesServiceType serviceType : KubernetesServiceType.values())
83+
if (serviceType.matches(service)) return serviceType;
84+
85+
return UNKNOWN;
86+
}
87+
88+
boolean matches(V1Service service) {
89+
return false;
90+
}
91+
92+
void addToPresence(DomainPresenceInfo presenceInfo, V1Service service) {}
93+
94+
void updateFromEvent(DomainPresenceInfo presenceInfo, V1Service service) {}
95+
96+
V1Service withTypeLabel(V1Service service) {
97+
Optional.ofNullable(service)
98+
.map(V1Service::getMetadata)
99+
.ifPresent(meta -> meta.putLabelsItem(SERVICE_TYPE, toString()));
100+
return service;
101+
}
102+
103+
boolean deleteFromEvent(DomainPresenceInfo info, V1Service service) {
104+
return false;
105+
}
106+
}

0 commit comments

Comments
 (0)