Skip to content

Commit

Permalink
Merge pull request #10470 from sawyersong2/issue10122_github_branch
Browse files Browse the repository at this point in the history
feat:整合微拓展资源调度能力 #10122
  • Loading branch information
bkci-bot authored Jun 18, 2024
2 parents 4cf6dc8 + 582ff4a commit 61b52de
Show file tree
Hide file tree
Showing 23 changed files with 1,266 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
api(project(":core:common:common-api"))
api(project(":core:common:common-web"))
api(project(":core:buildless:api-buildless"))
api("io.fabric8:kubernetes-client")
}

plugins {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-CI 蓝鲸持续集成平台 is licensed under the MIT license.
*
* A copy of the MIT License is included in this file.
*
*
* Terms of the MIT License:
* ---------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.tencent.devops.dispatch.kubernetes.pojo.base

import io.swagger.v3.oas.annotations.media.Schema

@Schema(title = "k8s仓库信息")
data class KubernetesRepo(
@get:Schema(title = "仓库地址", required = true)
val registryUrl: String,
@get:Schema(title = "用户名", required = true)
val username: String,
@get:Schema(title = "密码", required = true)
val password: String,
@get:Schema(title = "邮箱", required = false)
val email: String?
)
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@ enum class ErrorCodeEnum(
ErrorType.USER,
2126054,
"已超过DevCloud创建Job环境上限."
),
KUBERNETES_CREATE_RESOURCE_FAIL(
ErrorType.SYSTEM,
2126055,
"kubernetes创建{0}资源失败,原因:{1}"
);

fun getErrorMessage(): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-CI 蓝鲸持续集成平台 is licensed under the MIT license.
*
* A copy of the MIT License is included in this file.
*
*
* Terms of the MIT License:
* ---------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.tencent.devops.dispatch.kubernetes.client

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.tencent.devops.common.api.util.JsonUtil
import com.tencent.devops.common.api.util.OkhttpUtils
import com.tencent.devops.common.dispatch.sdk.BuildFailureException
import com.tencent.devops.dispatch.kubernetes.pojo.KubernetesResult
import com.tencent.devops.dispatch.kubernetes.pojo.common.ErrorCodeEnum
import io.fabric8.kubernetes.api.model.apps.Deployment
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired

class DeploymentClient @Autowired constructor(
private val objectMapper: ObjectMapper,
private val clientCommon: KubernetesClientCommon
) {

companion object {
private val logger = LoggerFactory.getLogger(DeploymentClient::class.java)
}

fun createDeployment(
userId: String,
namespace: String,
deployment: Deployment
): KubernetesResult<String> {
val url = "/api/namespace/$namespace/deployments"
val body = JsonUtil.toJson(deployment)
logger.info("Create deployment request url: $url, body: $body")
val request = clientCommon.microBaseRequest(url).post(
RequestBody.create(
"application/json; charset=utf-8".toMediaTypeOrNull(),
body
)
).build()
val responseBody = OkhttpUtils.doHttp(request).body!!.string()
logger.info("Create deployment response: ${JsonUtil.toJson(responseBody)}")
return JsonUtil.getObjectMapper().readValue(responseBody)
}

fun getDeploymentByName(
userId: String,
namespace: String,
deploymentName: String
): KubernetesResult<Deployment> {
val url = "/api/namespace/$namespace/deployments/$deploymentName"
val request = clientCommon.microBaseRequest(url).get().build()
logger.info("Get deployment: $deploymentName request url: $url, userId: $userId")
OkhttpUtils.doHttp(request).use { response ->
val responseContent = response.body!!.string()
logger.info("Get deployment: $deploymentName response: $responseContent")
if (!response.isSuccessful) {
throw BuildFailureException(
errorType = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorType,
errorCode = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorCode,
formatErrorMessage = ErrorCodeEnum.BCS_SYSTEM_ERROR.getErrorMessage(),
errorMessage = "Fail to get deployment,http response code: ${response.code}"
)
}
return objectMapper.readValue(responseContent)
}
}

fun deleteDeploymentByName(
userId: String,
namespace: String,
deploymentName: String
): KubernetesResult<String> {
val url = "/api/namespace/$namespace/deployments/$deploymentName"
val request = clientCommon.microBaseRequest(url).delete().build()
logger.info("Delete deployment: $deploymentName request url: $url, userId: $userId")
OkhttpUtils.doHttp(request).use { response ->
val responseContent = response.body!!.string()
logger.info("Delete deployment: $deploymentName response: $responseContent")
if (!response.isSuccessful) {
throw BuildFailureException(
errorType = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorType,
errorCode = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorCode,
formatErrorMessage = ErrorCodeEnum.BCS_SYSTEM_ERROR.getErrorMessage(),
errorMessage = "Fail to delete deployment,http response code: ${response.code}"
)
}
return objectMapper.readValue(responseContent)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-CI 蓝鲸持续集成平台 is licensed under the MIT license.
*
* A copy of the MIT License is included in this file.
*
*
* Terms of the MIT License:
* ---------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.tencent.devops.dispatch.kubernetes.client

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.tencent.devops.common.api.util.JsonUtil
import com.tencent.devops.common.api.util.OkhttpUtils
import com.tencent.devops.common.dispatch.sdk.BuildFailureException
import com.tencent.devops.dispatch.kubernetes.pojo.KubernetesResult
import com.tencent.devops.dispatch.kubernetes.pojo.common.ErrorCodeEnum
import io.fabric8.kubernetes.api.model.networking.v1.Ingress
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired

class IngressClient @Autowired constructor(
private val objectMapper: ObjectMapper,
private val clientCommon: KubernetesClientCommon
) {

companion object {
private val logger = LoggerFactory.getLogger(IngressClient::class.java)
}

fun createIngress(
userId: String,
namespace: String,
ingress: Ingress
): KubernetesResult<String> {
val url = "/api/namespace/$namespace/ingress"
val body = JsonUtil.toJson(ingress)
logger.info("Create ingress request url: $url, body: $body")
val request = clientCommon.microBaseRequest(url).post(
RequestBody.create(
"application/json; charset=utf-8".toMediaTypeOrNull(),
body
)
).build()
val responseBody = OkhttpUtils.doHttp(request).body!!.string()
logger.info("Create ingress response: ${JsonUtil.toJson(responseBody)}")
return JsonUtil.getObjectMapper().readValue(responseBody)
}

fun getIngressByName(
userId: String,
namespace: String,
ingressName: String
): KubernetesResult<Ingress> {
val url = "/api/namespace/$namespace/ingress/$ingressName"
val request = clientCommon.microBaseRequest(url).get().build()
logger.info("Get ingress: $ingressName request url: $url, userId: $userId")
OkhttpUtils.doHttp(request).use { response ->
val responseContent = response.body!!.string()
logger.info("Get ingress: $ingressName response: $responseContent")
if (!response.isSuccessful) {
throw BuildFailureException(
errorType = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorType,
errorCode = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorCode,
formatErrorMessage = ErrorCodeEnum.BCS_SYSTEM_ERROR.getErrorMessage(),
errorMessage = "Fail to get ingress,http response code: ${response.code}"
)
}
return objectMapper.readValue(responseContent)
}
}

fun deleteIngressByName(
userId: String,
namespace: String,
ingressName: String
): KubernetesResult<String> {
val url = "/api/namespace/$namespace/ingress/$ingressName"
val request = clientCommon.microBaseRequest(url).delete().build()
logger.info("Delete ingress: $ingressName request url: $url, userId: $userId")
OkhttpUtils.doHttp(request).use { response ->
val responseContent = response.body!!.string()
logger.info("Delete ingress: $ingressName response: $responseContent")
if (!response.isSuccessful) {
throw BuildFailureException(
errorType = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorType,
errorCode = ErrorCodeEnum.BCS_SYSTEM_ERROR.errorCode,
formatErrorMessage = ErrorCodeEnum.BCS_SYSTEM_ERROR.getErrorMessage(),
errorMessage = "Fail to delete ingress,http response code: ${response.code}"
)
}
return objectMapper.readValue(responseContent)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class KubernetesClientCommon @Autowired constructor(
return Request.Builder().url(commonService.getProxyUrl(kubernetesApiUrl + url)).headers(headers(headers))
}

fun microBaseRequest(url: String, headers: Map<String, String>? = null): Request.Builder {
return Request.Builder().url(kubernetesApiUrl + url).headers(headers(headers))
}

fun headers(otherHeaders: Map<String, String>? = null): Headers {
val result = mutableMapOf<String, String>()

Expand Down
Loading

0 comments on commit 61b52de

Please sign in to comment.