From 5fffde5bde57557242b41a430805728913939677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E7=BF=8A=20SionYang?= Date: Mon, 27 Mar 2023 19:00:22 +0800 Subject: [PATCH] [ISSUE#10153] Add auth state into /state api and add announcement api. (#10203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add ModuleState and use ModuleState replace ServerStateController. * Add AuthModuleStateBuilder * state接口使用ModuleState. * Add announcement api. * skip rat scan for announcement.conf * default plugin open login page when auth.enabled=true. --- .../nacos/auth/config/AuthConfigs.java | 7 ++ .../auth/config/AuthModuleStateBuilder.java | 57 ++++++++++ ...libaba.nacos.sys.module.ModuleStateBuilder | 17 +++ .../config/AuthModuleStateBuilderTest.java | 61 ++++++++++ .../injector/NamingResourceInjectorTest.java | 2 + .../controller/ServerStateController.java | 27 +++-- .../controller/ServerStateControllerTest.java | 15 ++- distribution/conf/announcement.conf | 1 + .../auth/impl/NacosAuthPluginService.java | 6 + .../auth/spi/server/AuthPluginService.java | 9 ++ pom.xml | 1 + .../com/alibaba/nacos/sys/env/Constants.java | 8 ++ .../nacos/sys/env/EnvModuleStateBuilder.java | 39 +++++++ .../alibaba/nacos/sys/module/ModuleState.java | 55 +++++++++ .../nacos/sys/module/ModuleStateBuilder.java | 32 ++++++ .../nacos/sys/module/ModuleStateHolder.java | 105 ++++++++++++++++++ ...libaba.nacos.sys.module.ModuleStateBuilder | 17 +++ .../sys/env/EnvModuleStateBuilderTest.java | 43 +++++++ .../sys/module/ModuleStateHolderTest.java | 77 +++++++++++++ .../mock/ExceptionMockModuleStateBuilder.java | 28 +++++ .../module/mock/MockModuleStateBuilder.java | 30 +++++ ...libaba.nacos.sys.module.ModuleStateBuilder | 18 +++ 22 files changed, 647 insertions(+), 8 deletions(-) create mode 100644 auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java create mode 100644 auth/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder create mode 100644 auth/src/test/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilderTest.java create mode 100644 distribution/conf/announcement.conf create mode 100644 sys/src/main/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilder.java create mode 100644 sys/src/main/java/com/alibaba/nacos/sys/module/ModuleState.java create mode 100644 sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateBuilder.java create mode 100644 sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateHolder.java create mode 100644 sys/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder create mode 100644 sys/src/test/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilderTest.java create mode 100644 sys/src/test/java/com/alibaba/nacos/sys/module/ModuleStateHolderTest.java create mode 100644 sys/src/test/java/com/alibaba/nacos/sys/module/mock/ExceptionMockModuleStateBuilder.java create mode 100644 sys/src/test/java/com/alibaba/nacos/sys/module/mock/MockModuleStateBuilder.java create mode 100644 sys/src/test/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder diff --git a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java index 7c9460b99..594feab5d 100644 --- a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java +++ b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthConfigs.java @@ -26,6 +26,8 @@ import com.alibaba.nacos.common.utils.ConvertUtils; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.plugin.auth.constant.Constants; import com.alibaba.nacos.sys.env.EnvUtil; +import com.alibaba.nacos.sys.module.ModuleState; +import com.alibaba.nacos.sys.module.ModuleStateHolder; import com.alibaba.nacos.sys.utils.PropertiesUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -179,6 +181,11 @@ public class AuthConfigs extends Subscriber { .getProperty(Constants.Auth.NACOS_CORE_AUTH_ENABLE_USER_AGENT_AUTH_WHITE, Boolean.class, false); nacosAuthSystemType = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SYSTEM_TYPE, ""); refreshPluginProperties(); + ModuleStateHolder.getInstance().getModuleState(AuthModuleStateBuilder.AUTH_MODULE) + .ifPresent(moduleState -> { + ModuleState temp = new AuthModuleStateBuilder().build(); + moduleState.getStates().putAll(temp.getStates()); + }); } catch (Exception e) { LOGGER.warn("Upgrade auth config from env failed, use old value", e); } diff --git a/auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java new file mode 100644 index 000000000..dd83d1329 --- /dev/null +++ b/auth/src/main/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilder.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.auth.config; + +import com.alibaba.nacos.plugin.auth.spi.server.AuthPluginManager; +import com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService; +import com.alibaba.nacos.sys.module.ModuleState; +import com.alibaba.nacos.sys.module.ModuleStateBuilder; +import com.alibaba.nacos.sys.utils.ApplicationUtils; + +import java.util.Optional; + +/** + * Module state builder for auth module. + * + * @author xiweng.yy + */ +public class AuthModuleStateBuilder implements ModuleStateBuilder { + + public static final String AUTH_MODULE = "auth"; + + public static final String AUTH_ENABLED = "auth_enabled"; + + public static final String LOGIN_PAGE_ENABLED = "login_page_enabled"; + + public static final String AUTH_SYSTEM_TYPE = "auth_system_type"; + + @Override + public ModuleState build() { + ModuleState result = new ModuleState(AUTH_MODULE); + AuthConfigs authConfigs = ApplicationUtils.getBean(AuthConfigs.class); + result.newState(AUTH_ENABLED, authConfigs.isAuthEnabled()); + result.newState(LOGIN_PAGE_ENABLED, isLoginPageEnabled(authConfigs)); + result.newState(AUTH_SYSTEM_TYPE, authConfigs.getNacosAuthSystemType()); + return result; + } + + private Boolean isLoginPageEnabled(AuthConfigs authConfigs) { + Optional authPluginService = AuthPluginManager.getInstance() + .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType()); + return authPluginService.map(AuthPluginService::isLoginEnabled).orElse(false); + } +} diff --git a/auth/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder b/auth/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder new file mode 100644 index 000000000..9d80b854d --- /dev/null +++ b/auth/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder @@ -0,0 +1,17 @@ +# +# Copyright 1999-2023 Alibaba Group Holding Ltd. +# +# 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. +# + +com.alibaba.nacos.auth.config.AuthModuleStateBuilder diff --git a/auth/src/test/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilderTest.java b/auth/src/test/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilderTest.java new file mode 100644 index 000000000..bfed02f61 --- /dev/null +++ b/auth/src/test/java/com/alibaba/nacos/auth/config/AuthModuleStateBuilderTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.auth.config; + +import com.alibaba.nacos.sys.module.ModuleState; +import com.alibaba.nacos.sys.utils.ApplicationUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.context.ConfigurableApplicationContext; + +import static com.alibaba.nacos.auth.config.AuthModuleStateBuilder.AUTH_ENABLED; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class AuthModuleStateBuilderTest { + + @Mock + private ConfigurableApplicationContext context; + + @Mock + private AuthConfigs authConfigs; + + @Before + public void setUp() throws Exception { + when(context.getBean(AuthConfigs.class)).thenReturn(authConfigs); + ApplicationUtils.injectContext(context); + when(authConfigs.getNacosAuthSystemType()).thenReturn("nacos"); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testBuild() { + ModuleState actual = new AuthModuleStateBuilder().build(); + assertFalse((Boolean) actual.getStates().get(AUTH_ENABLED)); + assertFalse((Boolean) actual.getStates().get("login_page_enabled")); + assertEquals("nacos", actual.getStates().get("auth_system_type")); + } +} \ No newline at end of file diff --git a/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java b/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java index 97f36ecd9..9c51266e8 100644 --- a/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java @@ -49,6 +49,7 @@ public class NamingResourceInjectorTest { ramContext.setAccessKey(PropertyKeyConst.ACCESS_KEY); ramContext.setSecretKey(PropertyKeyConst.SECRET_KEY); stsCredential = new StsCredential(); + StsConfig.getInstance().setRamRoleName(null); } @After @@ -141,6 +142,7 @@ public class NamingResourceInjectorTest { private void clearForSts() throws NoSuchFieldException, IllegalAccessException { StsConfig.getInstance().setSecurityCredentialsUrl(null); + StsConfig.getInstance().setSecurityCredentials(null); Field field = StsCredentialHolder.class.getDeclaredField("stsCredential"); field.setAccessible(true); field.set(StsCredentialHolder.getInstance(), null); diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java b/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java index aa5ead4b1..75056bf09 100644 --- a/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java +++ b/console/src/main/java/com/alibaba/nacos/console/controller/ServerStateController.java @@ -16,13 +16,18 @@ package com.alibaba.nacos.console.controller; -import com.alibaba.nacos.common.utils.VersionUtils; +import com.alibaba.nacos.common.model.RestResult; +import com.alibaba.nacos.common.model.RestResultUtils; import com.alibaba.nacos.sys.env.EnvUtil; +import com.alibaba.nacos.sys.module.ModuleState; +import com.alibaba.nacos.sys.module.ModuleStateHolder; +import com.alibaba.nacos.sys.utils.DiskUtils; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.io.File; import java.util.HashMap; import java.util.Map; @@ -35,6 +40,8 @@ import java.util.Map; @RequestMapping("/v1/console/server") public class ServerStateController { + private static final String ANNOUNCEMENT_FILE = "announcement.conf"; + /** * Get server state of current server. * @@ -43,13 +50,19 @@ public class ServerStateController { @GetMapping("/state") public ResponseEntity> serverState() { Map serverState = new HashMap<>(4); - serverState.put("standalone_mode", - EnvUtil.getStandaloneMode() ? EnvUtil.STANDALONE_MODE_ALONE : EnvUtil.STANDALONE_MODE_CLUSTER); - - serverState.put("function_mode", EnvUtil.getFunctionMode()); - serverState.put("version", VersionUtils.version); - + for (ModuleState each : ModuleStateHolder.getInstance().getAllModuleStates()) { + each.getStates().forEach((s, o) -> serverState.put(s, null == o ? null : o.toString())); + } return ResponseEntity.ok().body(serverState); } + @GetMapping("/announcement") + public RestResult getAnnouncement() { + File announcementFile = new File(EnvUtil.getConfPath(), ANNOUNCEMENT_FILE); + String announcement = null; + if (announcementFile.exists() && announcementFile.isFile()) { + announcement = DiskUtils.readFile(announcementFile); + } + return RestResultUtils.success(announcement); + } } diff --git a/console/src/test/java/com/alibaba/nacos/console/controller/ServerStateControllerTest.java b/console/src/test/java/com/alibaba/nacos/console/controller/ServerStateControllerTest.java index b2d5cab9c..ac21a1abb 100644 --- a/console/src/test/java/com/alibaba/nacos/console/controller/ServerStateControllerTest.java +++ b/console/src/test/java/com/alibaba/nacos/console/controller/ServerStateControllerTest.java @@ -16,12 +16,18 @@ package com.alibaba.nacos.console.controller; +import com.alibaba.nacos.common.utils.JacksonUtils; +import com.alibaba.nacos.common.utils.VersionUtils; +import com.alibaba.nacos.sys.env.Constants; +import com.alibaba.nacos.sys.env.EnvUtil; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -29,6 +35,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; /** * ServerStateController unit test. + * * @ClassName: ServerStateControllerTest * @Author: ChenHao26 * @Date: 2022/8/13 10:54 @@ -52,6 +59,12 @@ public class ServerStateControllerTest { @Test public void serverState() throws Exception { MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(CONSOLE_URL); - Assert.assertEquals(200, mockmvc.perform(builder).andReturn().getResponse().getStatus()); + MockHttpServletResponse response = mockmvc.perform(builder).andReturn().getResponse(); + Assert.assertEquals(200, response.getStatus()); + ObjectNode responseContent = JacksonUtils.toObj(response.getContentAsByteArray(), ObjectNode.class); + Assert.assertEquals(EnvUtil.STANDALONE_MODE_CLUSTER, + responseContent.get(Constants.STANDALONE_MODE_STATE).asText()); + Assert.assertEquals("null", responseContent.get(Constants.FUNCTION_MODE_STATE).asText()); + Assert.assertEquals(VersionUtils.version, responseContent.get(Constants.NACOS_VERSION).asText()); } } diff --git a/distribution/conf/announcement.conf b/distribution/conf/announcement.conf new file mode 100644 index 000000000..0c55968b5 --- /dev/null +++ b/distribution/conf/announcement.conf @@ -0,0 +1 @@ +当前集群没有开启鉴权,请参考[文档](https://nacos.io/zh-cn/docs/v2/guide/user/auth.html)开启鉴权~ \ No newline at end of file diff --git a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java index 5ec9200ee..4902e6652 100644 --- a/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java +++ b/plugin-default-impl/src/main/java/com/alibaba/nacos/plugin/auth/impl/NacosAuthPluginService.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.plugin.auth.impl; import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.auth.config.AuthConfigs; import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.plugin.auth.api.IdentityContext; import com.alibaba.nacos.plugin.auth.api.Permission; @@ -107,6 +108,11 @@ public class NacosAuthPluginService implements AuthPluginService { return AuthConstants.AUTH_PLUGIN_TYPE; } + @Override + public boolean isLoginEnabled() { + return ApplicationUtils.getBean(AuthConfigs.class).isAuthEnabled(); + } + protected void checkNacosAuthManager() { if (null == authenticationManager) { authenticationManager = ApplicationUtils.getBean(DefaultAuthenticationManager.class); diff --git a/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java b/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java index a4ba323ef..f08dd3b1b 100644 --- a/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java +++ b/plugin/auth/src/main/java/com/alibaba/nacos/plugin/auth/spi/server/AuthPluginService.java @@ -75,4 +75,13 @@ public interface AuthPluginService { */ String getAuthServiceName(); + /** + * Is the plugin enable login. + * + * @return {@code true} if plugin need login, otherwise {@code false} + * @since 2.2.2 + */ + default boolean isLoginEnabled() { + return false; + } } diff --git a/pom.xml b/pom.xml index 4bcffdc92..fd5d7ac07 100644 --- a/pom.xml +++ b/pom.xml @@ -354,6 +354,7 @@ **/any.proto src/main/java/com/alibaba/nacos/common/packagescan/classreading/** .flattened-pom.xml + **/announcement.conf diff --git a/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java b/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java index 6c42d7faf..1e07f6a6b 100644 --- a/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java +++ b/sys/src/main/java/com/alibaba/nacos/sys/env/Constants.java @@ -24,6 +24,8 @@ package com.alibaba.nacos.sys.env; */ public interface Constants { + String SYS_MODULE = "sys"; + /** * Spring Profile : "standalone". */ @@ -34,11 +36,15 @@ public interface Constants { */ String STANDALONE_MODE_PROPERTY_NAME = "nacos.standalone"; + String STANDALONE_MODE_STATE = "standalone_mode"; + /** * The System property name of Function mode. */ String FUNCTION_MODE_PROPERTY_NAME = "nacos.functionMode"; + String FUNCTION_MODE_STATE = "function_mode"; + /** * The System property name of prefer hostname over ip. */ @@ -49,6 +55,8 @@ public interface Constants { */ String ROOT_WEB_CONTEXT_PATH = "/"; + String NACOS_VERSION = "version"; + String NACOS_SERVER_IP = "nacos.server.ip"; String USE_ONLY_SITE_INTERFACES = "nacos.inetutils.use-only-site-local-interfaces"; diff --git a/sys/src/main/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilder.java b/sys/src/main/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilder.java new file mode 100644 index 000000000..b4e55c98d --- /dev/null +++ b/sys/src/main/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilder.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.env; + +import com.alibaba.nacos.common.utils.VersionUtils; +import com.alibaba.nacos.sys.module.ModuleState; +import com.alibaba.nacos.sys.module.ModuleStateBuilder; + +/** + * Module state builder for env module. + * + * @author xiweng.yy + */ +public class EnvModuleStateBuilder implements ModuleStateBuilder { + + @Override + public ModuleState build() { + ModuleState result = new ModuleState(Constants.SYS_MODULE); + result.newState(Constants.STANDALONE_MODE_STATE, + EnvUtil.getStandaloneMode() ? EnvUtil.STANDALONE_MODE_ALONE : EnvUtil.STANDALONE_MODE_CLUSTER); + result.newState(Constants.FUNCTION_MODE_STATE, EnvUtil.getFunctionMode()); + result.newState(Constants.NACOS_VERSION, VersionUtils.version); + return result; + } +} diff --git a/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleState.java b/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleState.java new file mode 100644 index 000000000..4e5145af4 --- /dev/null +++ b/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleState.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.module; + +import java.util.HashMap; +import java.util.Map; + +/** + * Module state. + * + * @author xiweng.yy + */ +public class ModuleState { + + private final String moduleName; + + private final Map states; + + public ModuleState(String moduleName) { + this.moduleName = moduleName; + this.states = new HashMap<>(); + } + + public String getModuleName() { + return moduleName; + } + + public ModuleState newState(String stateName, Object stateValue) { + this.states.put(stateName, stateValue); + return this; + } + + public Map getStates() { + return states; + } + + @SuppressWarnings("all") + public T getState(String stateName, T defaultValue) { + return (T) states.getOrDefault(stateName, defaultValue); + } +} diff --git a/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateBuilder.java b/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateBuilder.java new file mode 100644 index 000000000..f79e1324a --- /dev/null +++ b/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateBuilder.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.module; + +/** + * Module state builder. + * + * @author xiweng.yy + */ +public interface ModuleStateBuilder { + + /** + * Build module state. + * + * @return ModuleState + */ + ModuleState build(); +} diff --git a/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateHolder.java b/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateHolder.java new file mode 100644 index 000000000..eeeee6849 --- /dev/null +++ b/sys/src/main/java/com/alibaba/nacos/sys/module/ModuleStateHolder.java @@ -0,0 +1,105 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.module; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.alibaba.nacos.common.utils.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Module State Holder. + * + * @author xiweng.yy + */ +public class ModuleStateHolder { + + private static final Logger LOGGER = LoggerFactory.getLogger(ModuleStateHolder.class); + + private static final ModuleStateHolder INSTANCE = new ModuleStateHolder(); + + private final Map moduleStates; + + private ModuleStateHolder() { + this.moduleStates = new HashMap<>(); + for (ModuleStateBuilder each : NacosServiceLoader.load(ModuleStateBuilder.class)) { + try { + ModuleState moduleState = each.build(); + moduleStates.put(moduleState.getModuleName(), moduleState); + } catch (Exception e) { + LOGGER.warn("Build ModuleState failed in builder:{}", each.getClass().getCanonicalName(), e); + } + } + } + + public static ModuleStateHolder getInstance() { + return INSTANCE; + } + + public Optional getModuleState(String moduleName) { + return Optional.ofNullable(moduleStates.get(moduleName)); + } + + public Set getAllModuleStates() { + return new HashSet<>(moduleStates.values()); + } + + public String getStateValueByName(String moduleName, String stateName) { + return getStateValueByName(moduleName, stateName, StringUtils.EMPTY); + } + + /** + * Get State Value by module name and state name. + * + * @param moduleName module name of state + * @param stateName state name + * @param defaultValue default value when can't find module or state + * @return state value + */ + public T getStateValueByName(String moduleName, String stateName, T defaultValue) { + Optional moduleState = getModuleState(moduleName); + if (!moduleState.isPresent()) { + return defaultValue; + } + return moduleState.get().getState(stateName, defaultValue); + } + + /** + * Search State Value by state name one by one. + * + * @param stateName state name + * @param defaultValue default value when can't find module or state + * @return state value + */ + @SuppressWarnings("all") + public T searchStateValue(String stateName, T defaultValue) { + T result = null; + for (ModuleState each : getAllModuleStates()) { + if (each.getStates().containsKey(stateName)) { + result = (T) each.getStates().get(stateName); + break; + } + } + return null == result ? defaultValue : result; + } +} diff --git a/sys/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder b/sys/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder new file mode 100644 index 000000000..30cbcc5d5 --- /dev/null +++ b/sys/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder @@ -0,0 +1,17 @@ +# +# Copyright 1999-2023 Alibaba Group Holding Ltd. +# +# 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. +# + +com.alibaba.nacos.sys.env.EnvModuleStateBuilder diff --git a/sys/src/test/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilderTest.java b/sys/src/test/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilderTest.java new file mode 100644 index 000000000..591795ca5 --- /dev/null +++ b/sys/src/test/java/com/alibaba/nacos/sys/env/EnvModuleStateBuilderTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.env; + +import com.alibaba.nacos.common.utils.VersionUtils; +import com.alibaba.nacos.sys.module.ModuleState; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class EnvModuleStateBuilderTest { + + @BeforeClass + public static void setUp() throws Exception { + System.setProperty(Constants.STANDALONE_MODE_PROPERTY_NAME, "true"); + EnvUtil.setIsStandalone(null); + } + + @Test + public void testBuild() { + ModuleState actual = new EnvModuleStateBuilder().build(); + assertEquals(Constants.SYS_MODULE, actual.getModuleName()); + assertEquals(EnvUtil.STANDALONE_MODE_ALONE, actual.getStates().get(Constants.STANDALONE_MODE_STATE)); + assertNull(EnvUtil.FUNCTION_MODE_NAMING, actual.getStates().get(Constants.FUNCTION_MODE_STATE)); + assertEquals(VersionUtils.version, actual.getStates().get(Constants.NACOS_VERSION)); + } +} \ No newline at end of file diff --git a/sys/src/test/java/com/alibaba/nacos/sys/module/ModuleStateHolderTest.java b/sys/src/test/java/com/alibaba/nacos/sys/module/ModuleStateHolderTest.java new file mode 100644 index 000000000..40733749d --- /dev/null +++ b/sys/src/test/java/com/alibaba/nacos/sys/module/ModuleStateHolderTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.module; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ModuleStateHolderTest { + + private Map moduleStateMap; + + @Before + public void setUp() throws Exception { + moduleStateMap = (Map) ReflectionTestUtils + .getField(ModuleStateHolder.getInstance(), ModuleStateHolder.class, "moduleStates"); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testGetModuleState() { + assertNotNull(ModuleStateHolder.getInstance().getModuleState("mock")); + } + + @Test + public void testGetAllModuleStates() { + assertEquals(2, ModuleStateHolder.getInstance().getAllModuleStates().size()); + } + + @Test + public void testGetStateValueByNameFound() { + assertEquals("test", ModuleStateHolder.getInstance().getStateValueByName("mock", "test")); + assertEquals("test", ModuleStateHolder.getInstance().getStateValueByName("mock", "test", "aaa")); + } + + @Test + public void testGetStateValueByNameWithoutModuleState() { + assertEquals("", ModuleStateHolder.getInstance().getStateValueByName("non-exist", "test")); + assertEquals("aaa", ModuleStateHolder.getInstance().getStateValueByName("non-exist", "test", "aaa")); + } + + @Test + public void testGetStateValueByNameWithoutStateName() { + assertEquals("", ModuleStateHolder.getInstance().getStateValueByName("mock", "non-exist")); + assertEquals("aaa", ModuleStateHolder.getInstance().getStateValueByName("mock", "non-exist", "aaa")); + } + + @Test + public void testSearchStateValue() { + assertEquals("test", ModuleStateHolder.getInstance().searchStateValue("test", "aaa")); + assertEquals("aaa", ModuleStateHolder.getInstance().searchStateValue("non-exist", "aaa")); + } + +} \ No newline at end of file diff --git a/sys/src/test/java/com/alibaba/nacos/sys/module/mock/ExceptionMockModuleStateBuilder.java b/sys/src/test/java/com/alibaba/nacos/sys/module/mock/ExceptionMockModuleStateBuilder.java new file mode 100644 index 000000000..e0a313b00 --- /dev/null +++ b/sys/src/test/java/com/alibaba/nacos/sys/module/mock/ExceptionMockModuleStateBuilder.java @@ -0,0 +1,28 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.module.mock; + +import com.alibaba.nacos.sys.module.ModuleState; +import com.alibaba.nacos.sys.module.ModuleStateBuilder; + +public class ExceptionMockModuleStateBuilder implements ModuleStateBuilder { + + @Override + public ModuleState build() { + throw new RuntimeException("test"); + } +} diff --git a/sys/src/test/java/com/alibaba/nacos/sys/module/mock/MockModuleStateBuilder.java b/sys/src/test/java/com/alibaba/nacos/sys/module/mock/MockModuleStateBuilder.java new file mode 100644 index 000000000..33bd8845d --- /dev/null +++ b/sys/src/test/java/com/alibaba/nacos/sys/module/mock/MockModuleStateBuilder.java @@ -0,0 +1,30 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * 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.alibaba.nacos.sys.module.mock; + +import com.alibaba.nacos.sys.module.ModuleState; +import com.alibaba.nacos.sys.module.ModuleStateBuilder; + +public class MockModuleStateBuilder implements ModuleStateBuilder { + + @Override + public ModuleState build() { + ModuleState result = new ModuleState("mock"); + result.newState("test", "test").newState("mock", true); + return result; + } +} diff --git a/sys/src/test/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder b/sys/src/test/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder new file mode 100644 index 000000000..309959a1b --- /dev/null +++ b/sys/src/test/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder @@ -0,0 +1,18 @@ +# +# Copyright 1999-2023 Alibaba Group Holding Ltd. +# +# 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. +# + +com.alibaba.nacos.sys.module.mock.MockModuleStateBuilder +com.alibaba.nacos.sys.module.mock.ExceptionMockModuleStateBuilder