format check on client labels (#11903)

* format check on client labels

* log optimize

* testcase fix
This commit is contained in:
nov.lzf 2024-04-01 14:55:44 +08:00 committed by GitHub
parent 2df335d57e
commit 5fcef225be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 100 additions and 53 deletions

View File

@ -59,6 +59,8 @@ public class DefaultLabelsCollector implements LabelsCollector {
public Map<String, String> collectLabels(Properties properties) {
//properties
LOGGER.info("default nacos collect properties raw labels: {}",
properties.getProperty(Constants.APP_CONN_LABELS_KEY));
Map<String, String> propertiesLabels = ConnLabelsUtils.parseRawLabels(
properties.getProperty(Constants.APP_CONN_LABELS_KEY));
if (properties.containsKey(Constants.CONFIG_GRAY_LABEL)) {
@ -67,6 +69,7 @@ public class DefaultLabelsCollector implements LabelsCollector {
LOGGER.info("default nacos collect properties labels: {}", propertiesLabels);
//jvm
LOGGER.info("default nacos collect jvm raw labels: {}", System.getProperty(Constants.APP_CONN_LABELS_KEY));
Map<String, String> jvmLabels = ConnLabelsUtils.parseRawLabels(
System.getProperty(Constants.APP_CONN_LABELS_KEY));
if (System.getProperty(Constants.CONFIG_GRAY_LABEL) != null) {
@ -75,6 +78,8 @@ public class DefaultLabelsCollector implements LabelsCollector {
LOGGER.info("default nacos collect jvm labels: {}", jvmLabels);
//env
LOGGER.info("default nacos collect env raw labels: {}",
System.getenv(Constants.APP_CONN_LABELS_KEY.replaceAll(DOT, UNDERSCORE)));
Map<String, String> envLabels = ConnLabelsUtils.parseRawLabels(
System.getenv(Constants.APP_CONN_LABELS_KEY.replaceAll(DOT, UNDERSCORE)));
if (System.getenv(Constants.CONFIG_GRAY_LABEL.replaceAll(DOT, UNDERSCORE)) != null) {

View File

@ -18,6 +18,7 @@ package com.alibaba.nacos.common.labels.impl;
import com.alibaba.nacos.common.labels.LabelsCollector;
import com.alibaba.nacos.common.labels.LabelsCollectorManager;
import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -60,6 +61,11 @@ public class DefaultLabelsCollectorManager implements LabelsCollectorManager {
LOGGER.info("Process LabelsCollector with [name:{}]", labelsCollector.getName());
for (Map.Entry<String, String> entry : labelsCollector.collectLabels(properties).entrySet()) {
if (!checkValidLabel(entry.getKey(), entry.getValue())) {
LOGGER.info(" ignore invalid label with [key:{}, value:{}] of collector [name:{}]", entry.getKey(),
entry.getValue(), labelsCollector.getName());
continue;
}
if (innerAddLabel(labels, entry.getKey(), entry.getValue())) {
LOGGER.info("pick label with [key:{}, value:{}] of collector [name:{}]", entry.getKey(),
entry.getValue(), labelsCollector.getName());
@ -73,6 +79,40 @@ public class DefaultLabelsCollectorManager implements LabelsCollectorManager {
return labels;
}
private boolean checkValidLabel(String key, String value) {
return isValid(key) && isValid(value);
}
private static boolean isValid(String param) {
if (StringUtils.isBlank(param)) {
return false;
}
int length = param.length();
if (length > maxLength) {
return false;
}
for (int i = 0; i < length; i++) {
char ch = param.charAt(i);
if (!Character.isLetterOrDigit(ch) && !isValidChar(ch)) {
return false;
}
}
return true;
}
private static char[] validChars = new char[] {'_', '-', '.'};
private static int maxLength = 128;
private static boolean isValidChar(char ch) {
for (char c : validChars) {
if (c == ch) {
return true;
}
}
return false;
}
private ArrayList<LabelsCollector> loadLabelsCollectors() {
ServiceLoader<LabelsCollector> labelsCollectors = ServiceLoader.load(LabelsCollector.class);
ArrayList<LabelsCollector> labelsCollectorsList = new ArrayList<>();

View File

@ -41,22 +41,22 @@ public class ConnLabelsUtils {
public static final int TAG_V2_LABEL_KEY_VALUE_SPLIT_LENGTH = 2;
public static final int TAG_V1_LABEL_KEY_VALUE_SPLIT_LENGTH = 1;
/**
* parse property value to map.
*
* @date 2024/1/29
* @description will get a key-value map from properties, JVM OPTIONS, ENV by order of <tt>properties > JVM OPTIONS > ENV</tt>
* which will use the next level value when the current level value isn't setup.
* <p>eg: if the value of "nacos.app.conn.labels"(properties' key) is "k1=v1,k2=v2"(properties' value), the result will be
* parse property value to map.
*
* @param properties Properties
* @param propertyName which key to get
* @return (String)key-(String)value map
* @date 2024/1/29
* @description will get a key-value map from properties, JVM OPTIONS, ENV by order of <tt>properties > JVM OPTIONS
* > ENV</tt> which will use the next level value when the current level value isn't setup.
* <p>eg: if the value of "nacos.app.conn.labels"(properties' key) is "k1=v1,k2=v2"(properties' value), the result
* will be
* a Map with value{k1=v1,k2=v2}.</p>
* @param properties Properties
* @param propertyName which key to get
* @return (String)key-(String)value map
*/
public static Map<String, String> parsePropertyValue2Map(Properties properties, String propertyName) {
String rawLabels = properties.getProperty(propertyName, System.getProperty(propertyName, System.getenv(propertyName)));
String rawLabels = properties.getProperty(propertyName,
System.getProperty(propertyName, System.getenv(propertyName)));
if (StringUtils.isBlank(rawLabels)) {
LOGGER.info("no value found for property key: {}", propertyName);
return new HashMap<>(2);
@ -65,29 +65,24 @@ public class ConnLabelsUtils {
}
/**
* parse raw json labels into a key-value map.
*
* @date 2024/1/29
* @description
* @param rawLabels rawLabels to parse
* @return map parsed from rawLabels
*/
* parse raw json labels into a key-value map.
*
* @param rawLabels rawLabels to parse
* @return map parsed from rawLabels
* @date 2024/1/29
* @description
*/
public static Map<String, String> parseRawLabels(String rawLabels) {
if (StringUtils.isBlank(rawLabels)) {
return new HashMap<>(2);
}
HashMap<String, String> resultMap = new HashMap<>(2);
try {
Arrays.stream(rawLabels.split(LABEL_SPLIT_OPERATOR))
.filter(Objects::nonNull)
.map(String::trim)
.filter(StringUtils::isNotBlank)
.forEach(label -> {
Arrays.stream(rawLabels.split(LABEL_SPLIT_OPERATOR)).filter(Objects::nonNull).map(String::trim)
.filter(StringUtils::isNotBlank).forEach(label -> {
String[] kv = label.split(LABEL_EQUALS_OPERATOR);
if (kv.length == TAG_V2_LABEL_KEY_VALUE_SPLIT_LENGTH) {
resultMap.put(kv[0].trim(), kv[1].trim());
} else if (kv.length == TAG_V1_LABEL_KEY_VALUE_SPLIT_LENGTH) {
resultMap.put(kv[0].trim(), kv[0].trim());
} else {
LOGGER.error("unknown label format: {}", label);
}
@ -99,24 +94,32 @@ public class ConnLabelsUtils {
}
/**
* merge two map into one by using the former value when key is duplicated.
*
* @date 2024/1/29
* @description merge two map into one preferring using the first one when key is duplicated
* @param preferredMap preferredMap
* @param backwardMap backwardMap
*/
* merge two map into one by using the former value when key is duplicated.
*
* @param preferredMap preferredMap
* @param backwardMap backwardMap
* @date 2024/1/29
* @description merge two map into one preferring using the first one when key is duplicated
*/
public static <T, R> Map<T, R> mergeMapByOrder(Map<T, R> preferredMap, Map<T, R> backwardMap) {
if (preferredMap == null || preferredMap.isEmpty()) {
return new HashMap<T, R>(8) { {
putAll(backwardMap); } };
return new HashMap<T, R>(8) {
{
putAll(backwardMap);
}
};
}
if (backwardMap == null || backwardMap.isEmpty()) {
return new HashMap<T, R>(8) { {
putAll(preferredMap); } };
return new HashMap<T, R>(8) {
{
putAll(preferredMap);
}
};
}
HashMap<T, R> resultMap = new HashMap<T, R>(8) {{
putAll(preferredMap); } };
HashMap<T, R> resultMap = new HashMap<T, R>(8) {
{
putAll(preferredMap);
} };
backwardMap.forEach((key, value) -> {
if (!resultMap.containsKey(key)) {
resultMap.put(key, value);
@ -126,19 +129,18 @@ public class ConnLabelsUtils {
}
/**
* add prefix for each key in map.
*
* @date 2024/1/29
* @description add prefix for each key in map
* @param map map to add prefix
* @param prefix prefix
*/
* add prefix for each key in map.
*
* @param map map to add prefix
* @param prefix prefix
* @date 2024/1/29
* @description add prefix for each key in map
*/
public static <T> Map<String, T> addPrefixForEachKey(Map<String, T> map, String prefix) {
if (map == null || map.isEmpty()) {
return map;
}
return map.entrySet().stream().filter(Objects::nonNull)
.filter(elem -> !elem.getKey().trim().isEmpty())
return map.entrySet().stream().filter(Objects::nonNull).filter(elem -> !elem.getKey().trim().isEmpty())
.collect(Collectors.toMap(elem -> prefix + elem.getKey(), Map.Entry::getValue));
}
}

View File

@ -39,7 +39,7 @@ public class ConnLabelsUtilsTest {
String rawValue = "k1 = v1, k2 = v2";
properties.put(property, rawValue);
String property1 = "property2";
String rawValue1 = "k1, kk2";
String rawValue1 = "k11=v11, kk2";
properties.put(property1, rawValue1);
Map<String, String> m = ConnLabelsUtils.parsePropertyValue2Map(properties, property);
@ -48,15 +48,15 @@ public class ConnLabelsUtilsTest {
assertEquals("v2", m.get("k2"));
Map<String, String> m1 = ConnLabelsUtils.parsePropertyValue2Map(properties, property1);
assertEquals(2, m.size());
assertEquals("k1", m1.get("k1"));
assertEquals("kk2", m1.get("kk2"));
assertEquals(1, m1.size());
assertEquals("v11", m1.get("k11"));
assertEquals(null, m1.get("kk2"));
m = ConnLabelsUtils.mergeMapByOrder(m, m1);
assertEquals(3, m.size());
assertEquals("v1", m.get("k1"));
assertEquals("v2", m.get("k2"));
assertEquals("kk2", m.get("kk2"));
assertEquals("v11", m.get("k11"));
m = ConnLabelsUtils.addPrefixForEachKey(m, "test_prefix");
assertEquals(3, m.size());