From 429d2bb5ee3182ae150ec1c438aa488c67bfa965 Mon Sep 17 00:00:00 2001 From: DongYafei <1823366314@qq.com> Date: Fri, 26 Aug 2022 09:51:58 +0800 Subject: [PATCH] for #8308, add namespace api v2.0 (#9012) * Add NamespaceControllerV2 and UT * add api [query namespace by namespaceId] --- .../alibaba/nacos/api/model/v2/ErrorCode.java | 5 + .../controller/NamespaceController.java | 67 ++------ .../controller/v2/NamespaceControllerV2.java | 144 +++++++++++++++++ .../nacos/console/model/vo/NamespaceVo.java | 111 +++++++++++++ .../service/NamespaceOperationService.java | 149 ++++++++++++++++++ .../v2/NamespaceControllerV2Test.java | 137 ++++++++++++++++ .../NamespaceOperationServiceTest.java | 139 ++++++++++++++++ 7 files changed, 697 insertions(+), 55 deletions(-) create mode 100644 console/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java create mode 100644 console/src/main/java/com/alibaba/nacos/console/model/vo/NamespaceVo.java create mode 100644 console/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java create mode 100644 console/src/test/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2Test.java create mode 100644 console/src/test/java/com/alibaba/nacos/console/service/NamespaceOperationServiceTest.java diff --git a/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java b/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java index 9f0580c2f..b86897c11 100644 --- a/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java +++ b/api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java @@ -160,6 +160,11 @@ public enum ErrorCode { */ NAMESPACE_NOT_EXIST(22001, "namespace not exist"), + /** + * namespace already exist. + */ + NAMESPACE_ALREADY_EXIST(22002, "namespace already exist"), + /** * illegal state. */ diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java b/console/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java index 642b8cf4c..d54716e6d 100644 --- a/console/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java +++ b/console/src/main/java/com/alibaba/nacos/console/controller/NamespaceController.java @@ -16,15 +16,15 @@ package com.alibaba.nacos.console.controller; +import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.auth.annotation.Secured; import com.alibaba.nacos.common.model.RestResult; import com.alibaba.nacos.common.model.RestResultUtils; import com.alibaba.nacos.common.utils.StringUtils; -import com.alibaba.nacos.config.server.model.TenantInfo; import com.alibaba.nacos.config.server.service.repository.PersistService; -import com.alibaba.nacos.console.enums.NamespaceTypeEnum; import com.alibaba.nacos.console.model.Namespace; import com.alibaba.nacos.console.model.NamespaceAllInfo; +import com.alibaba.nacos.console.service.NamespaceOperationService; import com.alibaba.nacos.plugin.auth.constant.ActionTypes; import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; import org.springframework.beans.factory.annotation.Autowired; @@ -36,7 +36,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.regex.Pattern; @@ -53,24 +52,13 @@ public class NamespaceController { @Autowired private PersistService persistService; + @Autowired + private NamespaceOperationService namespaceOperationService; + private final Pattern namespaceIdCheckPattern = Pattern.compile("^[\\w-]+"); private static final int NAMESPACE_ID_MAX_LENGTH = 128; - private static final String DEFAULT_NAMESPACE = "public"; - - private static final int DEFAULT_QUOTA = 200; - - private static final String DEFAULT_CREATE_SOURCE = "nacos"; - - private static final String DEFAULT_NAMESPACE_SHOW_NAME = "Public"; - - private static final String DEFAULT_NAMESPACE_DESCRIPTION = "Public Namespace"; - - private static final String DEFAULT_TENANT = ""; - - private static final String DEFAULT_KP = "1"; - /** * Get namespace list. * @@ -78,19 +66,7 @@ public class NamespaceController { */ @GetMapping public RestResult> getNamespaces() { - // TODO 获取用kp - List tenantInfos = persistService.findTenantByKp(DEFAULT_KP); - Namespace namespace0 = new Namespace("", DEFAULT_NAMESPACE, DEFAULT_QUOTA, - persistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType()); - List namespaces = new ArrayList<>(); - namespaces.add(namespace0); - for (TenantInfo tenantInfo : tenantInfos) { - int configCount = persistService.configInfoCount(tenantInfo.getTenantId()); - Namespace namespaceTmp = new Namespace(tenantInfo.getTenantId(), tenantInfo.getTenantName(), - tenantInfo.getTenantDesc(), DEFAULT_QUOTA, configCount, NamespaceTypeEnum.CUSTOM.getType()); - namespaces.add(namespaceTmp); - } - return RestResultUtils.success(namespaces); + return RestResultUtils.success(namespaceOperationService.getNamespaceList()); } /** @@ -100,18 +76,8 @@ public class NamespaceController { * @return namespace all info */ @GetMapping(params = "show=all") - public NamespaceAllInfo getNamespace(@RequestParam("namespaceId") String namespaceId) { - // TODO 获取用kp - if (StringUtils.isBlank(namespaceId)) { - return new NamespaceAllInfo(namespaceId, DEFAULT_NAMESPACE_SHOW_NAME, DEFAULT_QUOTA, - persistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType(), - DEFAULT_NAMESPACE_DESCRIPTION); - } else { - TenantInfo tenantInfo = persistService.findTenantByKp(DEFAULT_KP, namespaceId); - int configCount = persistService.configInfoCount(namespaceId); - return new NamespaceAllInfo(namespaceId, tenantInfo.getTenantName(), DEFAULT_QUOTA, configCount, - NamespaceTypeEnum.CUSTOM.getType(), tenantInfo.getTenantDesc()); - } + public NamespaceAllInfo getNamespace(@RequestParam("namespaceId") String namespaceId) throws NacosException { + return namespaceOperationService.getNamespace(namespaceId, false); } /** @@ -125,8 +91,7 @@ public class NamespaceController { @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE) public Boolean createNamespace(@RequestParam("customNamespaceId") String namespaceId, @RequestParam("namespaceName") String namespaceName, - @RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) { - // TODO 获取用kp + @RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) throws NacosException { if (StringUtils.isBlank(namespaceId)) { namespaceId = UUID.randomUUID().toString(); } else { @@ -137,13 +102,8 @@ public class NamespaceController { if (namespaceId.length() > NAMESPACE_ID_MAX_LENGTH) { return false; } - if (persistService.tenantInfoCountByTenantId(namespaceId) > 0) { - return false; - } } - persistService.insertTenantInfoAtomic(DEFAULT_KP, namespaceId, namespaceName, namespaceDesc, - DEFAULT_CREATE_SOURCE, System.currentTimeMillis()); - return true; + return namespaceOperationService.createNamespace(namespaceId, namespaceName, namespaceDesc, false); } /** @@ -173,9 +133,7 @@ public class NamespaceController { public Boolean editNamespace(@RequestParam("namespace") String namespace, @RequestParam("namespaceShowName") String namespaceShowName, @RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) { - // TODO 获取用kp - persistService.updateTenantNameAtomic(DEFAULT_KP, namespace, namespaceShowName, namespaceDesc); - return true; + return namespaceOperationService.editNamespace(namespace, namespaceShowName, namespaceDesc); } /** @@ -187,8 +145,7 @@ public class NamespaceController { @DeleteMapping @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE) public Boolean deleteConfig(@RequestParam("namespaceId") String namespaceId) { - persistService.removeTenantInfoAtomic(DEFAULT_KP, namespaceId); - return true; + return namespaceOperationService.removeNamespace(namespaceId); } } diff --git a/console/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java b/console/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java new file mode 100644 index 000000000..689fd575b --- /dev/null +++ b/console/src/main/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2.java @@ -0,0 +1,144 @@ +/* + * Copyright 1999-2022 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.console.controller.v2; + +import com.alibaba.nacos.api.annotation.NacosApi; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.exception.api.NacosApiException; +import com.alibaba.nacos.api.model.v2.ErrorCode; +import com.alibaba.nacos.api.model.v2.Result; +import com.alibaba.nacos.auth.annotation.Secured; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.console.model.Namespace; +import com.alibaba.nacos.console.model.NamespaceAllInfo; +import com.alibaba.nacos.console.model.vo.NamespaceVo; +import com.alibaba.nacos.console.service.NamespaceOperationService; +import com.alibaba.nacos.plugin.auth.constant.ActionTypes; +import com.alibaba.nacos.plugin.auth.impl.constant.AuthConstants; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.UUID; +import java.util.regex.Pattern; + +/** + * NamespaceControllerV2. + * @author dongyafei + * @date 2022/8/16 + */ +@NacosApi +@RestController +@RequestMapping(path = "/v2/console/namespace") +public class NamespaceControllerV2 { + + private final NamespaceOperationService namespaceOperationService; + + public NamespaceControllerV2(NamespaceOperationService namespaceOperationService) { + this.namespaceOperationService = namespaceOperationService; + } + + private final Pattern namespaceIdCheckPattern = Pattern.compile("^[\\w-]+"); + + private static final int NAMESPACE_ID_MAX_LENGTH = 128; + + /** + * Get namespace list. + * + * @return namespace list + */ + @GetMapping("/list") + public Result> getNamespaceList() { + return Result.success(namespaceOperationService.getNamespaceList()); + } + + /** + * get namespace all info by namespace id. + * + * @param namespaceId namespaceId + * @return namespace all info + */ + @GetMapping() + public Result getNamespace(@RequestParam("namespaceId") String namespaceId) + throws NacosException { + return Result.success(namespaceOperationService.getNamespace(namespaceId, true)); + } + + /** + * create namespace. + * + * @param namespaceVo namespaceVo. + * @return whether create ok + */ + @PostMapping + @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE) + public Result createNamespace(NamespaceVo namespaceVo) throws NacosException { + + namespaceVo.validate(); + + String namespaceId = namespaceVo.getNamespaceId(); + String namespaceName = namespaceVo.getNamespaceName(); + String namespaceDesc = namespaceVo.getNamespaceDesc(); + + if (StringUtils.isBlank(namespaceId)) { + namespaceId = UUID.randomUUID().toString(); + } else { + namespaceId = namespaceId.trim(); + if (!namespaceIdCheckPattern.matcher(namespaceId).matches()) { + throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.ILLEGAL_NAMESPACE, + "namespaceId [" + namespaceId + "] mismatch the pattern"); + } + if (namespaceId.length() > NAMESPACE_ID_MAX_LENGTH) { + throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.ILLEGAL_NAMESPACE, + "too long namespaceId, over " + NAMESPACE_ID_MAX_LENGTH); + } + } + return Result.success(namespaceOperationService.createNamespace(namespaceId, namespaceName, namespaceDesc, true)); + } + + /** + * edit namespace. + * + * @param namespaceVo namespace params + * @return whether edit ok + */ + @PutMapping + @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE) + public Result editNamespace(NamespaceVo namespaceVo) throws NacosException { + namespaceVo.validate(); + return Result.success(namespaceOperationService.editNamespace(namespaceVo.getNamespaceId(), + namespaceVo.getNamespaceName(), namespaceVo.getNamespaceDesc())); + } + + /** + * delete namespace by id. + * + * @param namespaceId namespace ID + * @return whether delete ok + */ + @DeleteMapping + @Secured(resource = AuthConstants.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE) + public Result deleteNamespace(@RequestParam("namespaceId") String namespaceId) { + return Result.success(namespaceOperationService.removeNamespace(namespaceId)); + } +} diff --git a/console/src/main/java/com/alibaba/nacos/console/model/vo/NamespaceVo.java b/console/src/main/java/com/alibaba/nacos/console/model/vo/NamespaceVo.java new file mode 100644 index 000000000..d3ebbfd2f --- /dev/null +++ b/console/src/main/java/com/alibaba/nacos/console/model/vo/NamespaceVo.java @@ -0,0 +1,111 @@ +/* + * Copyright 1999-2022 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.console.model.vo; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.exception.api.NacosApiException; +import com.alibaba.nacos.api.model.v2.ErrorCode; +import org.springframework.http.HttpStatus; + +import java.io.Serializable; +import java.util.Objects; + +/** + * NamespaceVo. + * @author dongyafei + * @date 2022/8/16 + */ +public class NamespaceVo implements Serializable { + + private static final long serialVersionUID = -1078976569495343487L; + + private String namespaceId; + + private String namespaceName; + + private String namespaceDesc; + + public NamespaceVo() { + } + + public NamespaceVo(String namespaceId, String namespaceName, String namespaceDesc) { + this.namespaceId = namespaceId; + this.namespaceName = namespaceName; + this.namespaceDesc = namespaceDesc; + } + + public String getNamespaceId() { + return namespaceId; + } + + public void setNamespaceId(String namespaceId) { + this.namespaceId = namespaceId; + } + + public String getNamespaceName() { + return namespaceName; + } + + public void setNamespaceName(String namespaceName) { + this.namespaceName = namespaceName; + } + + public String getNamespaceDesc() { + return namespaceDesc; + } + + public void setNamespaceDesc(String namespaceDesc) { + this.namespaceDesc = namespaceDesc; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + NamespaceVo that = (NamespaceVo) o; + return Objects.equals(namespaceId, that.namespaceId) && Objects.equals(namespaceName, that.namespaceName) + && Objects.equals(namespaceDesc, that.namespaceDesc); + } + + @Override + public int hashCode() { + return Objects.hash(namespaceId, namespaceName, namespaceDesc); + } + + @Override + public String toString() { + return "NamespaceVo{" + "namespaceId='" + namespaceId + '\'' + ", namespaceName='" + namespaceName + '\'' + + ", namespaceDesc='" + namespaceDesc + '\'' + '}'; + } + + /** + * check required param. + * @throws NacosException NacosException + */ + public void validate() throws NacosException { + if (null == namespaceId) { + throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING, "required parameter 'namespaceId' is missing"); + } + if (null == namespaceName) { + throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING, "required parameter 'namespaceName' is missing"); + } + } +} diff --git a/console/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java b/console/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java new file mode 100644 index 000000000..375f394ba --- /dev/null +++ b/console/src/main/java/com/alibaba/nacos/console/service/NamespaceOperationService.java @@ -0,0 +1,149 @@ +/* + * Copyright 1999-2022 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.console.service; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.exception.api.NacosApiException; +import com.alibaba.nacos.api.model.v2.ErrorCode; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.config.server.model.TenantInfo; +import com.alibaba.nacos.config.server.service.repository.PersistService; +import com.alibaba.nacos.console.enums.NamespaceTypeEnum; +import com.alibaba.nacos.console.model.Namespace; +import com.alibaba.nacos.console.model.NamespaceAllInfo; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * NamespaceOperationService. + * + * @author dongyafei + * @date 2022/8/16 + */ + +@Service +public class NamespaceOperationService { + + private final PersistService persistService; + + private static final String DEFAULT_NAMESPACE = "public"; + + private static final String DEFAULT_NAMESPACE_SHOW_NAME = "Public"; + + private static final String DEFAULT_NAMESPACE_DESCRIPTION = "Public Namespace"; + + private static final int DEFAULT_QUOTA = 200; + + private static final String DEFAULT_CREATE_SOURCE = "nacos"; + + private static final String DEFAULT_TENANT = ""; + + private static final String DEFAULT_KP = "1"; + + public NamespaceOperationService(PersistService persistService) { + this.persistService = persistService; + } + + public List getNamespaceList() { + // TODO 获取用kp + List tenantInfos = persistService.findTenantByKp(DEFAULT_KP); + + Namespace namespace0 = new Namespace("", DEFAULT_NAMESPACE, DEFAULT_QUOTA, + persistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType()); + List namespaceList = new ArrayList<>(); + namespaceList.add(namespace0); + + for (TenantInfo tenantInfo : tenantInfos) { + int configCount = persistService.configInfoCount(tenantInfo.getTenantId()); + Namespace namespaceTmp = new Namespace(tenantInfo.getTenantId(), tenantInfo.getTenantName(), + tenantInfo.getTenantDesc(), DEFAULT_QUOTA, configCount, NamespaceTypeEnum.CUSTOM.getType()); + namespaceList.add(namespaceTmp); + } + return namespaceList; + } + + /** + * query namespace by namespace id. + * + * @param namespaceId namespace Id. + * @return NamespaceAllInfo. + */ + public NamespaceAllInfo getNamespace(String namespaceId, Boolean isV2) throws NacosException { + // TODO 获取用kp + if (StringUtils.isBlank(namespaceId)) { + return new NamespaceAllInfo(namespaceId, DEFAULT_NAMESPACE_SHOW_NAME, DEFAULT_QUOTA, + persistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType(), + DEFAULT_NAMESPACE_DESCRIPTION); + } else { + TenantInfo tenantInfo = persistService.findTenantByKp(DEFAULT_KP, namespaceId); + if (isV2 && null == tenantInfo) { + throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.NAMESPACE_NOT_EXIST, + "namespaceId [ " + namespaceId + " ] not exist"); + } + int configCount = persistService.configInfoCount(namespaceId); + return new NamespaceAllInfo(namespaceId, tenantInfo.getTenantName(), DEFAULT_QUOTA, configCount, + NamespaceTypeEnum.CUSTOM.getType(), tenantInfo.getTenantDesc()); + } + } + + /** + * create namespace. + * + * @param namespaceId namespace ID + * @param namespaceName namespace Name + * @param namespaceDesc namespace Desc + * @param isV2 whether api v2 + * @return whether create ok + */ + public Boolean createNamespace(String namespaceId, String namespaceName, String namespaceDesc, Boolean isV2) + throws NacosException { + // TODO 获取用kp + if (persistService.tenantInfoCountByTenantId(namespaceId) > 0) { + if (isV2) { + throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.NAMESPACE_ALREADY_EXIST, + "namespaceId [" + namespaceId + "] already exist"); + } else { + return false; + } + } + + persistService + .insertTenantInfoAtomic(DEFAULT_KP, namespaceId, namespaceName, namespaceDesc, DEFAULT_CREATE_SOURCE, + System.currentTimeMillis()); + return true; + } + + /** + * edit namespace. + */ + public Boolean editNamespace(String namespaceId, String namespaceName, String namespaceDesc) { + // TODO 获取用kp + persistService.updateTenantNameAtomic(DEFAULT_KP, namespaceId, namespaceName, namespaceDesc); + return true; + } + + /** + * remove namespace. + */ + public Boolean removeNamespace(String namespaceId) { + persistService.removeTenantInfoAtomic(DEFAULT_KP, namespaceId); + return true; + } +} diff --git a/console/src/test/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2Test.java b/console/src/test/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2Test.java new file mode 100644 index 000000000..10a5e3731 --- /dev/null +++ b/console/src/test/java/com/alibaba/nacos/console/controller/v2/NamespaceControllerV2Test.java @@ -0,0 +1,137 @@ +/* + * Copyright 1999-2022 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.console.controller.v2; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.model.v2.ErrorCode; +import com.alibaba.nacos.api.model.v2.Result; +import com.alibaba.nacos.console.enums.NamespaceTypeEnum; +import com.alibaba.nacos.console.model.Namespace; +import com.alibaba.nacos.console.model.NamespaceAllInfo; +import com.alibaba.nacos.console.model.vo.NamespaceVo; +import com.alibaba.nacos.console.service.NamespaceOperationService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * NamespaceControllerV2Test. + * @author dongyafei + * @date 2022/8/16 + */ +@RunWith(MockitoJUnitRunner.class) +public class NamespaceControllerV2Test { + + private NamespaceControllerV2 namespaceControllerV2; + + @Mock + private NamespaceOperationService namespaceOperationService; + + private static final String TEST_NAMESPACE_ID = "testId"; + + private static final String TEST_NAMESPACE_NAME = "testName"; + + private static final String TEST_NAMESPACE_DESC = "testDesc"; + + @Before + public void setUp() throws Exception { + namespaceControllerV2 = new NamespaceControllerV2(namespaceOperationService); + } + + @Test + public void testGetNamespaceList() { + Namespace namespace = new Namespace(); + namespace.setNamespace(TEST_NAMESPACE_ID); + namespace.setNamespaceShowName(TEST_NAMESPACE_NAME); + namespace.setNamespaceDesc(TEST_NAMESPACE_DESC); + List namespaceList = Collections.singletonList(namespace); + when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList); + + Result> actualResult = namespaceControllerV2.getNamespaceList(); + verify(namespaceOperationService).getNamespaceList(); + assertEquals(ErrorCode.SUCCESS.getCode(), actualResult.getCode()); + + List actualList = actualResult.getData(); + Namespace actualNamespace = actualList.get(0); + assertEquals(namespaceList.size(), actualList.size()); + assertEquals(namespace.getNamespace(), actualNamespace.getNamespace()); + assertEquals(namespace.getNamespaceShowName(), actualNamespace.getNamespaceShowName()); + assertEquals(namespace.getNamespaceDesc(), actualNamespace.getNamespaceDesc()); + + } + + @Test + public void testGetNamespace() throws NacosException { + NamespaceAllInfo namespaceAllInfo = new NamespaceAllInfo(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, 200, + 1, NamespaceTypeEnum.GLOBAL.getType(), TEST_NAMESPACE_DESC); + when(namespaceOperationService.getNamespace(TEST_NAMESPACE_ID, true)).thenReturn(namespaceAllInfo); + Result result = namespaceControllerV2.getNamespace(TEST_NAMESPACE_ID); + verify(namespaceOperationService).getNamespace(TEST_NAMESPACE_ID, true); + assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode()); + NamespaceAllInfo namespace = result.getData(); + assertEquals(namespaceAllInfo.getNamespace(), namespace.getNamespace()); + assertEquals(namespaceAllInfo.getNamespaceShowName(), namespace.getNamespaceShowName()); + assertEquals(namespaceAllInfo.getNamespaceDesc(), namespace.getNamespaceDesc()); + assertEquals(namespaceAllInfo.getQuota(), namespace.getQuota()); + assertEquals(namespaceAllInfo.getConfigCount(), namespace.getConfigCount()); + } + + @Test + public void testCreateNamespace() throws NacosException { + when(namespaceOperationService + .createNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC, true)).thenReturn(true); + Result result = namespaceControllerV2 + .createNamespace(new NamespaceVo(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC)); + + verify(namespaceOperationService).createNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC, true); + + assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode()); + assertEquals(true, result.getData()); + } + + @Test + public void testEditNamespace() throws NacosException { + when(namespaceOperationService.editNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC)).thenReturn(true); + Result result = namespaceControllerV2 + .editNamespace(new NamespaceVo(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC)); + + verify(namespaceOperationService).editNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC); + + assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode()); + assertEquals(true, result.getData()); + } + + @Test + public void testDeleteNamespace() { + when(namespaceOperationService.removeNamespace(TEST_NAMESPACE_ID)).thenReturn(true); + Result result = namespaceControllerV2.deleteNamespace(TEST_NAMESPACE_ID); + + verify(namespaceOperationService).removeNamespace(TEST_NAMESPACE_ID); + + assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode()); + assertEquals(true, result.getData()); + } +} diff --git a/console/src/test/java/com/alibaba/nacos/console/service/NamespaceOperationServiceTest.java b/console/src/test/java/com/alibaba/nacos/console/service/NamespaceOperationServiceTest.java new file mode 100644 index 000000000..802a5b409 --- /dev/null +++ b/console/src/test/java/com/alibaba/nacos/console/service/NamespaceOperationServiceTest.java @@ -0,0 +1,139 @@ +/* + * Copyright 1999-2022 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.console.service; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.exception.api.NacosApiException; +import com.alibaba.nacos.config.server.model.TenantInfo; +import com.alibaba.nacos.config.server.service.repository.PersistService; +import com.alibaba.nacos.console.enums.NamespaceTypeEnum; +import com.alibaba.nacos.console.model.Namespace; +import com.alibaba.nacos.console.model.NamespaceAllInfo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * NamespaceOperationServiceTest. + * @author dongyafei + * @date 2022/8/16 + */ +@RunWith(MockitoJUnitRunner.class) +public class NamespaceOperationServiceTest { + + private NamespaceOperationService namespaceOperationService; + + @Mock + private PersistService persistService; + + private static final String TEST_NAMESPACE_ID = "testId"; + + private static final String TEST_NAMESPACE_NAME = "testName"; + + private static final String TEST_NAMESPACE_DESC = "testDesc"; + + private static final String DEFAULT_NAMESPACE = "public"; + + private static final int DEFAULT_QUOTA = 200; + + private static final String DEFAULT_KP = "1"; + + @Before + public void setUp() throws Exception { + namespaceOperationService = new NamespaceOperationService(persistService); + } + + @Test + public void testGetNamespaceList() { + TenantInfo tenantInfo = new TenantInfo(); + tenantInfo.setTenantId(TEST_NAMESPACE_ID); + tenantInfo.setTenantName(TEST_NAMESPACE_NAME); + tenantInfo.setTenantDesc(TEST_NAMESPACE_DESC); + when(persistService.findTenantByKp(DEFAULT_KP)).thenReturn(Collections.singletonList(tenantInfo)); + when(persistService.configInfoCount(anyString())).thenReturn(1); + + List list = namespaceOperationService.getNamespaceList(); + assertEquals(2, list.size()); + Namespace namespaceA = list.get(0); + assertEquals("", namespaceA.getNamespace()); + assertEquals(DEFAULT_NAMESPACE, namespaceA.getNamespaceShowName()); + assertEquals(DEFAULT_QUOTA, namespaceA.getQuota()); + assertEquals(1, namespaceA.getConfigCount()); + + Namespace namespaceB = list.get(1); + assertEquals(TEST_NAMESPACE_ID, namespaceB.getNamespace()); + assertEquals(TEST_NAMESPACE_NAME, namespaceB.getNamespaceShowName()); + assertEquals(1, namespaceB.getConfigCount()); + } + + @Test(expected = NacosApiException.class) + public void testGetNamespace() throws NacosException { + + TenantInfo tenantInfo = new TenantInfo(); + tenantInfo.setTenantId(TEST_NAMESPACE_ID); + tenantInfo.setTenantName(TEST_NAMESPACE_NAME); + tenantInfo.setTenantDesc(TEST_NAMESPACE_DESC); + when(persistService.findTenantByKp(DEFAULT_KP, TEST_NAMESPACE_ID)).thenReturn(tenantInfo); + when(persistService.findTenantByKp(DEFAULT_KP, "test_not_exist_id")).thenReturn(null); + when(persistService.configInfoCount(anyString())).thenReturn(1); + NamespaceAllInfo namespaceAllInfo = new NamespaceAllInfo(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, DEFAULT_QUOTA, + 1, NamespaceTypeEnum.GLOBAL.getType(), TEST_NAMESPACE_DESC); + NamespaceAllInfo namespace = namespaceOperationService.getNamespace(TEST_NAMESPACE_ID, true); + assertEquals(namespaceAllInfo.getNamespace(), namespace.getNamespace()); + assertEquals(namespaceAllInfo.getNamespaceShowName(), namespace.getNamespaceShowName()); + assertEquals(namespaceAllInfo.getNamespaceDesc(), namespace.getNamespaceDesc()); + assertEquals(namespaceAllInfo.getQuota(), namespace.getQuota()); + assertEquals(namespaceAllInfo.getConfigCount(), namespace.getConfigCount()); + + namespaceOperationService.getNamespace("test_not_exist_id", true); + + } + + @Test + public void testCreateNamespace() throws NacosException { + when(persistService.tenantInfoCountByTenantId(anyString())).thenReturn(0); + namespaceOperationService.createNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC, true); + verify(persistService) + .insertTenantInfoAtomic(eq(DEFAULT_KP), eq(TEST_NAMESPACE_ID), eq(TEST_NAMESPACE_NAME), eq(TEST_NAMESPACE_DESC), + any(), anyLong()); + } + + @Test + public void testEditNamespace() { + namespaceOperationService.editNamespace(TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC); + verify(persistService).updateTenantNameAtomic(DEFAULT_KP, TEST_NAMESPACE_ID, TEST_NAMESPACE_NAME, TEST_NAMESPACE_DESC); + } + + @Test + public void testRemoveNamespace() { + namespaceOperationService.removeNamespace(TEST_NAMESPACE_ID); + verify(persistService).removeTenantInfoAtomic(DEFAULT_KP, TEST_NAMESPACE_ID); + } +}