diff --git a/src/main/java/com/educoder/bridge/game/service/K8sService.java b/src/main/java/com/educoder/bridge/game/service/K8sService.java index 34609f2..daec216 100644 --- a/src/main/java/com/educoder/bridge/game/service/K8sService.java +++ b/src/main/java/com/educoder/bridge/game/service/K8sService.java @@ -18,12 +18,13 @@ import com.educoder.bridge.common.settings.AppConfig; import com.educoder.bridge.common.utils.BeanFactory; import com.educoder.bridge.common.utils.ConstantUtil; import com.educoder.bridge.common.utils.ShellUtil; -import com.educoder.bridge.common.utils.ThreadPoolUtil; import com.educoder.bridge.common.utils.TpUtils; import com.educoder.bridge.game.model.PodCreateStrategy; +import com.educoder.bridge.k8s.model.NodeQueryParam; import com.spotify.docker.client.exceptions.DockerException; import io.fabric8.kubernetes.api.model.Container; +import io.fabric8.kubernetes.api.model.DoneableNode; import io.fabric8.kubernetes.api.model.DoneablePod; import io.fabric8.kubernetes.api.model.HostPathVolumeSource; import io.fabric8.kubernetes.api.model.Node; @@ -46,6 +47,7 @@ import io.fabric8.kubernetes.client.Watcher; import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable; import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; import io.fabric8.kubernetes.client.dsl.PodResource; +import io.fabric8.kubernetes.client.dsl.Resource; @Service("K8sService") public class K8sService { private static final Logger logger = LoggerFactory.getLogger(K8sService.class); @@ -85,6 +87,32 @@ public class K8sService { } return addressList; } + + /** + * 获取k8s集群中Node列表 + * + * @return + */ + public List getNodes(NodeQueryParam param) { + NonNamespaceOperation> operation = client.nodes(); + if (param != null) { + if (param.getName() != null) { + Node node = operation.withName(param.getName()).get(); + if (node == null) { + return Collections.emptyList(); + } else { + return Arrays.asList(node); + } + } else if (param.getLabels() != null) { + return operation.withLabels(param.getLabels()).list().getItems(); + } else { + return Collections.emptyList(); + } + } else { + return operation.list().getItems(); + } + + } /** * 获取某个节点上的Pod数量 diff --git a/src/main/java/com/educoder/bridge/k8s/controller/NodeController.java b/src/main/java/com/educoder/bridge/k8s/controller/NodeController.java new file mode 100644 index 0000000..98a78c9 --- /dev/null +++ b/src/main/java/com/educoder/bridge/k8s/controller/NodeController.java @@ -0,0 +1,76 @@ +package com.educoder.bridge.k8s.controller; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import com.educoder.bridge.common.constant.ApiResultCodeCsts; +import com.educoder.bridge.common.model.ApiResult; +import com.educoder.bridge.game.service.K8sService; +import com.educoder.bridge.k8s.model.NodeQueryParam; + +import io.fabric8.kubernetes.api.model.Node; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * Node相关的接口 + * + * @author jiangzhongxiang + */ +@Api(value = "Node", hidden = true) +@RestController +@RequestMapping("/nodes") +public class NodeController { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private K8sService k8sService; + + /** + * 获取Node列表 + */ + @RequestMapping(path = "", method = RequestMethod.GET) + @ApiOperation(value = "获取Node列表", httpMethod = "GET", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public ApiResult> getNodes() throws Exception { + logger.info("获取Node列表"); + + ApiResult> result = new ApiResult<>(); + + NodeQueryParam param = new NodeQueryParam(); + List nodeList = k8sService.getNodes(param); + + result.setData(nodeList); + return result; + } + + + /** + * 获取Node列表 + */ + @RequestMapping(path = "/{name}", method = RequestMethod.GET) + @ApiOperation(value = "获取Node详情", httpMethod = "GET", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public ApiResult getNode(@PathVariable("name") String name) throws Exception { + logger.info("获取Node列表"); + + ApiResult result = new ApiResult<>(); + + NodeQueryParam param = new NodeQueryParam(); + param.setName(name); + List nodeList = k8sService.getNodes(param); + if(nodeList != null && nodeList.size() > 0) { + result.setData(nodeList.get(0)); + } else { + result.setCode(ApiResultCodeCsts.FAIL); + } + return result; + } + +} diff --git a/src/main/java/com/educoder/bridge/k8s/controller/PodController.java b/src/main/java/com/educoder/bridge/k8s/controller/PodController.java new file mode 100644 index 0000000..2d5e9e3 --- /dev/null +++ b/src/main/java/com/educoder/bridge/k8s/controller/PodController.java @@ -0,0 +1,71 @@ +package com.educoder.bridge.k8s.controller; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import com.educoder.bridge.common.constant.ApiResultCodeCsts; +import com.educoder.bridge.common.model.ApiResult; +import com.educoder.bridge.game.service.K8sService; +import com.educoder.bridge.k8s.model.NodeQueryParam; + +import io.fabric8.kubernetes.api.model.Node; +import io.fabric8.kubernetes.api.model.Pod; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * Pod相关的接口 + * + * @author jiangzhongxiang + */ +@Api(value = "Pod", hidden = true) +@RestController +@RequestMapping("/pods") +public class PodController { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private K8sService k8sService; + + /** + * 获取Node列表 + */ + @RequestMapping(path = "", method = RequestMethod.GET) + @ApiOperation(value = "获取Pod列表", httpMethod = "GET", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public ApiResult> getPods() throws Exception { + logger.info("获取Node列表"); + + ApiResult> result = new ApiResult<>(); + + + return result; + } + + /** + * 获取Pod详情 + */ + @RequestMapping(path = "/{name}", method = RequestMethod.GET) + @ApiOperation(value = "获取Pod详情", httpMethod = "GET", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public ApiResult getPod(@PathVariable("name") String name) throws Exception { + logger.info("获取Pod {} 详情", name); + + ApiResult result = new ApiResult<>(); + + Pod pod = k8sService.getPod(name); + if (pod != null) { + result.setData(pod); + } else { + result.setCode(ApiResultCodeCsts.FAIL); + } + return result; + } + +} diff --git a/src/main/java/com/educoder/bridge/k8s/model/BridgePod.java b/src/main/java/com/educoder/bridge/k8s/model/BridgePod.java new file mode 100644 index 0000000..f6eae41 --- /dev/null +++ b/src/main/java/com/educoder/bridge/k8s/model/BridgePod.java @@ -0,0 +1,84 @@ +package com.educoder.bridge.k8s.model; + +import java.time.LocalDateTime; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "bridge pod 信息", description = "bridge pod 信息") +public class BridgePod { + + @ApiModelProperty(value = "pod name") + private String name; + @ApiModelProperty(value = "实训id") + private String tpiID; + + @ApiModelProperty(value = "评测请求到达时间") + private LocalDateTime requestTime; + @ApiModelProperty(value = "k8s创建pod时间") + private LocalDateTime k8sCreateTime; + @ApiModelProperty(value = "删除时间") + private LocalDateTime deleteTime; + + @ApiModelProperty(value = "pod所在node名称") + private String nodeName; + @ApiModelProperty(value = "pod所在node ip") + private String nodeIp; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTpiID() { + return tpiID; + } + + public void setTpiID(String tpiID) { + this.tpiID = tpiID; + } + + public LocalDateTime getRequestTime() { + return requestTime; + } + + public void setRequestTime(LocalDateTime requestTime) { + this.requestTime = requestTime; + } + + public LocalDateTime getK8sCreateTime() { + return k8sCreateTime; + } + + public void setK8sCreateTime(LocalDateTime k8sCreateTime) { + this.k8sCreateTime = k8sCreateTime; + } + + public LocalDateTime getDeleteTime() { + return deleteTime; + } + + public void setDeleteTime(LocalDateTime deleteTime) { + this.deleteTime = deleteTime; + } + + public String getNodeName() { + return nodeName; + } + + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + public String getNodeIp() { + return nodeIp; + } + + public void setNodeIp(String nodeIp) { + this.nodeIp = nodeIp; + } + +} diff --git a/src/main/java/com/educoder/bridge/k8s/model/NodeQueryParam.java b/src/main/java/com/educoder/bridge/k8s/model/NodeQueryParam.java new file mode 100644 index 0000000..cb22be7 --- /dev/null +++ b/src/main/java/com/educoder/bridge/k8s/model/NodeQueryParam.java @@ -0,0 +1,26 @@ +package com.educoder.bridge.k8s.model; + +import java.util.Map; + +public class NodeQueryParam { + + private String name; + private Map labels; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map getLabels() { + return labels; + } + + public void setLabels(Map labels) { + this.labels = labels; + } + +}