Skip to content
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Release Notes.
* Support collection type in dynamic configuration core.
* Support zookeeper grouped dynamic configurations.
* Fix NPE when OAP nodes synchronize events with each other in cluster mode.
* Support k8s configmap grouped dynamic configurations.

#### UI

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package org.apache.skywalking.oap.server.configuration.configmap;

import io.kubernetes.client.openapi.models.V1ConfigMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -40,9 +40,9 @@ public ConfigmapConfigurationWatcherRegister(ConfigmapConfigurationSettings sett
@Override
public Optional<ConfigTable> readConfig(Set<String> keys) {
final ConfigTable configTable = new ConfigTable();
Optional<V1ConfigMap> v1ConfigMap = informer.configMap();
Map<String, String> configMapData = informer.configMapData();
for (final String name : keys) {
final String value = v1ConfigMap.map(V1ConfigMap::getData).map(data -> data.get(name)).orElse(null);
final String value = configMapData.get(name);
if (log.isDebugEnabled()) {
log.debug("read config: name:{} ,value:{}", name, value);
}
Expand All @@ -53,8 +53,19 @@ public Optional<ConfigTable> readConfig(Set<String> keys) {

@Override
public Optional<GroupConfigTable> readGroupConfig(final Set<String> keys) {
// TODO: implement readGroupConfig
return Optional.empty();
}
GroupConfigTable groupConfigTable = new GroupConfigTable();
Map<String, String> configMapData = informer.configMapData();
keys.forEach(key -> {
GroupConfigTable.GroupConfigItems groupConfigItems = new GroupConfigTable.GroupConfigItems(key);
groupConfigTable.addGroupConfigItems(groupConfigItems);
configMapData.forEach((groupItemKey, itemValue) -> {
if (groupItemKey.startsWith(key)) {
String itemName = groupItemKey.replaceFirst(key + ".", "");
groupConfigItems.add(new ConfigTable.ConfigItem(itemName, itemValue));
}
});
});

return Optional.of(groupConfigTable);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@
import io.kubernetes.client.openapi.models.V1ConfigMapList;
import io.kubernetes.client.util.Config;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ConfigurationConfigmapInformer {

private Lister<V1ConfigMap> configMapLister;

private SharedInformerFactory factory;
Expand Down Expand Up @@ -84,8 +84,18 @@ private void doStartConfigMapInformer(final ConfigmapConfigurationSettings setti
configMapLister = new Lister<>(configMapSharedIndexInformer.getIndexer());
}

public Optional<V1ConfigMap> configMap() {
return Optional.ofNullable(configMapLister.list().size() == 1 ? configMapLister.list().get(0) : null);
}
public Map<String, String> configMapData() {
Map<String, String> configMapData = new HashMap<>();
if (configMapLister != null && configMapLister.list() != null) {
configMapLister.list().forEach(cf -> {
Map<String, String> data = cf.getData();
if (data == null) {
return;
}
configMapData.putAll(data);
});
}

return configMapData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@

package org.apache.skywalking.oap.server.configuration.configmap;

import io.kubernetes.client.openapi.models.V1ConfigMap;
import java.io.FileNotFoundException;
import java.io.Reader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
import org.apache.skywalking.oap.server.configuration.api.GroupConfigTable;
import org.apache.skywalking.oap.server.library.util.ResourceUtils;
import org.junit.Assert;
import org.junit.Before;
Expand Down Expand Up @@ -59,8 +61,8 @@ public void prepare() throws IllegalAccessException {

@Test
public void readConfigWhenConfigMapDataIsNull() throws Exception {
V1ConfigMap v1ConfigMap = new V1ConfigMap();
PowerMockito.doReturn(Optional.of(v1ConfigMap)).when(informer).configMap();
Map<String, String> configMapData = new HashMap<>();
PowerMockito.doReturn(configMapData).when(informer).configMapData();
Optional<ConfigTable> optionalConfigTable = register.readConfig(new HashSet<String>() {{
add("key1");
}});
Expand All @@ -74,7 +76,7 @@ public void readConfigWhenConfigMapDataIsNull() throws Exception {

@Test
public void readConfigWhenInformerNotwork() throws Exception {
PowerMockito.doReturn(Optional.empty()).when(informer).configMap();
PowerMockito.doReturn(new HashMap<>()).when(informer).configMapData();
Optional<ConfigTable> optionalConfigTable = register.readConfig(new HashSet<String>() {{
add("key1");
}});
Expand All @@ -88,17 +90,15 @@ public void readConfigWhenInformerNotwork() throws Exception {

@Test
public void readConfigWhenInformerWork() throws Exception {
Reader configmapReader = ResourceUtils.read("skywalking-dynamic-configmap.example.yaml");
Map<String, Map<String, String>> configmapMap = yaml.loadAs(configmapReader, Map.class);
V1ConfigMap v1ConfigMap = new V1ConfigMap();
v1ConfigMap.data(configmapMap.get("data"));
PowerMockito.doReturn(Optional.of(v1ConfigMap)).when(informer).configMap();
Map<String, String> configMapData = this.readMockConfigMapData();
PowerMockito.doReturn(configMapData).when(informer).configMapData();
Optional<ConfigTable> optionalConfigTable = register.readConfig(new HashSet<String>() {{
add("receiver-trace.default.slowDBAccessThreshold");
add("alarm.default.alarm-settings");
add("core.default.apdexThreshold");
add("receiver-trace.default.uninstrumentedGateways");
}});

Assert.assertTrue(optionalConfigTable.isPresent());
ConfigTable configTable = optionalConfigTable.get();

Expand All @@ -108,4 +108,65 @@ public void readConfigWhenInformerWork() throws Exception {
.collect(Collectors.toList());
Assert.assertEquals(list.size(), 4);
}

@Test
public void readGroupConfigWhenConfigMapDataIsNull() throws Exception {
Map<String, String> configMapData = new HashMap<>();
PowerMockito.doReturn(configMapData).when(informer).configMapData();
Optional<GroupConfigTable> optionalGroupConfigTable = register.readGroupConfig(new HashSet<String>() {{
add("key1");
}});

Assert.assertTrue(optionalGroupConfigTable.isPresent());
GroupConfigTable groupConfigTable = optionalGroupConfigTable.get();
Assert.assertEquals(groupConfigTable.getGroupItems().size(), 1);
Assert.assertEquals(groupConfigTable.getGroupItems().get(0).getName(), "key1");
Assert.assertEquals(groupConfigTable.getGroupItems().get(0).getItems().size(), 0);
}

@Test
public void readGroupConfigWhenInformerNotwork() throws Exception {
PowerMockito.doReturn(new HashMap<>()).when(informer).configMapData();
Optional<GroupConfigTable> optionalGroupConfigTable = register.readGroupConfig(new HashSet<String>() {{
add("key1");
}});

Assert.assertTrue(optionalGroupConfigTable.isPresent());
GroupConfigTable groupConfigTable = optionalGroupConfigTable.get();
Assert.assertEquals(groupConfigTable.getGroupItems().size(), 1);
Assert.assertEquals(groupConfigTable.getGroupItems().get(0).getName(), "key1");
Assert.assertEquals(groupConfigTable.getGroupItems().get(0).getItems().size(), 0);
}

@Test
public void readGroupConfigWhenInformerWork() throws Exception {
Map<String, String> configMapData = this.readMockConfigMapData();
PowerMockito.doReturn(configMapData).when(informer).configMapData();
Optional<GroupConfigTable> optionalGroupConfigTable = register.readGroupConfig(new HashSet<String>() {{
add("core.default.endpoint-name-grouping-openapi");
}});

Assert.assertTrue(optionalGroupConfigTable.isPresent());
GroupConfigTable groupConfigTable = optionalGroupConfigTable.get();

Assert.assertEquals(groupConfigTable.getGroupItems().size(), 1);
Assert.assertEquals(groupConfigTable.getGroupItems().get(0).getName(), "core.default.endpoint-name-grouping-openapi");
Assert.assertEquals(groupConfigTable.getGroupItems().get(0).getItems().size(), 3);
}

private Map<String, String> readMockConfigMapData() throws FileNotFoundException {
Reader configmapReader1 = ResourceUtils.read("skywalking-dynamic-configmap.example.yaml");
Reader configmapReader2 = ResourceUtils.read("skywalking-group-dynamic-configmap.example-serviceA.yaml");
Reader configmapReader3 = ResourceUtils.read("skywalking-group-dynamic-configmap.example-serviceB.yaml");
Map<String, Map<String, String>> configmapMap1 = yaml.loadAs(configmapReader1, Map.class);
Map<String, Map<String, String>> configmapMap2 = yaml.loadAs(configmapReader2, Map.class);
Map<String, Map<String, String>> configmapMap3 = yaml.loadAs(configmapReader3, Map.class);

Map<String, String> configMapData = new HashMap<>();
configMapData.putAll(configmapMap1.get("data"));
configMapData.putAll(configmapMap2.get("data"));
configMapData.putAll(configmapMap3.get("data"));

return configMapData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ kind: ConfigMap
metadata:
name: skywalking-dynamic-config
labels:
app: skywalking-alarm
app: collector
release: skywalking
data:
receiver-trace.default.slowDBAccessThreshold: default:200,mongodb:50
Expand Down
Loading