Skip to content

Commit

Permalink
[ISSUE #12017] Add the console backend API for new section (#12553)
Browse files Browse the repository at this point in the history
* [ISSUE #12017] Add the console backend API for config section

* Add history handling module

* [ISSUE #12017] Add the console backend API for naming section

* Add service handling module

* Add instance handling module

* [ISSUE #12017] Add the console backend API for auth section

* Add user handling module

* Add role handling module

* Add permission handling module

* [ISSUE #12017] Add the console backend API for core section

* Add cluster handling module

* [ISSUE #12017] Fix the error by adding ApiType

* Fix the error by adding ApiType

* Revert "[ISSUE #12017] Add the console backend API for auth section"

This reverts commit 052112a.

* [ISSUE #12017] Updated ControllerV3 for auth section

* Updated ControllerV3 for auth section

* [ISSUE #12017] Fix errors

* Add ApiType annotation

* Transfer the updateCluster method

* Fix Compilation Errors
  • Loading branch information
RickonZhang0929 authored Sep 4, 2024
1 parent 59858d1 commit f1b00a3
Show file tree
Hide file tree
Showing 19 changed files with 2,454 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Copyright 1999-2024 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.v3.config;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.model.v2.Result;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.enums.ApiType;
import com.alibaba.nacos.common.utils.NamespaceUtil;
import com.alibaba.nacos.common.utils.StringUtils;
import com.alibaba.nacos.config.server.model.ConfigHistoryInfo;
import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
import com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;
import com.alibaba.nacos.config.server.utils.ParamUtils;
import com.alibaba.nacos.console.proxy.config.HistoryProxy;
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
import com.alibaba.nacos.persistence.model.Page;
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
import com.alibaba.nacos.plugin.auth.constant.SignType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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;

/**
* Controller for handling HTTP requests related to history operations.
*
* @author zhangyukun on:2024/8/16
*/
@RestController
@RequestMapping("/v3/console/cs/history")
@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)
public class ConsoleHistoryController {

private final HistoryProxy historyProxy;

@Autowired
public ConsoleHistoryController(HistoryProxy historyProxy) {
this.historyProxy = historyProxy;
}

/**
* Query the detailed configuration history information. notes:
*
* @param nid history_config_info nid
* @param dataId dataId
* @param group groupId
* @param namespaceId namespaceId
* @return history config info
*/
@GetMapping
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)
public Result<ConfigHistoryInfo> getConfigHistoryInfo(@RequestParam("dataId") String dataId,
@RequestParam("group") String group,
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
@RequestParam("nid") Long nid) throws NacosException {
// check namespaceId
ParamUtils.checkTenantV2(namespaceId);
namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);
// check params
ParamUtils.checkParam(dataId, group, "datumId", "content");

return Result.success(historyProxy.getConfigHistoryInfo(dataId, group, namespaceId, nid));
}

/**
* Query the list history config. notes:
*
* @param dataId dataId string value [required].
* @param group group string value [required].
* @param namespaceId namespaceId.
* @param pageNo pageNo integer value.
* @param pageSize pageSize integer value.
* @return the page of history config.
*/
@GetMapping("/list")
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)
public Result<Page<ConfigHistoryInfo>> listConfigHistory(@RequestParam("dataId") String dataId,
@RequestParam("group") String group,
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", required = false, defaultValue = "100") Integer pageSize)
throws NacosException {
pageSize = Math.min(500, pageSize);
// check namespaceId
ParamUtils.checkTenantV2(namespaceId);
namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);
// check params
ParamUtils.checkParam(dataId, group, "datumId", "content");

return Result.success(historyProxy.listConfigHistory(dataId, group, namespaceId, pageNo, pageSize));
}

/**
* Query previous config history information. notes:
*
* @param id config_info id
* @param dataId dataId
* @param group groupId
* @param namespaceId namespaceId
* @return history config info
*/
@GetMapping(value = "/previous")
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)
public Result<ConfigHistoryInfo> getPreviousConfigHistoryInfo(@RequestParam("dataId") String dataId,
@RequestParam("group") String group,
@RequestParam(value = "namespaceId", required = false, defaultValue = StringUtils.EMPTY) String namespaceId,
@RequestParam("id") Long id) throws NacosException {
// check namespaceId
ParamUtils.checkTenantV2(namespaceId);
namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);
// check params
ParamUtils.checkParam(dataId, group, "datumId", "content");

return Result.success(historyProxy.getPreviousConfigHistoryInfo(dataId, group, namespaceId, id));
}

/**
* Query configs list by namespace.
*
* @param namespaceId config_info namespace
* @return list
*/
@GetMapping(value = "/configs")
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)
public Result<List<ConfigInfoWrapper>> getConfigsByTenant(@RequestParam("namespaceId") String namespaceId)
throws NacosException {
// check namespaceId
ParamUtils.checkTenantV2(namespaceId);
namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);

return Result.success(historyProxy.getConfigsByTenant(namespaceId));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 1999-2024 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.v3.core;

import com.alibaba.nacos.api.model.v2.Result;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;
import com.alibaba.nacos.console.proxy.core.ClusterProxy;
import com.alibaba.nacos.core.cluster.Member;
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
import com.alibaba.nacos.core.utils.Commons;
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
import com.alibaba.nacos.plugin.auth.constant.SignType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;

/**
* Controller for handling HTTP requests related to cluster operations.
*
* @author zhangyukun on:2024/8/16
*/
@RestController
@RequestMapping("/v3/console/core/cluster")
@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)
public class ConsoleClusterController {

private final ClusterProxy clusterProxy;

/**
* Constructs a new ConsoleClusterController with the provided ClusterProxy.
*
* @param clusterProxy the proxy used for handling cluster-related operations
*/
public ConsoleClusterController(ClusterProxy clusterProxy) {
this.clusterProxy = clusterProxy;
}

/**
* The console displays the list of cluster members.
*
* @param ipKeyWord search keyWord
* @return all members
*/
@GetMapping(value = "/nodes")
@Secured(resource = Commons.NACOS_CORE_CONTEXT + "/cluster", action = ActionTypes.READ, signType = SignType.CONSOLE)
public Result<Collection<Member>> getNodeList(@RequestParam(value = "keyword", required = false) String ipKeyWord) {
Collection<Member> result = clusterProxy.getNodeList(ipKeyWord);
return Result.success(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright 1999-2024 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.v3.naming;

import com.alibaba.nacos.api.common.Constants;
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.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.builder.InstanceBuilder;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.auth.annotation.Secured;
import com.alibaba.nacos.auth.enums.ApiType;
import com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;
import com.alibaba.nacos.console.proxy.naming.InstanceProxy;
import com.alibaba.nacos.core.control.TpsControl;
import com.alibaba.nacos.core.paramcheck.ExtractorManager;
import com.alibaba.nacos.naming.misc.SwitchDomain;
import com.alibaba.nacos.naming.misc.UtilsAndCommons;
import com.alibaba.nacos.naming.model.form.InstanceForm;
import com.alibaba.nacos.naming.web.CanDistro;
import com.alibaba.nacos.plugin.auth.constant.ActionTypes;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.http.HttpStatus;
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;

/**
* Controller for handling HTTP requests related to instance operations.
*
* @author zhangyukun on:2024/8/16
*/
@RestController
@RequestMapping("/v3/console/ns/instance")
@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)
public class ConsoleInstanceController {

private final SwitchDomain switchDomain;

private final InstanceProxy instanceProxy;

/**
* Constructs a new ConsoleInstanceController with the provided InstanceProxy.
*
* @param instanceProxy the proxy used for handling instance-related operations
*/
public ConsoleInstanceController(InstanceProxy instanceProxy, SwitchDomain switchDomain) {
this.instanceProxy = instanceProxy;
this.switchDomain = switchDomain;
}

/**
* List instances of special service.
*
* @param namespaceId namespace id
* @param serviceName service name
* @param healthyOnly instance health only
* @param enabledOnly instance enabled
* @param page number of page
* @param pageSize size of each page
* @return instances information
*/
@Secured(action = ActionTypes.READ, apiType = ApiType.CONSOLE_API)
@RequestMapping("/list")
public Result<ObjectNode> getInstanceList(
@RequestParam(defaultValue = Constants.DEFAULT_NAMESPACE_ID) String namespaceId,
@RequestParam String serviceName, @RequestParam(required = false) Boolean healthyOnly,
@RequestParam(required = false) Boolean enabledOnly, @RequestParam(name = "pageNo") int page,
@RequestParam int pageSize) {
String serviceNameWithoutGroup = NamingUtils.getServiceName(serviceName);
String groupName = NamingUtils.getGroupName(serviceName);
ObjectNode result = instanceProxy.listInstances(namespaceId, serviceNameWithoutGroup, groupName, page, pageSize, healthyOnly, enabledOnly);
return Result.success(result);
}

/**
* Update instance.
*/
@CanDistro
@PutMapping
@TpsControl(pointName = "NamingInstanceUpdate", name = "HttpNamingInstanceUpdate")
@Secured(action = ActionTypes.WRITE, apiType = ApiType.CONSOLE_API)
public Result<String> updateInstance(InstanceForm instanceForm) throws NacosException {
// check param
instanceForm.validate();
checkWeight(instanceForm.getWeight());
// build instance
Instance instance = buildInstance(instanceForm);
instanceProxy.updateInstance(instanceForm, instance);
return Result.success("ok");
}

private void checkWeight(Double weight) throws NacosException {
if (weight > com.alibaba.nacos.naming.constants.Constants.MAX_WEIGHT_VALUE
|| weight < com.alibaba.nacos.naming.constants.Constants.MIN_WEIGHT_VALUE) {
throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.WEIGHT_ERROR,
"instance format invalid: The weights range from "
+ com.alibaba.nacos.naming.constants.Constants.MIN_WEIGHT_VALUE + " to "
+ com.alibaba.nacos.naming.constants.Constants.MAX_WEIGHT_VALUE);
}
}

private Instance buildInstance(InstanceForm instanceForm) throws NacosException {
Instance instance = InstanceBuilder.newBuilder().setServiceName(buildCompositeServiceName(instanceForm))
.setIp(instanceForm.getIp()).setClusterName(instanceForm.getClusterName())
.setPort(instanceForm.getPort()).setHealthy(instanceForm.getHealthy())
.setWeight(instanceForm.getWeight()).setEnabled(instanceForm.getEnabled())
.setMetadata(UtilsAndCommons.parseMetadata(instanceForm.getMetadata()))
.setEphemeral(instanceForm.getEphemeral()).build();
if (instanceForm.getEphemeral() == null) {
instance.setEphemeral((switchDomain.isDefaultInstanceEphemeral()));
}
return instance;
}

private String buildCompositeServiceName(InstanceForm instanceForm) {
return NamingUtils.getGroupedName(instanceForm.getServiceName(), instanceForm.getGroupName());
}
}
Loading

0 comments on commit f1b00a3

Please sign in to comment.