diff --git a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java index 01250dac8..37e90f04d 100644 --- a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java +++ b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java @@ -85,6 +85,20 @@ NacosPropertySource build(String dataId, String group, String fileExtension, return nacosPropertySource; } + NacosPropertySource buildWithContext(String dataId, String group, String fileExtension, String context) { + List> propertySources; + try { + propertySources = NacosDataParserHandler.getInstance().parseNacosData(dataId, context, fileExtension); + } catch (Exception e) { + log.error("build config error, dataId: {}, group: {}, context: {}", dataId, group, context, e); + return null; + } + NacosPropertySource nacosPropertySource = new NacosPropertySource(propertySources, + group, dataId, new Date(), true); + NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource); + return nacosPropertySource; + } + private List> loadNacosData(String dataId, String group, String fileExtension) { String data = null; diff --git a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java index ec273bb27..702d5222c 100644 --- a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java +++ b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceLocator.java @@ -21,6 +21,8 @@ import com.huaweicloud.nacos.config.NacosConfigConst; import com.alibaba.cloud.nacos.NacosConfigProperties; import com.alibaba.cloud.nacos.NacosPropertySourceRepository; +import com.huaweicloud.nacos.config.client.NacosPropertiesFuzzyQueryService; +import com.huaweicloud.nacos.config.client.PropertyConfigItem; import com.huaweicloud.nacos.config.manager.NacosConfigManager; import com.alibaba.cloud.nacos.parser.NacosDataParserHandler; import com.alibaba.cloud.nacos.refresh.NacosContextRefresher; @@ -100,14 +102,29 @@ public PropertySource locate(Environment env) { // load security configs loadSecurityConfigs(composite, env); + // load router configs loadLabelRouterConfigs(composite, env); return composite; } private void loadLabelRouterConfigs(CompositePropertySource composite, Environment env) { - String group = nacosConfigProperties.getGroup(); - String dataId = buildIncludeServiceNameDataId(env, NacosConfigConst.LABEL_ROUTER_DATA_ID_PREFIX); - loadNacosDataIfPresent(composite, dataId, group, NacosConfigConst.DEFAULT_CONFIG_FILE_EXTENSION, true); + if (!env.getProperty(NacosConfigConst.ROUTER_CONFIG_DEFAULT_LOAD_ENABLED, boolean.class, false)) { + return; + } + NacosPropertiesFuzzyQueryService blurQueryService = NacosPropertiesFuzzyQueryService.getInstance(); + blurQueryService.setConfigProperties(nacosConfigProperties); + List routerProperties = blurQueryService.loadRouterProperties(); + if (CollectionUtils.isEmpty(routerProperties)) { + return; + } + for (PropertyConfigItem item: routerProperties) { + NacosPropertySource propertySource = nacosPropertySourceBuilder.buildWithContext(item.getDataId(), + item.getGroup(), item.getType(), item.getContent()); + if (propertySource == null) { + continue; + } + this.addFirstPropertySource(composite, propertySource, false); + } } private void loadSecurityConfigs(CompositePropertySource composite, Environment env) { diff --git a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/NacosConfigConst.java b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/NacosConfigConst.java index e44202ce7..60cd22eeb 100644 --- a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/NacosConfigConst.java +++ b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/NacosConfigConst.java @@ -29,4 +29,7 @@ public class NacosConfigConst { public static final String RETRY_MASTER_ENABLED = "spring.cloud.nacos.config.retryMasterServerEnabled"; public static final String LABEL_ROUTER_DATA_ID_PREFIX = "cse-label-route-"; + + public static final String ROUTER_CONFIG_DEFAULT_LOAD_ENABLED + = "spring.cloud.nacos.config.routerConfigDefaultLoadEnabled"; } diff --git a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/NacosPropertiesFuzzyQueryService.java b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/NacosPropertiesFuzzyQueryService.java new file mode 100644 index 000000000..a26d2ff71 --- /dev/null +++ b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/NacosPropertiesFuzzyQueryService.java @@ -0,0 +1,157 @@ +/* + + * Copyright (C) 2020-2024 Huawei Technologies Co., Ltd. All rights reserved. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huaweicloud.nacos.config.client; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.cloud.nacos.NacosConfigProperties; +import com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant; +import com.alibaba.nacos.client.auth.impl.process.HttpLoginProcessor; +import com.alibaba.nacos.client.config.impl.ConfigHttpClientManager; +import com.alibaba.nacos.common.http.HttpRestResult; +import com.alibaba.nacos.common.http.client.NacosRestTemplate; +import com.alibaba.nacos.common.http.param.Header; +import com.alibaba.nacos.common.http.param.Query; +import com.alibaba.nacos.plugin.auth.api.LoginIdentityContext; +import com.huaweicloud.nacos.config.NacosConfigConst; +import com.huaweicloud.nacos.config.manager.ConfigServiceManagerUtils; + +public class NacosPropertiesFuzzyQueryService { + private static final Logger LOGGER = LoggerFactory.getLogger(NacosPropertiesFuzzyQueryService.class); + + private static final String NACOS_CONFIG_QUERY_URI = "%s/nacos/v1/cs/configs"; + + private NacosConfigProperties configProperties; + + private Properties properties; + + private final Map address_token = new ConcurrentHashMap<>(); + + private long tokenTtl; + + private long lastRefreshTime; + + private long refreshWindow; + + private static final NacosPropertiesFuzzyQueryService INSTANCE = new NacosPropertiesFuzzyQueryService(); + + private NacosPropertiesFuzzyQueryService() { + + } + + public static NacosPropertiesFuzzyQueryService getInstance() { + return INSTANCE; + } + + public List loadRouterProperties() { + try { + String address = chooseAddress(); + NacosRestTemplate nacosRestTemplate = ConfigHttpClientManager.getInstance().getNacosRestTemplate(); + HttpRestResult response = nacosRestTemplate.get(buildUrl(address), initHeader(address), + buildQuery(), PropertiePageQueryResult.class); + return response.getData().getPageItems(); + } catch (Exception e) { + LOGGER.error("load router properties failed!", e); + return Collections.emptyList(); + } + } + + private Query buildQuery() { + Query query = new Query(); + query.addParam("dataId", NacosConfigConst.LABEL_ROUTER_DATA_ID_PREFIX + "*"); + query.addParam("group", configProperties.getGroup()); + query.addParam("tenant", getNamespace()); + + // this value is fixes when using blur query configs + query.addParam("search", "blur"); + query.addParam("pageNo", 1); + query.addParam("pageSize", 100); + return query; + } + + private Header initHeader(String address) { + Header header = Header.newInstance(); + if (!StringUtils.isEmpty(configProperties.getUsername())) { + header.addParam(NacosAuthLoginConstant.ACCESSTOKEN, getAccessToken(address)); + } + return header; + } + + private String buildUrl(String address) { + String prefix = ""; + if (!configProperties.getServerAddr().startsWith("http")) { + prefix = "http://"; + } + return prefix + String.format(NACOS_CONFIG_QUERY_URI, address); + } + + private String getNamespace() { + return StringUtils.isEmpty(configProperties.getNamespace()) ? "" : configProperties.getNamespace(); + } + + private String chooseAddress() { + properties = configProperties.assembleMasterNacosServerProperties(); + if (!configProperties.isMasterStandbyEnabled()) { + return configProperties.getServerAddr(); + } + if (ConfigServiceManagerUtils.checkServerConnect(configProperties.getServerAddr())) { + return configProperties.getServerAddr(); + } + if (ConfigServiceManagerUtils.checkServerConnect(configProperties.getStandbyServerAddr())) { + properties = configProperties.assembleStandbyNacosServerProperties(); + return configProperties.getStandbyServerAddr(); + } + return configProperties.getServerAddr(); + } + + private String getAccessToken(String address) { + if (address_token.get(address) != null + && (System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS.toMillis(tokenTtl - refreshWindow)) { + return address_token.get(address); + } + HttpLoginProcessor httpLoginProcessor + = new HttpLoginProcessor(ConfigHttpClientManager.getInstance().getNacosRestTemplate()); + properties.setProperty(NacosAuthLoginConstant.SERVER, address); + LoginIdentityContext identityContext = httpLoginProcessor.getResponse(properties); + if (identityContext != null + && !StringUtils.isEmpty(identityContext.getParameter(NacosAuthLoginConstant.ACCESSTOKEN))) { + tokenTtl = Long.parseLong(identityContext.getParameter(NacosAuthLoginConstant.TOKENTTL)); + refreshWindow = tokenTtl / 10; + lastRefreshTime = System.currentTimeMillis(); + address_token.put(address, identityContext.getParameter(NacosAuthLoginConstant.ACCESSTOKEN)); + return identityContext.getParameter(NacosAuthLoginConstant.ACCESSTOKEN); + } + lastRefreshTime = System.currentTimeMillis(); + return ""; + } + + public void setConfigProperties(NacosConfigProperties nacosConfigProperties) { + if (configProperties == null) { + this.configProperties = nacosConfigProperties; + } + } +} diff --git a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/PropertiePageQueryResult.java b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/PropertiePageQueryResult.java new file mode 100644 index 000000000..0fab164bb --- /dev/null +++ b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/PropertiePageQueryResult.java @@ -0,0 +1,62 @@ +/* + + * Copyright (C) 2020-2024 Huawei Technologies Co., Ltd. All rights reserved. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huaweicloud.nacos.config.client; + +import java.util.List; + +public class PropertiePageQueryResult { + private Integer totalCount; + + private Integer pageNumber; + + private Integer pagesAvailable; + + private List pageItems; + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } + + public Integer getPageNumber() { + return pageNumber; + } + + public void setPageNumber(Integer pageNumber) { + this.pageNumber = pageNumber; + } + + public Integer getPagesAvailable() { + return pagesAvailable; + } + + public void setPagesAvailable(Integer pagesAvailable) { + this.pagesAvailable = pagesAvailable; + } + + public List getPageItems() { + return pageItems; + } + + public void setPageItems(List pageItems) { + this.pageItems = pageItems; + } +} diff --git a/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/PropertyConfigItem.java b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/PropertyConfigItem.java new file mode 100644 index 000000000..3ca8e27b6 --- /dev/null +++ b/spring-cloud-huawei-nacos/spring-cloud-huawei-nacos-config/src/main/java/com/huaweicloud/nacos/config/client/PropertyConfigItem.java @@ -0,0 +1,116 @@ +/* + + * Copyright (C) 2020-2024 Huawei Technologies Co., Ltd. All rights reserved. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huaweicloud.nacos.config.client; + +public class PropertyConfigItem { + private long id; + + private String tenant; + + private String appName; + + /** + * config file type(xml,json,yaml,text,html) + */ + private String type; + + private String dataId; + + private String group; + + /** + * config content + */ + private String content; + + private String md5; + + private String encryptedDataKey; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getTenant() { + return tenant; + } + + public void setTenant(String tenant) { + this.tenant = tenant; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDataId() { + return dataId; + } + + public void setDataId(String dataId) { + this.dataId = dataId; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getMd5() { + return md5; + } + + public void setMd5(String md5) { + this.md5 = md5; + } + + public String getEncryptedDataKey() { + return encryptedDataKey; + } + + public void setEncryptedDataKey(String encryptedDataKey) { + this.encryptedDataKey = encryptedDataKey; + } +}