Skip to content

Commit 4754297

Browse files
committed
Isolate accesses to service presence fields
1 parent ee417b8 commit 4754297

19 files changed

+1005
-630
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: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@
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;
@@ -71,10 +74,33 @@ private ServerKubernetesObjects getSko(String serverName) {
7174
return getServers().computeIfAbsent(serverName, (n -> new ServerKubernetesObjects()));
7275
}
7376

74-
V1Service getServerService(String serverName) {
77+
public V1Service getServerService(String serverName) {
7578
return getSko(serverName).getService().get();
7679
}
7780

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

86-
public void setClusterService(String clusterName, V1Service service) {
112+
void setClusterService(String clusterName, V1Service service) {
87113
getClusters().put(clusterName, service);
88114
}
89115

116+
void setClusterServiceFromEvent(String clusterName, V1Service event) {
117+
if (clusterName == null) return;
118+
119+
getClusters().compute(clusterName, (k, s) -> getNewerService(s, event));
120+
}
121+
122+
boolean deleteClusterServiceFromEvent(String clusterName, V1Service event) {
123+
return removeIfPresentAnd(
124+
getClusters(),
125+
clusterName,
126+
s -> !KubernetesUtils.isFirstNewer(getMetadata(s), getMetadata(event)));
127+
}
128+
129+
private static <K, V> boolean removeIfPresentAnd(
130+
ConcurrentMap<K, V> map, K key, Predicate<? super V> predicateFunction) {
131+
Objects.requireNonNull(predicateFunction);
132+
for (V oldValue; (oldValue = map.get(key)) != null; ) {
133+
if (!predicateFunction.test(oldValue)) return false;
134+
else if (map.remove(key, oldValue)) return true;
135+
}
136+
return false;
137+
}
138+
139+
private V1Service getNewerService(V1Service first, V1Service second) {
140+
return KubernetesUtils.isFirstNewer(getMetadata(first), getMetadata(second)) ? first : second;
141+
}
142+
143+
private V1ObjectMeta getMetadata(V1Service service) {
144+
return service == null ? null : service.getMetadata();
145+
}
146+
90147
V1Service getExternalService(String serverName) {
91-
return getSko(serverName).getExternalService();
148+
return getSko(serverName).getExternalService().get();
92149
}
93150

94151
void setExternalService(String serverName, V1Service service) {
95-
getSko(serverName).setExternalService(service);
152+
getSko(serverName).getExternalService().set(service);
153+
}
154+
155+
void setExternalServiceFromEvent(String serverName, V1Service event) {
156+
getSko(serverName).getExternalService().accumulateAndGet(event, this::getNewerService);
157+
}
158+
159+
boolean deleteExternalServiceFromEvent(String serverName, V1Service event) {
160+
if (serverName == null) return false;
161+
V1Service deletedService =
162+
getSko(serverName)
163+
.getExternalService()
164+
.getAndAccumulate(event, this::getNewerCurrentOrNull);
165+
return deletedService != null;
96166
}
97167

98168
public boolean isDeleting() {
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+
}

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.Objects;
1212
import javax.json.JsonPatchBuilder;
1313
import org.apache.commons.collections.MapUtils;
14+
import org.joda.time.DateTime;
1415

1516
public class KubernetesUtils {
1617

@@ -141,4 +142,26 @@ static V1ObjectMeta getResourceMetadata(Object resource) {
141142
return new V1ObjectMeta();
142143
}
143144
}
145+
146+
/**
147+
* Returns true if the first metadata indicates a newer resource than does the second.
148+
*
149+
* @param first the first item to compare
150+
* @param second the second item to compare
151+
* @return true if the first object is newer than the second object
152+
*/
153+
public static boolean isFirstNewer(V1ObjectMeta first, V1ObjectMeta second) {
154+
if (second == null) return true;
155+
if (first == null) return false;
156+
157+
DateTime time1 = first.getCreationTimestamp();
158+
DateTime time2 = second.getCreationTimestamp();
159+
160+
if (time2.isAfter(time1)) {
161+
return false;
162+
}
163+
return Integer.parseInt(second.getResourceVersion())
164+
< Integer.parseInt(first.getResourceVersion())
165+
|| time2.isBefore(time1);
166+
}
144167
}

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,7 @@ public ConcurrentMap<String, V1Service> getChannels() {
5656
return channels;
5757
}
5858

59-
public V1Service getExternalService() {
60-
return externalService.get();
61-
}
62-
63-
public void setExternalService(V1Service service) {
64-
externalService.set(service);
59+
AtomicReference<V1Service> getExternalService() {
60+
return externalService;
6561
}
6662
}

0 commit comments

Comments
 (0)