diff --git a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message.properties b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message.properties index 2f5e7da6ce..6df5eddb2d 100644 --- a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message.properties +++ b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message.properties @@ -132,10 +132,9 @@ 1246003=删除作业执行日志失败 ##业务错误-文件网关服务(job-file-gateway) 1260001=文件源不存在:{0} -1260002=接入点响应异常:ListBucket,详情:{0} -1260003=接入点响应异常:ListObjects,详情:{0} -1260008=接入点响应异常:DeleteBucket,详情:{0} -1260009=接入点响应异常:DeleteBucketFile,详情:{0} +1260002=接入点响应异常:ListFileNode,详情:{0} +1260003=接入点响应异常:FileAvailable,详情:{0} +1260008=接入点响应异常:ExecuteAction,详情:{0} 1260004=文件源别名已存在:{0} 1260005=无法匹配到有效接入点,请检查文件源配置 1260006=接入点响应异常:ClearTaskFiles,详情:{0} diff --git a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en.properties b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en.properties index 061da05367..0d8b812025 100644 --- a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en.properties +++ b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en.properties @@ -133,10 +133,9 @@ 1246003=Failed to delete execution log ## Business error (job-file-gateway) 1260001=FileSource does not exist:{0} -1260002=FileWorker response error:ListBucket, Detail:{0} -1260003=FileWorker response error:ListObjects, Detail:{0} -1260008=FileWorker response error:DeleteBucket, Detail:{0} -1260009=FileWorker response error:DeleteBucketFile, Detail:{0} +1260002=FileWorker response error:ListFileNode, Detail:{0} +1260003=FileWorker response error:FileAvailable, Detail:{0} +1260008=FileWorker response error:ExecuteAction, Detail:{0} 1260004=FileSource alias already exists:{0} 1260005=Cannot find available file worker, please check configuration of fileSource 1260006=FileWorker response error:ClearTaskFiles, Detail:{0} diff --git a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en_US.properties b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en_US.properties index 061da05367..0d8b812025 100644 --- a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en_US.properties +++ b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_en_US.properties @@ -133,10 +133,9 @@ 1246003=Failed to delete execution log ## Business error (job-file-gateway) 1260001=FileSource does not exist:{0} -1260002=FileWorker response error:ListBucket, Detail:{0} -1260003=FileWorker response error:ListObjects, Detail:{0} -1260008=FileWorker response error:DeleteBucket, Detail:{0} -1260009=FileWorker response error:DeleteBucketFile, Detail:{0} +1260002=FileWorker response error:ListFileNode, Detail:{0} +1260003=FileWorker response error:FileAvailable, Detail:{0} +1260008=FileWorker response error:ExecuteAction, Detail:{0} 1260004=FileSource alias already exists:{0} 1260005=Cannot find available file worker, please check configuration of fileSource 1260006=FileWorker response error:ClearTaskFiles, Detail:{0} diff --git a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh.properties b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh.properties index 2f5e7da6ce..6df5eddb2d 100644 --- a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh.properties +++ b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh.properties @@ -132,10 +132,9 @@ 1246003=删除作业执行日志失败 ##业务错误-文件网关服务(job-file-gateway) 1260001=文件源不存在:{0} -1260002=接入点响应异常:ListBucket,详情:{0} -1260003=接入点响应异常:ListObjects,详情:{0} -1260008=接入点响应异常:DeleteBucket,详情:{0} -1260009=接入点响应异常:DeleteBucketFile,详情:{0} +1260002=接入点响应异常:ListFileNode,详情:{0} +1260003=接入点响应异常:FileAvailable,详情:{0} +1260008=接入点响应异常:ExecuteAction,详情:{0} 1260004=文件源别名已存在:{0} 1260005=无法匹配到有效接入点,请检查文件源配置 1260006=接入点响应异常:ClearTaskFiles,详情:{0} diff --git a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh_CN.properties b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh_CN.properties index 2f5e7da6ce..6df5eddb2d 100644 --- a/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh_CN.properties +++ b/src/backend/commons/common-i18n/src/main/resources/i18n/exception/message_zh_CN.properties @@ -132,10 +132,9 @@ 1246003=删除作业执行日志失败 ##业务错误-文件网关服务(job-file-gateway) 1260001=文件源不存在:{0} -1260002=接入点响应异常:ListBucket,详情:{0} -1260003=接入点响应异常:ListObjects,详情:{0} -1260008=接入点响应异常:DeleteBucket,详情:{0} -1260009=接入点响应异常:DeleteBucketFile,详情:{0} +1260002=接入点响应异常:ListFileNode,详情:{0} +1260003=接入点响应异常:FileAvailable,详情:{0} +1260008=接入点响应异常:ExecuteAction,详情:{0} 1260004=文件源别名已存在:{0} 1260005=无法匹配到有效接入点,请检查文件源配置 1260006=接入点响应异常:ClearTaskFiles,详情:{0} diff --git a/src/backend/commons/common-web/build.gradle b/src/backend/commons/common-web/build.gradle index 2685ffd418..1c3834f63c 100644 --- a/src/backend/commons/common-web/build.gradle +++ b/src/backend/commons/common-web/build.gradle @@ -29,6 +29,7 @@ dependencies { implementation project(":commons:common-spring-ext") implementation project(":commons:esb-sdk") implementation project(":commons:common-iam") + implementation 'io.springfox:springfox-swagger2' implementation "org.hibernate.validator:hibernate-validator" implementation('jakarta.validation:jakarta.validation-api') implementation "org.springframework.cloud:spring-cloud-starter-sleuth" diff --git a/src/backend/commons/common-web/src/main/java/com/tencent/bk/job/common/web/model/InnerServiceResponse.java b/src/backend/commons/common-web/src/main/java/com/tencent/bk/job/common/web/model/InnerServiceResponse.java new file mode 100644 index 0000000000..68df06d837 --- /dev/null +++ b/src/backend/commons/common-web/src/main/java/com/tencent/bk/job/common/web/model/InnerServiceResponse.java @@ -0,0 +1,208 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.common.web.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tencent.bk.job.common.constant.ErrorCode; +import com.tencent.bk.job.common.exception.ServiceException; +import com.tencent.bk.job.common.i18n.service.MessageI18nService; +import com.tencent.bk.job.common.iam.model.AuthResult; +import com.tencent.bk.job.common.model.ValidateResult; +import com.tencent.bk.job.common.model.error.ErrorDetail; +import com.tencent.bk.job.common.util.ApplicationContextRegister; +import com.tencent.bk.job.common.util.JobContextUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +@Slf4j +@Getter +@Setter +@ToString +@NoArgsConstructor +@ApiModel("服务间调用通用返回结构") +public class InnerServiceResponse { + public static final Integer SUCCESS_CODE = 0; + public static final Integer COMMON_FAIL_CODE = 1; + private static volatile MessageI18nService i18nService; + + @ApiModelProperty("是否成功") + private boolean success; + + @ApiModelProperty("返回码") + private Integer code; + + @ApiModelProperty("错误信息") + private String errorMsg; + + @ApiModelProperty("请求成功返回的数据") + private T data; + + @ApiModelProperty("请求 ID") + private String requestId; + + @ApiModelProperty("鉴权结果,当返回码为1238001时,该字段有值") + @JsonProperty("authResult") + private AuthResult authResult; + + @ApiModelProperty("错误详情") + @JsonProperty("errorDetail") + private ErrorDetail errorDetail; + + public InnerServiceResponse(Integer code, String errorMsg, T data) { + this.code = code; + this.errorMsg = errorMsg; + this.data = data; + this.requestId = JobContextUtil.getRequestId(); + } + + private static MessageI18nService getI18nService() { + if (i18nService == null) { + synchronized (InnerServiceResponse.class) { + if (i18nService == null) { + i18nService = ApplicationContextRegister.getBean(MessageI18nService.class); + } + } + } + return i18nService; + } + + public static InnerServiceResponse buildSuccessResp(T data) { + InnerServiceResponse resp = new InnerServiceResponse<>(SUCCESS_CODE, null, data); + resp.success = true; + return resp; + } + + public static InnerServiceResponse buildAuthFailResp(AuthResult authResult) { + MessageI18nService i18nService = getI18nService(); + String message = null; + if (i18nService != null) { + message = i18nService.getI18n(String.valueOf(ErrorCode.USER_NO_PERMISSION_COMMON)); + } else { + log.warn("cannot find available i18nService"); + } + InnerServiceResponse resp = new InnerServiceResponse(ErrorCode.USER_NO_PERMISSION_COMMON, message, null); + resp.success = false; + resp.authResult = authResult; + return resp; + } + + public static InnerServiceResponse buildCommonFailResp(String msg) { + InnerServiceResponse resp = new InnerServiceResponse<>(COMMON_FAIL_CODE, msg, null); + resp.success = false; + return resp; + } + + public static InnerServiceResponse buildCommonFailResp(Integer errorCode, String msg) { + InnerServiceResponse resp = new InnerServiceResponse<>(errorCode, msg, null); + resp.success = false; + return resp; + } + + public static InnerServiceResponse buildCommonFailResp(Integer errorCode) { + try { + getI18nService(); + } catch (Exception e) { + log.warn("cannot get i18nService from spring context"); + } + String errorMsg = null; + if (i18nService != null) { + errorMsg = i18nService.getI18n(errorCode.toString()); + } + InnerServiceResponse resp = new InnerServiceResponse<>(errorCode, errorMsg, null); + resp.success = false; + return resp; + } + + public static InnerServiceResponse buildCommonFailResp(Integer errorCode, MessageI18nService i18nService) { + String errorMsg = i18nService.getI18n(String.valueOf(errorCode)); + if (StringUtils.isEmpty(errorMsg)) { + errorMsg = String.valueOf(errorCode); + } + InnerServiceResponse resp = new InnerServiceResponse<>(errorCode, errorMsg, null); + resp.success = false; + return resp; + } + + public static InnerServiceResponse buildCommonFailResp(Integer errorCode, Object[] params) { + getI18nService(); + return buildCommonFailResp(errorCode, params, i18nService); + } + + public static InnerServiceResponse buildCommonFailResp(Integer errorCode, Object[] params, + MessageI18nService i18nService) { + String errorMsg = ""; + if (params != null && params.length > 0) { + errorMsg = i18nService.getI18nWithArgs(String.valueOf(errorCode), params); + } else { + errorMsg = i18nService.getI18n(String.valueOf(errorCode)); + } + if (StringUtils.isEmpty(errorMsg)) { + errorMsg = String.valueOf(errorCode); + } + InnerServiceResponse resp = new InnerServiceResponse<>(errorCode, errorMsg, null); + resp.success = false; + return resp; + } + + public static InnerServiceResponse buildCommonFailResp(ServiceException e, MessageI18nService i18nService) { + log.info("exception: {}|{}|{}", e.getErrorCode(), e.getErrorMsg(), e.getErrorParams()); + int errorCode = e.getErrorCode(); + String errorMsg = e.getErrorMsg(); + if (StringUtils.isEmpty(errorMsg)) { + errorMsg = i18nService.getI18nWithArgs(String.valueOf(errorCode), e.getErrorParams()); + log.info("{}", errorMsg); + } + if (StringUtils.isEmpty(errorMsg)) { + errorMsg = String.valueOf(errorCode); + } + return new InnerServiceResponse<>(e.getErrorCode(), errorMsg, null); + } + + public static InnerServiceResponse buildValidateFailResp(MessageI18nService i18nService, + ValidateResult validateResult) { + if (validateResult.getErrorParams() != null && validateResult.getErrorParams().length > 0) { + return InnerServiceResponse.buildCommonFailResp(validateResult.getErrorCode(), + i18nService.getI18nWithArgs(String.valueOf(validateResult.getErrorCode()), + validateResult.getErrorParams())); + } else { + return InnerServiceResponse.buildCommonFailResp(validateResult.getErrorCode(), + i18nService.getI18n(String.valueOf(validateResult.getErrorCode()))); + } + } + + public static InnerServiceResponse buildCommonFailResp(int errorCode, ErrorDetail errorDetail, + MessageI18nService i18nService) { + String errorMsg = i18nService.getI18n(String.valueOf(errorCode)); + InnerServiceResponse esbResp = new InnerServiceResponse<>(errorCode, errorMsg, null); + esbResp.setErrorDetail(errorDetail); + return esbResp; + } +} diff --git a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/constant/ErrorCode.java b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/constant/ErrorCode.java index 454983ef24..459f53a91c 100644 --- a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/constant/ErrorCode.java +++ b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/constant/ErrorCode.java @@ -251,14 +251,12 @@ public class ErrorCode { // 文件网关 start // 文件源不存在:{0} public static final int FILE_SOURCE_NOT_EXIST = 1260001; - // 接入点响应异常:ListBucket,详情:{0} - public static final int FAIL_TO_REQUEST_FILE_WORKER_LIST_BUCKET = 1260002; - // 接入点响应异常:ListObjects,详情:{0} - public static final int FAIL_TO_REQUEST_FILE_WORKER_LIST_OBJECTS = 1260003; - // 接入点响应异常:DeleteBucket,详情:{0} - public static final int FAIL_TO_REQUEST_FILE_WORKER_DELETE_BUCKET = 1260008; - // 接入点响应异常:DeleteBucketFile,详情:{0} - public static final int FAIL_TO_REQUEST_FILE_WORKER_DELETE_BUCKET_FILE = 1260009; + // 接入点响应异常:ListFileNode,详情:{0} + public static final int FAIL_TO_REQUEST_FILE_WORKER_LIST_FILE_NODE = 1260002; + // 接入点响应异常:FileAvailable,详情:{0} + public static final int FAIL_TO_REQUEST_FILE_WORKER_FILE_AVAILABLE = 1260003; + // 接入点响应异常:ExecuteAction,详情:{0} + public static final int FAIL_TO_REQUEST_FILE_WORKER_EXECUTE_ACTION = 1260008; // 文件源别名已存在:{0} public static final int FILE_SOURCE_ALIAS_ALREADY_EXISTS = 1260004; diff --git a/src/backend/job-file-gateway/api-job-file-gateway/build.gradle b/src/backend/job-file-gateway/api-job-file-gateway/build.gradle index 7ea1a301b6..5e4c3eee14 100644 --- a/src/backend/job-file-gateway/api-job-file-gateway/build.gradle +++ b/src/backend/job-file-gateway/api-job-file-gateway/build.gradle @@ -26,6 +26,7 @@ dependencies { compile project(':commons:common') compile project(':commons:common-i18n') compile project(':commons:common-iam') + compile project(':commons:esb-sdk') compile project(":job-logsvr:api-job-logsvr") compile project(":job-file-gateway:api-job-file-gateway-worker") implementation "org.springframework:spring-web" diff --git a/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/api/esb/EsbFileSourceV3Resource.java b/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/api/esb/EsbFileSourceV3Resource.java new file mode 100644 index 0000000000..72c1df8d03 --- /dev/null +++ b/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/api/esb/EsbFileSourceV3Resource.java @@ -0,0 +1,52 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.file_gateway.api.esb; + +import com.tencent.bk.job.common.annotation.EsbAPI; +import com.tencent.bk.job.common.esb.model.EsbResp; +import com.tencent.bk.job.file_gateway.model.req.esb.v3.EsbCreateOrUpdateFileSourceV3Req; +import com.tencent.bk.job.file_gateway.model.resp.esb.v3.EsbFileSourceSimpleInfoV3DTO; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 文件源API-V3 + */ +@RequestMapping("/esb/api/v3") +@RestController +@EsbAPI +public interface EsbFileSourceV3Resource { + + @PostMapping("/create_file_source") + EsbResp createFileSource( + @RequestBody EsbCreateOrUpdateFileSourceV3Req req); + + @PostMapping("/update_file_source") + EsbResp updateFileSource( + @RequestBody EsbCreateOrUpdateFileSourceV3Req req); + +} diff --git a/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/model/req/esb/v3/EsbCreateOrUpdateFileSourceV3Req.java b/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/model/req/esb/v3/EsbCreateOrUpdateFileSourceV3Req.java new file mode 100644 index 0000000000..149a8769fa --- /dev/null +++ b/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/model/req/esb/v3/EsbCreateOrUpdateFileSourceV3Req.java @@ -0,0 +1,56 @@ +package com.tencent.bk.job.file_gateway.model.req.esb.v3; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tencent.bk.job.common.esb.model.EsbReq; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Map; + +@EqualsAndHashCode(callSuper = true) +@Data +public class EsbCreateOrUpdateFileSourceV3Req extends EsbReq { + /** + * 业务ID + */ + @JsonProperty("bk_biz_id") + private Long appId; + + @ApiModelProperty(value = "ID,更新文件源的时候需要传入,新建文件源不需要") + private Integer id; + /** + * 文件源Code + */ + @ApiModelProperty(value = "文件源Code") + private String code; + /** + * 文件源别名 + */ + @ApiModelProperty(value = "文件源名称") + private String alias; + /** + * 文件源类型 + */ + @ApiModelProperty(value = "文件源类型") + private String type; + + /** + * 文件源信息Map + */ + @ApiModelProperty(value = "文件源信息Map") + @JsonProperty(value = "access_params") + private Map accessParams; + /** + * 文件源凭证Id + */ + @ApiModelProperty(value = "文件源凭证Id") + @JsonProperty(value = "credential_id") + private String credentialId; + /** + * 文件前缀 + */ + @ApiModelProperty(value = "文件前缀:后台自动生成UUID传${UUID},自定义字符串直接传") + @JsonProperty(value = "file_prefix") + private String filePrefix; +} diff --git a/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/model/resp/esb/v3/EsbFileSourceSimpleInfoV3DTO.java b/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/model/resp/esb/v3/EsbFileSourceSimpleInfoV3DTO.java new file mode 100644 index 0000000000..aee7669c92 --- /dev/null +++ b/src/backend/job-file-gateway/api-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/model/resp/esb/v3/EsbFileSourceSimpleInfoV3DTO.java @@ -0,0 +1,38 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.file_gateway.model.resp.esb.v3; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class EsbFileSourceSimpleInfoV3DTO { + + private Integer id; + +} diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/api/esb/EsbFileSourceV3ResourceImpl.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/api/esb/EsbFileSourceV3ResourceImpl.java new file mode 100644 index 0000000000..8f14b8929c --- /dev/null +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/api/esb/EsbFileSourceV3ResourceImpl.java @@ -0,0 +1,163 @@ +package com.tencent.bk.job.file_gateway.api.esb; + +import com.tencent.bk.job.common.esb.model.EsbResp; +import com.tencent.bk.job.common.exception.InvalidParamException; +import com.tencent.bk.job.common.iam.constant.ActionId; +import com.tencent.bk.job.common.iam.constant.ResourceId; +import com.tencent.bk.job.common.iam.constant.ResourceTypeEnum; +import com.tencent.bk.job.common.iam.model.AuthResult; +import com.tencent.bk.job.common.iam.service.AuthService; +import com.tencent.bk.job.file_gateway.consts.WorkerSelectModeEnum; +import com.tencent.bk.job.file_gateway.consts.WorkerSelectScopeEnum; +import com.tencent.bk.job.file_gateway.model.dto.FileSourceDTO; +import com.tencent.bk.job.file_gateway.model.req.esb.v3.EsbCreateOrUpdateFileSourceV3Req; +import com.tencent.bk.job.file_gateway.model.resp.esb.v3.EsbFileSourceSimpleInfoV3DTO; +import com.tencent.bk.job.file_gateway.service.FileSourceService; +import com.tencent.bk.sdk.iam.util.PathBuilder; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; + +@RestController +@Slf4j +public class EsbFileSourceV3ResourceImpl implements EsbFileSourceV3Resource { + + private final AuthService authService; + private final FileSourceService fileSourceService; + + @Autowired + public EsbFileSourceV3ResourceImpl(AuthService authService, FileSourceService fileSourceService) { + this.authService = authService; + this.fileSourceService = fileSourceService; + } + + @Override + public EsbResp createFileSource(EsbCreateOrUpdateFileSourceV3Req req) { + Long appId = req.getAppId(); + String username = req.getUserName(); + AuthResult authResult = checkCreateFileSourcePermission(username, appId); + if (!authResult.isPass()) { + return authService.buildEsbAuthFailResp(authResult.getRequiredActionResources()); + } + checkCreateParam(req); + FileSourceDTO fileSourceDTO = buildFileSourceDTO(req.getUserName(), appId, req); + Integer fileSourceId = fileSourceService.saveFileSource(appId, fileSourceDTO); + boolean registerResult = authService.registerResource("" + fileSourceId, fileSourceDTO.getAlias(), + ResourceId.FILE_SOURCE, username, null); + if (!registerResult) { + log.warn("Fail to register file_source to iam:({},{})", fileSourceId, fileSourceDTO.getAlias()); + } + return EsbResp.buildSuccessResp(new EsbFileSourceSimpleInfoV3DTO(fileSourceId)); + } + + @Override + public EsbResp updateFileSource(EsbCreateOrUpdateFileSourceV3Req req) { + checkUpdateParam(req); + Long appId = req.getAppId(); + String username = req.getUserName(); + Integer id = req.getId(); + AuthResult authResult = checkManageFileSourcePermission(username, appId, id); + if (!authResult.isPass()) { + return authService.buildEsbAuthFailResp(authResult.getRequiredActionResources()); + } + FileSourceDTO fileSourceDTO = buildFileSourceDTO(req.getUserName(), appId, req); + Integer fileSourceId = fileSourceService.updateFileSourceById(appId, fileSourceDTO); + return EsbResp.buildSuccessResp(new EsbFileSourceSimpleInfoV3DTO(fileSourceId)); + } + + private void checkAppId(EsbCreateOrUpdateFileSourceV3Req req) { + if (req.getAppId() == null) { + throw new InvalidParamException("bk_biz_id", "bk_biz_id cannot be null"); + } + } + + private void checkCreateParam(EsbCreateOrUpdateFileSourceV3Req req) { + checkAppId(req); + String code = req.getCode(); + if (StringUtils.isBlank(code)) { + throw new InvalidParamException("code", "code cannot be null or blank"); + } + if (fileSourceService.existsCode(code)) { + throw new InvalidParamException("code", String.format("code [%s] already exists", code)); + } + if (StringUtils.isBlank(req.getAlias())) { + throw new InvalidParamException("alias", "alias cannot be null or blank"); + } + if (StringUtils.isBlank(req.getType())) { + throw new InvalidParamException("type", "type cannot be null or blank"); + } + if (StringUtils.isBlank(req.getCredentialId())) { + throw new InvalidParamException("credential_id", "credential_id cannot be null or blank"); + } + } + + private void checkUpdateParam(EsbCreateOrUpdateFileSourceV3Req req) { + checkAppId(req); + Long appId = req.getAppId(); + Integer id = req.getId(); + String code = req.getCode(); + if (id == null && StringUtils.isBlank(code)) { + throw new InvalidParamException("id/code", "id and code cannot be null/blank simultaneously"); + } + if (id == null) { + id = fileSourceService.getFileSourceIdByCode(appId, code); + if (id == null) { + throw new InvalidParamException("code", String.format("cannot find fileSource by code [%s]", code)); + } + } + req.setId(id); + if (!fileSourceService.existsFileSource(appId, id)) { + throw new InvalidParamException( + "bk_biz_id/id", + String.format("fileSource [%s] not exists in biz [%s]", id, appId) + ); + } + } + + private FileSourceDTO buildFileSourceDTO(String username, Long appId, + EsbCreateOrUpdateFileSourceV3Req fileSourceCreateUpdateReq) { + FileSourceDTO fileSourceDTO = new FileSourceDTO(); + fileSourceDTO.setAppId(appId); + fileSourceDTO.setId(fileSourceCreateUpdateReq.getId()); + fileSourceDTO.setCode(fileSourceCreateUpdateReq.getCode()); + fileSourceDTO.setAlias(fileSourceCreateUpdateReq.getAlias()); + fileSourceDTO.setStatus(null); + fileSourceDTO.setFileSourceType( + fileSourceService.getFileSourceTypeByCode( + fileSourceCreateUpdateReq.getType() + ) + ); + fileSourceDTO.setFileSourceInfoMap(fileSourceCreateUpdateReq.getAccessParams()); + fileSourceDTO.setPublicFlag(false); + fileSourceDTO.setSharedAppIdList(Collections.emptyList()); + fileSourceDTO.setShareToAllApp(false); + fileSourceDTO.setCredentialId(fileSourceCreateUpdateReq.getCredentialId()); + fileSourceDTO.setFilePrefix(fileSourceCreateUpdateReq.getFilePrefix()); + fileSourceDTO.setWorkerSelectScope(WorkerSelectScopeEnum.PUBLIC.name()); + fileSourceDTO.setWorkerSelectMode(WorkerSelectModeEnum.AUTO.name()); + fileSourceDTO.setWorkerId(null); + // 文件源默认开启状态 + fileSourceDTO.setEnable(true); + fileSourceDTO.setCreator(username); + fileSourceDTO.setCreateTime(System.currentTimeMillis()); + fileSourceDTO.setLastModifyUser(username); + fileSourceDTO.setLastModifyTime(System.currentTimeMillis()); + return fileSourceDTO; + } + + public AuthResult checkCreateFileSourcePermission(String username, Long appId) { + // 需要拥有在业务下创建文件源的权限 + return authService.auth(true, username, ActionId.CREATE_FILE_SOURCE, ResourceTypeEnum.BUSINESS, + appId.toString(), null); + } + + public AuthResult checkManageFileSourcePermission(String username, Long appId, Integer fileSourceId) { + // 需要拥有在业务下管理某个具体文件源的权限 + return authService.auth(true, username, ActionId.MANAGE_FILE_SOURCE, ResourceTypeEnum.FILE_SOURCE, + fileSourceId.toString(), + PathBuilder.newBuilder(ResourceTypeEnum.BUSINESS.getId(), appId.toString()).build()); + } +} diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/FileSourceDAO.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/FileSourceDAO.java index 40b4020565..2e1b27a3de 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/FileSourceDAO.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/FileSourceDAO.java @@ -62,4 +62,10 @@ List listWorkTableFileSource(DSLContext dslContext, Long appId, S List listWorkTableFileSource(DSLContext dslContext, List appIdList, List idList, Integer start, Integer pageSize); + + boolean existsCode(String code); + + boolean existsFileSource(Long appId, Integer id); + + Integer getFileSourceIdByCode(Long appId, String code); } diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/impl/FileSourceDAOImpl.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/impl/FileSourceDAOImpl.java index c1da5f1946..a0ddc809f9 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/impl/FileSourceDAOImpl.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/dao/filesource/impl/FileSourceDAOImpl.java @@ -416,6 +416,45 @@ public List listWorkTableFileSource(DSLContext dslContext, List 0; + } + + @Override + public boolean existsFileSource(Long appId, Integer id) { + val query = defaultContext.selectZero().from(defaultTable) + .where(defaultTable.APP_ID.eq(appId)) + .and(defaultTable.ID.eq(id)) + .limit(1); + return query.fetch().size() > 0; + } + + @Override + public Integer getFileSourceIdByCode(Long appId, String code) { + List conditions = new ArrayList<>(); + if (appId != null) { + conditions.add(defaultTable.APP_ID.eq(appId)); + } + if (code != null) { + conditions.add(defaultTable.CODE.eq(code)); + } + val query = defaultContext.select( + defaultTable.ID + ).from(defaultTable) + .where(conditions); + val result = query.fetch(); + if (result.size() > 0) { + if (result.size() > 1) { + log.warn("{} records found when get id by code, use first one", result.size()); + } + return result.get(0).get(defaultTable.ID); + } + return null; + } + private List listFileSourceByConditions(DSLContext dslContext, Collection conditions, Integer start, Integer pageSize) { val query = dslContext.select( diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/CredentialService.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/CredentialService.java index e4622f4a84..21eb8886f2 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/CredentialService.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/CredentialService.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.file_gateway.service; -import com.tencent.bk.job.ticket.model.credential.CommonCredentialDTO; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; public interface CredentialService { @@ -34,5 +34,5 @@ public interface CredentialService { * @param id * @return */ - CommonCredentialDTO getCredentialById(Long appId, String id); + CommonCredential getCredentialById(Long appId, String id); } diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileService.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileService.java index e8dc9b31fb..f6de456397 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileService.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileService.java @@ -29,6 +29,8 @@ public interface FileService { + boolean isFileAvailable(String username, Long appId, Integer fileSourceId); + FileNodesVO listFileNode(String username, Long appId, Integer fileSourceId, String path, String name, Integer start, Integer pageSize); diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileSourceService.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileSourceService.java index b8207d9672..bea4dcb3c9 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileSourceService.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/FileSourceService.java @@ -75,4 +75,10 @@ List listWorkTableFileSource(List appIdList, List List getFileSourceParams(Long appId, String fileSourceTypeCode); Boolean checkFileSourceAlias(Long appId, String alias, Integer fileSourceId); + + boolean existsCode(String code); + + boolean existsFileSource(Long appId, Integer id); + + Integer getFileSourceIdByCode(Long appId, String code); } diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/CredentialServiceImpl.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/CredentialServiceImpl.java index 5af544e422..b368646af8 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/CredentialServiceImpl.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/CredentialServiceImpl.java @@ -25,10 +25,9 @@ package com.tencent.bk.job.file_gateway.service.impl; import com.tencent.bk.job.common.model.ServiceResponse; -import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.file_gateway.client.ServiceCredentialResourceClient; import com.tencent.bk.job.file_gateway.service.CredentialService; -import com.tencent.bk.job.ticket.model.credential.CommonCredentialDTO; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import com.tencent.bk.job.ticket.model.inner.resp.ServiceCredentialDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -46,7 +45,7 @@ public CredentialServiceImpl(ServiceCredentialResourceClient credentialService) } @Override - public CommonCredentialDTO getCredentialById(Long appId, String id) { + public CommonCredential getCredentialById(Long appId, String id) { ServiceResponse credentialServiceResponse = credentialService.getCredentialById(appId, id); ServiceCredentialDTO credentialDTO = credentialServiceResponse.getData(); @@ -54,11 +53,10 @@ public CommonCredentialDTO getCredentialById(Long appId, String id) { return null; } try { - CommonCredentialDTO commonCredentialDTO = JsonUtils.fromJson(credentialDTO.getValue(), - CommonCredentialDTO.class); + CommonCredential commonCredential = credentialDTO.getCredential(); // Type补全 - commonCredentialDTO.setType(credentialDTO.getType()); - return commonCredentialDTO; + commonCredential.setType(credentialDTO.getType()); + return commonCredential; } catch (Exception e) { log.error("credential not valid:{}", credentialDTO); return null; diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileServiceImpl.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileServiceImpl.java index 063c62defc..f58212d09c 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileServiceImpl.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileServiceImpl.java @@ -69,6 +69,33 @@ private FileWorkerDTO getFileWorker(Long appId, FileSourceDTO fileSourceDTO) { return dispatchService.findBestFileWorker(fileSourceDTO); } + @Override + public boolean isFileAvailable(String username, Long appId, Integer fileSourceId) { + FileSourceDTO fileSourceDTO = fileSourceService.getFileSourceById(appId, fileSourceId); + FileWorkerDTO fileWorkerDTO = getFileWorker(appId, fileSourceDTO); + if (fileWorkerDTO == null) { + throw new ServiceException(ErrorCode.CAN_NOT_FIND_AVAILABLE_FILE_WORKER); + } + log.info("choose file worker:" + fileWorkerDTO); + // 访问文件Worker接口,拿到available状态信息 + HttpReq fileAvailableReq = fileSourceReqGenService.genFileAvailableReq(appId, fileWorkerDTO, fileSourceDTO); + String respStr = null; + log.info(String.format("url=%s,body=%s,headers=%s", fileAvailableReq.getUrl(), fileAvailableReq.getBody(), + JsonUtils.toJson(fileAvailableReq.getHeaders()))); + try { + respStr = fileWorkerHttpHelper.post(fileAvailableReq.getUrl(), fileAvailableReq.getBody(), + fileAvailableReq.getHeaders()); + log.info(String.format("respStr=%s", respStr)); + ServiceResponse resp = JsonUtils.fromJson(respStr, + new TypeReference>() { + }); + return resp.getData(); + } catch (Exception e) { + log.error("Fail to request remote worker:", e); + return false; + } + } + @Override public FileNodesVO listFileNode(String username, Long appId, Integer fileSourceId, String path, String name, Integer start, Integer pageSize) { @@ -91,7 +118,7 @@ public FileNodesVO listFileNode(String username, Long appId, Integer fileSourceI listFileNodeReq.getHeaders()); } catch (Exception e) { log.error("Fail to request remote worker:", e); - throw new ServiceException(ErrorCode.FAIL_TO_REQUEST_FILE_WORKER_LIST_BUCKET, new String[]{e.getMessage()}); + throw new ServiceException(ErrorCode.FAIL_TO_REQUEST_FILE_WORKER_LIST_FILE_NODE, new String[]{e.getMessage()}); } log.info(String.format("respStr=%s", respStr)); FileNodesDTO fileNodesDTO = parseFileNodesDTO(respStr); @@ -127,7 +154,7 @@ public Boolean executeAction(String username, Long appId, Integer fileSourceId, throw (ServiceException) e; } else { log.error("Fail to request remote worker:", e); - throw new ServiceException(ErrorCode.FAIL_TO_REQUEST_FILE_WORKER_DELETE_BUCKET, + throw new ServiceException(ErrorCode.FAIL_TO_REQUEST_FILE_WORKER_EXECUTE_ACTION, new String[]{e.getMessage()}); } } @@ -140,7 +167,7 @@ private FileNodesDTO parseFileNodesDTO(String respStr) { }); } catch (Exception e) { log.error("Fail to parse bucket from response={}", respStr, e); - throw new ServiceException(ErrorCode.FAIL_TO_REQUEST_FILE_WORKER_LIST_BUCKET, e.getMessage()); + throw new ServiceException(ErrorCode.FAIL_TO_REQUEST_FILE_WORKER_LIST_FILE_NODE, e.getMessage()); } if (resp.isSuccess()) { return resp.getData(); diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileSourceServiceImpl.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileSourceServiceImpl.java index 686b896412..0f6ed59c6b 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileSourceServiceImpl.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/impl/FileSourceServiceImpl.java @@ -183,7 +183,7 @@ public List getFileSourceParams(Long appId, String fileSo FileWorkerDTO fileWorkerDTO = fileWorkerDAO.getFileWorkerById(dslContext, workerId); FileWorkerConfig fileWorkerConfig = JsonUtils.fromJson(fileWorkerDTO.getConfigStr(), new TypeReference() { - }); + }); List fileSourceMetaDataList = fileWorkerConfig.getFileSourceMetaDataList(); for (FileSourceMetaData fileSourceMetaData : fileSourceMetaDataList) { if (StringUtils.isNotBlank(fileSourceTypeCode) @@ -208,4 +208,19 @@ public Boolean checkFileSourceAlias(Long appId, String alias, Integer fileSource } return false; } + + @Override + public boolean existsCode(String code) { + return fileSourceDAO.existsCode(code); + } + + @Override + public boolean existsFileSource(Long appId, Integer id) { + return fileSourceDAO.existsFileSource(appId, id); + } + + @Override + public Integer getFileSourceIdByCode(Long appId, String code) { + return fileSourceDAO.getFileSourceIdByCode(appId, code); + } } diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/FileSourceReqGenService.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/FileSourceReqGenService.java index 35131fa337..85988d99a7 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/FileSourceReqGenService.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/FileSourceReqGenService.java @@ -34,15 +34,21 @@ * 远程文件源请求生成 */ public interface FileSourceReqGenService { + + /** + * 生成FileAvailable请求 + */ + HttpReq genFileAvailableReq(Long appId, FileWorkerDTO fileWorkerDTO, FileSourceDTO fileSourceDTO); + /** - * 生成ListBucket请求 - * - * @param fileWorkerDTO - * @return + * 生成ListFileNode请求 */ HttpReq genListFileNodeReq(Long appId, String path, String name, Integer start, Integer pageSize, FileWorkerDTO fileWorkerDTO, FileSourceDTO fileSourceDTO); + /** + * 生成ExecuteAction请求 + */ HttpReq genExecuteActionReq(Long appId, String actionCode, Map actionParams, FileWorkerDTO fileWorkerDTO, FileSourceDTO fileSourceDTO); diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/BaseRemoteFileReqGenServiceImpl.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/BaseRemoteFileReqGenServiceImpl.java index c5c7c12fb9..0fdbbddeb8 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/BaseRemoteFileReqGenServiceImpl.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/BaseRemoteFileReqGenServiceImpl.java @@ -30,7 +30,7 @@ import com.tencent.bk.job.file_gateway.model.dto.FileSourceDTO; import com.tencent.bk.job.file_gateway.model.dto.FileWorkerDTO; import com.tencent.bk.job.file_gateway.service.CredentialService; -import com.tencent.bk.job.ticket.model.credential.CommonCredentialDTO; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -55,14 +55,14 @@ protected String fillBaseReqGetUrl(BaseReq req, Long appId, FileWorkerDTO fileWo FileSourceDTO fileSourceDTO, String url) { String completeUrl = getCompleteUrl(fileWorkerDTO, url); String credentialId = fileSourceDTO.getCredentialId(); - CommonCredentialDTO commonCredentialDTO = null; + CommonCredential commonCredential = null; if (StringUtils.isNotBlank(credentialId)) { - commonCredentialDTO = credentialService.getCredentialById(fileSourceDTO.getAppId(), + commonCredential = credentialService.getCredentialById(fileSourceDTO.getAppId(), fileSourceDTO.getCredentialId()); } - if (commonCredentialDTO != null) { - req.setCredential(commonCredentialDTO); - log.debug("Credential of id {} is {}", credentialId, commonCredentialDTO); + if (commonCredential != null) { + req.setCredential(commonCredential); + log.debug("Credential of id {} is {}", credentialId, commonCredential); } else if (StringUtils.isNotBlank(credentialId)) { log.warn("Cannot find credential by id {}", credentialId); } diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/FileSourceReqGenServiceImpl.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/FileSourceReqGenServiceImpl.java index ccf7837637..dc47f5b09e 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/FileSourceReqGenServiceImpl.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/service/remote/impl/FileSourceReqGenServiceImpl.java @@ -25,6 +25,7 @@ package com.tencent.bk.job.file_gateway.service.remote.impl; import com.tencent.bk.job.common.model.http.HttpReq; +import com.tencent.bk.job.file.worker.model.req.BaseReq; import com.tencent.bk.job.file.worker.model.req.ExecuteActionReq; import com.tencent.bk.job.file.worker.model.req.ListFileNodeReq; import com.tencent.bk.job.file_gateway.model.dto.FileSourceDTO; @@ -45,6 +46,13 @@ public FileSourceReqGenServiceImpl(CredentialService credentialService) { super(credentialService); } + @Override + public HttpReq genFileAvailableReq(Long appId, FileWorkerDTO fileWorkerDTO, FileSourceDTO fileSourceDTO) { + BaseReq req = new BaseReq(); + String url = fillBaseReqGetUrl(req, appId, fileWorkerDTO, fileSourceDTO, "/file/available"); + return genRemoteFileReq(url, req); + } + @Override public HttpReq genListFileNodeReq(Long appId, String path, String name, Integer start, Integer pageSize, FileWorkerDTO fileWorkerDTO, FileSourceDTO fileSourceDTO) { diff --git a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/task/filesource/FileSourceStatusUpdateTask.java b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/task/filesource/FileSourceStatusUpdateTask.java index 2deab3bcfe..ecbc9419c6 100644 --- a/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/task/filesource/FileSourceStatusUpdateTask.java +++ b/src/backend/job-file-gateway/service-job-file-gateway/src/main/java/com/tencent/bk/job/file_gateway/task/filesource/FileSourceStatusUpdateTask.java @@ -57,7 +57,13 @@ public void run() { int start = 0; int pageSize = 20; do { - fileSourceDTOList = fileSourceService.listWorkTableFileSource(null, null, null, start, pageSize); + fileSourceDTOList = fileSourceService.listWorkTableFileSource( + null, + null, + null, + start, + pageSize + ); for (FileSourceDTO fileSourceDTO : fileSourceDTOList) { FileWorkerDTO fileWorkerDTO = dispatchService.findBestFileWorker(fileSourceDTO); int status; @@ -70,9 +76,12 @@ public void run() { } else { // 通过Worker调用listFileNode接口,OK的才算正常 try { - fileService.listFileNode(fileSourceDTO.getCreator(), fileSourceDTO.getAppId(), - fileSourceDTO.getId(), null, null, 0, 1); - status = 1; + if (fileService.isFileAvailable(fileSourceDTO.getCreator(), fileSourceDTO.getAppId(), + fileSourceDTO.getId())) { + status = 1; + } else { + status = 0; + } } catch (Throwable t) { status = 0; } diff --git a/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResource.java b/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResource.java index 8f15d9e0c7..bae8a170eb 100644 --- a/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResource.java +++ b/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResource.java @@ -26,6 +26,7 @@ import com.tencent.bk.job.common.annotation.InternalAPI; import com.tencent.bk.job.common.model.ServiceResponse; +import com.tencent.bk.job.file.worker.model.req.BaseReq; import com.tencent.bk.job.file.worker.model.req.ExecuteActionReq; import com.tencent.bk.job.file.worker.model.req.ListFileNodeReq; import com.tencent.bk.job.file_gateway.model.resp.common.FileNodesDTO; @@ -44,6 +45,11 @@ @InternalAPI public interface FileResource { + @ApiOperation(value = "测试文件源是否可用", produces = "application/json") + @PostMapping("/available") + ServiceResponse isFileAvailable( + @ApiParam(value = "文件源是否可用", required = true) @RequestBody BaseReq req); + @ApiOperation(value = "获取文件源/FileNode下的子FileNode列表", produces = "application/json") @PostMapping("/listFileNode") ServiceResponse listFileNode( diff --git a/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/BaseReq.java b/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/BaseReq.java index 322eeb8b3c..dc4e2ab5a9 100644 --- a/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/BaseReq.java +++ b/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/BaseReq.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.file.worker.model.req; -import com.tencent.bk.job.ticket.model.credential.CommonCredentialDTO; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import lombok.Data; import lombok.EqualsAndHashCode; @@ -38,7 +38,7 @@ public class BaseReq { String fileSourceTypeCode; // 凭据信息 - CommonCredentialDTO credential; + CommonCredential credential; // 文件源信息Map Map fileSourceInfoMap; diff --git a/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/ListFileNodeReq.java b/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/ListFileNodeReq.java index 444d4b3e4f..3257cce07d 100644 --- a/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/ListFileNodeReq.java +++ b/src/backend/job-file-worker-sdk/api-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/model/req/ListFileNodeReq.java @@ -42,4 +42,10 @@ public class ListFileNodeReq extends BaseReq { String name; Integer start; Integer pageSize; + + public ListFileNodeReq(BaseReq req) { + this.setCredential(req.getCredential()); + this.setFileSourceTypeCode(req.getFileSourceTypeCode()); + this.setFileSourceInfoMap(req.getFileSourceInfoMap()); + } } diff --git a/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceImpl.java b/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceImpl.java index 84b1a21b60..272e0d8f4c 100644 --- a/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceImpl.java +++ b/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceImpl.java @@ -26,6 +26,7 @@ import com.tencent.bk.job.common.model.ServiceResponse; import com.tencent.bk.job.common.util.json.JsonUtils; +import com.tencent.bk.job.file.worker.model.req.BaseReq; import com.tencent.bk.job.file.worker.model.req.ExecuteActionReq; import com.tencent.bk.job.file.worker.model.req.ListFileNodeReq; import com.tencent.bk.job.file_gateway.model.resp.common.FileNodesDTO; @@ -45,6 +46,11 @@ protected FileResourceImpl(IFileResource fileResource) { this.fileResource = fileResource; } + @Override + public ServiceResponse isFileAvailable(BaseReq req) { + return fileResource.isFileAvailable(req); + } + @Override public ServiceResponse listFileNode(ListFileNodeReq req) { log.info("req={}", JsonUtils.toJson(req)); diff --git a/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/IFileResource.java b/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/IFileResource.java index 3afcc64f01..ee19270f40 100644 --- a/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/IFileResource.java +++ b/src/backend/job-file-worker-sdk/service-job-file-worker-sdk/src/main/java/com/tencent/bk/job/file/worker/api/IFileResource.java @@ -35,6 +35,8 @@ public interface IFileResource { RemoteClient getRemoteClient(BaseReq req); + ServiceResponse isFileAvailable(BaseReq req); + ServiceResponse listFileNode(ListFileNodeReq req); ServiceResponse executeAction(ExecuteActionReq req); diff --git a/src/backend/job-file-worker/boot-job-file-worker/src/main/resources/FileWorkerConfig.json b/src/backend/job-file-worker/boot-job-file-worker/src/main/resources/FileWorkerConfig.json index 420f318c78..8a721a2fdb 100644 --- a/src/backend/job-file-worker/boot-job-file-worker/src/main/resources/FileWorkerConfig.json +++ b/src/backend/job-file-worker/boot-job-file-worker/src/main/resources/FileWorkerConfig.json @@ -8,14 +8,14 @@ "iconPath": "tencent_cloud.png", "staticParamList": [ { - "name": "endPointDomain", + "name": "end_point_domain", "label": "EndPoint", "required": true, "type": "TextInput", "default": "" }, { - "name": "appId", + "name": "app_id", "label": "APPID", "required": true, "type": "TextInput", @@ -170,7 +170,7 @@ "iconPath": "bk_artifactory.png", "staticParamList": [ { - "name": "baseUrl", + "name": "base_url", "label": "制品库根地址", "required": true, "type": "TextInput", diff --git a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceProxy.java b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceProxy.java index ca59790ac4..2996956412 100644 --- a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceProxy.java +++ b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/api/FileResourceProxy.java @@ -69,6 +69,11 @@ public RemoteClient getRemoteClient(BaseReq req) { return chooseFileResource(req).getRemoteClient(req); } + @Override + public ServiceResponse isFileAvailable(BaseReq req) { + return chooseFileResource(req).isFileAvailable(req); + } + @Override public ServiceResponse listFileNode(ListFileNodeReq req) { return chooseFileResource(req).listFileNode(req); diff --git a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/impl/ArtifactoryFileResourceImpl.java b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/impl/ArtifactoryFileResourceImpl.java index b3c66675b6..f8225a55ab 100644 --- a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/impl/ArtifactoryFileResourceImpl.java +++ b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/impl/ArtifactoryFileResourceImpl.java @@ -75,6 +75,12 @@ public RemoteClient getRemoteClient(BaseReq req) { return baseService.getArtifactoryClientFromBaseReq(req); } + @Override + public ServiceResponse isFileAvailable(BaseReq req) { + ArtifactoryRemoteClient client = baseService.getArtifactoryClientFromBaseReq(req); + return ServiceResponse.buildSuccessResp(client.isAvailable()); + } + private String parseParentNodeTypeByPath(String path) { if (StringUtils.isBlank(path)) return ArtifactoryNodeTypeEnum.FILE_SOURCE.name(); path = StringUtil.removePrefix(path, "/"); diff --git a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryBaseService.java b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryBaseService.java index 14055554db..992dcb2307 100644 --- a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryBaseService.java +++ b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryBaseService.java @@ -25,7 +25,7 @@ package com.tencent.bk.job.file.worker.artifactory.service; import com.tencent.bk.job.file.worker.model.req.BaseReq; -import com.tencent.bk.job.ticket.model.credential.CommonCredentialDTO; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -43,9 +43,9 @@ public ArtifactoryBaseService(MeterRegistry meterRegistry) { } public ArtifactoryRemoteClient getArtifactoryClientFromBaseReq(BaseReq req) { - CommonCredentialDTO credential = req.getCredential(); + CommonCredential credential = req.getCredential(); Map fileSourceInfoMap = req.getFileSourceInfoMap(); - return new ArtifactoryRemoteClient((String) fileSourceInfoMap.get("baseUrl"), credential.getUsername(), + return new ArtifactoryRemoteClient((String) fileSourceInfoMap.get("base_url"), credential.getUsername(), credential.getPassword(), meterRegistry); } } diff --git a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryRemoteClient.java b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryRemoteClient.java index 31723c8f77..c513fe83b1 100644 --- a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryRemoteClient.java +++ b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/artifactory/service/ArtifactoryRemoteClient.java @@ -34,8 +34,19 @@ import com.tencent.bk.job.common.util.http.LongRetryableHttpHelper; import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.file.worker.artifactory.consts.ArtifactoryInterfaceConsts; -import com.tencent.bk.job.file.worker.artifactory.model.dto.*; -import com.tencent.bk.job.file.worker.artifactory.model.req.*; +import com.tencent.bk.job.file.worker.artifactory.model.dto.ArtifactoryResp; +import com.tencent.bk.job.file.worker.artifactory.model.dto.NodeDTO; +import com.tencent.bk.job.file.worker.artifactory.model.dto.PageData; +import com.tencent.bk.job.file.worker.artifactory.model.dto.ProjectDTO; +import com.tencent.bk.job.file.worker.artifactory.model.dto.RepoDTO; +import com.tencent.bk.job.file.worker.artifactory.model.req.ArtifactoryReq; +import com.tencent.bk.job.file.worker.artifactory.model.req.DeleteNodeReq; +import com.tencent.bk.job.file.worker.artifactory.model.req.DeleteRepoReq; +import com.tencent.bk.job.file.worker.artifactory.model.req.DownloadGenericFileReq; +import com.tencent.bk.job.file.worker.artifactory.model.req.ListNodePageReq; +import com.tencent.bk.job.file.worker.artifactory.model.req.ListProjectReq; +import com.tencent.bk.job.file.worker.artifactory.model.req.ListRepoPageReq; +import com.tencent.bk.job.file.worker.artifactory.model.req.QueryNodeDetailReq; import com.tencent.bk.job.file.worker.cos.service.RemoteClient; import com.tencent.bk.job.file.worker.model.FileMetaData; import io.micrometer.core.instrument.MeterRegistry; @@ -52,11 +63,13 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; @Slf4j public class ArtifactoryRemoteClient implements RemoteClient { + public static final String URL_ACTUATOR_INFO = "/repository/actuator/info"; public static final String URL_LIST_PROJECT = "/repository/api/project/list"; public static final String URL_LIST_REPO_PAGE = "/repository/api/repo/page/{projectId}/{pageNumber}/{pageSize}"; public static final String URL_LIST_NODE_PAGE = "/repository/api/node/page/{projectId}/{repoName}/{fullPath}"; @@ -154,34 +167,36 @@ private R getArtifactoryRespByReq( log.debug("success|method={}|url={}|reqStr={}|respStr={}", method, url, reqStr, respStr); } R result = JsonUtils.fromJson(respStr, typeReference); - ArtifactoryResp artifactoryResp = (ArtifactoryResp) result; - if (artifactoryResp == null) { - log.error("fail:artifactoryResp is null after parse|method={}|url={}|reqStr={}|respStr={}", method, - url, reqStr, respStr); - status = "error"; - throw new ServiceException(ErrorCode.ARTIFACTORY_API_DATA_ERROR, "artifactoryResp is null after parse"); - } else if (artifactoryResp.getCode() != ArtifactoryInterfaceConsts.RESULT_CODE_OK) { - log.error( - "fail:artifactoryResp code!={}|artifactoryResp.requestId={}|artifactoryResp" + - ".code={}|artifactoryResp.message={}|method={}|url={}|reqStr={}|respStr={}" - , ArtifactoryInterfaceConsts.RESULT_CODE_OK - , artifactoryResp.getTraceId() - , artifactoryResp.getCode() - , artifactoryResp.getMessage() - , method, url, reqStr, respStr - ); - status = "error"; - throw new ServiceException(ErrorCode.ARTIFACTORY_API_DATA_ERROR, "artifactoryResp code!=0"); - } - if (artifactoryResp.getData() == null) { - log.warn( - "warn:artifactoryResp.getData() == null|artifactoryResp.requestId={}|artifactoryResp" + - ".code={}|artifactoryResp.message={}|method={}|url={}|reqStr={}|respStr={}" - , artifactoryResp.getTraceId() - , artifactoryResp.getCode() - , artifactoryResp.getMessage() - , method, url, reqStr, respStr - ); + if (result instanceof ArtifactoryResp) { + ArtifactoryResp artifactoryResp = (ArtifactoryResp) result; + if (artifactoryResp == null) { + log.error("fail:artifactoryResp is null after parse|method={}|url={}|reqStr={}|respStr={}", method, + url, reqStr, respStr); + status = "error"; + throw new ServiceException(ErrorCode.ARTIFACTORY_API_DATA_ERROR, "artifactoryResp is null after parse"); + } else if (artifactoryResp.getCode() != ArtifactoryInterfaceConsts.RESULT_CODE_OK) { + log.error( + "fail:artifactoryResp code!={}|artifactoryResp.requestId={}|artifactoryResp" + + ".code={}|artifactoryResp.message={}|method={}|url={}|reqStr={}|respStr={}" + , ArtifactoryInterfaceConsts.RESULT_CODE_OK + , artifactoryResp.getTraceId() + , artifactoryResp.getCode() + , artifactoryResp.getMessage() + , method, url, reqStr, respStr + ); + status = "error"; + throw new ServiceException(ErrorCode.ARTIFACTORY_API_DATA_ERROR, "artifactoryResp code!=0"); + } + if (artifactoryResp.getData() == null) { + log.warn( + "warn:artifactoryResp.getData() == null|artifactoryResp.requestId={}|artifactoryResp" + + ".code={}|artifactoryResp.message={}|method={}|url={}|reqStr={}|respStr={}" + , artifactoryResp.getTraceId() + , artifactoryResp.getCode() + , artifactoryResp.getMessage() + , method, url, reqStr, respStr + ); + } } status = "ok"; return result; @@ -198,10 +213,21 @@ private R getArtifactoryRespByReq( } } + public boolean isAvailable() { + try { + getArtifactoryRespByReq(HttpGet.METHOD_NAME, URL_ACTUATOR_INFO, + new ArtifactoryReq(), new TypeReference>() { + }, httpHelper); + return true; + } catch (Throwable t) { + return false; + } + } + public List listProject() { ArtifactoryResp> resp = getArtifactoryRespByReq(HttpGet.METHOD_NAME, URL_LIST_PROJECT, new ListProjectReq(), new TypeReference>>() { - }, httpHelper); + }, httpHelper); return resp.getData(); } @@ -213,7 +239,7 @@ public PageData listRepo(String projectId, String name, int pageNumber, req.setPageSize(pageSize); ArtifactoryResp> resp = getArtifactoryRespByReq(HttpGet.METHOD_NAME, URL_LIST_REPO_PAGE, req, new TypeReference>>() { - }, httpHelper); + }, httpHelper); return resp.getData(); } @@ -227,7 +253,7 @@ public PageData listNode(String projectId, String repoName, String full req.setPageSize(pageSize); ArtifactoryResp> resp = getArtifactoryRespByReq(HttpGet.METHOD_NAME, URL_LIST_NODE_PAGE, req, new TypeReference>>() { - }, httpHelper); + }, httpHelper); return resp.getData(); } @@ -238,7 +264,7 @@ public NodeDTO queryNodeDetail(String projectId, String repoName, String fullPat req.setFullPath(fullPath); ArtifactoryResp resp = getArtifactoryRespByReq(HttpGet.METHOD_NAME, URL_QUERY_NODE_DETAIL, req, new TypeReference>() { - }, httpHelper); + }, httpHelper); return resp.getData(); } @@ -253,7 +279,7 @@ public Boolean deleteRepo(String projectId, String repoName, Boolean forced) { req.setForced(forced); ArtifactoryResp resp = getArtifactoryRespByReq(HttpDelete.METHOD_NAME, URL_DELETE_REPO, req, new TypeReference>() { - }, httpHelper); + }, httpHelper); return resp.getCode() == 0; } @@ -264,7 +290,7 @@ public Boolean deleteNode(String projectId, String repoName, String fullPath) { req.setFullPath(fullPath); ArtifactoryResp resp = getArtifactoryRespByReq(HttpDelete.METHOD_NAME, URL_DELETE_NODE, req, new TypeReference>() { - }, httpHelper); + }, httpHelper); return resp.getCode() == 0; } diff --git a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/impl/COSFileResourceImpl.java b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/impl/COSFileResourceImpl.java index 84a5afa26b..0446d8c032 100644 --- a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/impl/COSFileResourceImpl.java +++ b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/impl/COSFileResourceImpl.java @@ -24,7 +24,6 @@ package com.tencent.bk.job.file.worker.cos.impl; -import com.fasterxml.jackson.core.type.TypeReference; import com.tencent.bk.job.common.constant.ErrorCode; import com.tencent.bk.job.common.exception.ServiceException; import com.tencent.bk.job.common.model.ServiceResponse; @@ -32,7 +31,6 @@ import com.tencent.bk.job.common.util.StringUtil; import com.tencent.bk.job.common.util.date.DateUtils; import com.tencent.bk.job.common.util.file.PathUtil; -import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.file.worker.api.IFileResource; import com.tencent.bk.job.file.worker.cos.JobTencentInnerCOSClient; import com.tencent.bk.job.file.worker.cos.consts.COSActionCodeEnum; @@ -48,7 +46,6 @@ import com.tencent.bk.job.file.worker.model.req.ListFileNodeReq; import com.tencent.bk.job.file_gateway.model.resp.common.FileNodesDTO; import com.tencent.bk.job.file_gateway.model.resp.common.FileTreeNodeDef; -import com.tencent.bk.job.file_gateway.model.resp.common.FileVO; import com.tencent.cos.model.Bucket; import com.tencent.cos.model.COSObjectSummary; import io.micrometer.core.instrument.util.StringUtils; @@ -207,6 +204,21 @@ public RemoteClient getRemoteClient(BaseReq req) { return new COSRemoteClient(jobTencentInnerCOSClient); } + @Override + public ServiceResponse isFileAvailable(BaseReq req) { + try { + ListFileNodeReq listFileNodeReq = new ListFileNodeReq(req); + listFileNodeReq.setPath(""); + listFileNodeReq.setName(""); + listFileNodeReq.setStart(0); + listFileNodeReq.setPageSize(1); + listBucket(listFileNodeReq); + return ServiceResponse.buildSuccessResp(true); + } catch (Throwable t) { + return ServiceResponse.buildSuccessResp(false); + } + } + private String getTypeFromFileName(String fileName) { if (StringUtils.isBlank(fileName)) { return "UNKNOWN"; @@ -233,39 +245,6 @@ private Boolean isDir(String fileName) { return fileName.endsWith("/"); } - private List parseBucketFileList(String bucketName, String path, String respStr) { - ServiceResponse> resp = null; - if (path == null) { - path = ""; - } - try { - resp = JsonUtils.fromJson(respStr, new TypeReference>>() { - }); - } catch (Exception e) { - log.error("Fail to parse bucket file from response={}", respStr, e); - throw new ServiceException(ErrorCode.FAIL_TO_REQUEST_FILE_WORKER_LIST_OBJECTS, resp.getErrorMsg()); - } - if (resp.isSuccess()) { - List fileVOList = new ArrayList<>(); - List fileDTOList = resp.getData(); - for (FileDTO fileDTO : fileDTOList) { - FileVO fileVO = new FileVO(); - fileVO.setName(fileDTO.getKey()); - fileVO.setCompletePath(bucketName + "/" + path + fileDTO.getKey()); - fileVO.setSize(fileDTO.getSize()); - fileVO.setDir(isDir(fileDTO.getKey())); - fileVO.setType(getTypeFromFileName(fileDTO.getKey())); - fileVO.setDownloadUrl(fileDTO.getDownloadUrl()); - fileVO.setLastModifyTime(fileDTO.getLastModified()); - fileVOList.add(fileVO); - } - return fileVOList; - } else { - log.error("get failed bucket file response={}", respStr); - throw new ServiceException(resp.getCode(), resp.getErrorMsg()); - } - } - private int getSlashNum(String str) { if (StringUtils.isBlank(str)) return 0; int count = 0; @@ -342,7 +321,7 @@ private void fillFileFileNodesDTO(FileNodesDTO fileNodesDTO, ListFileNodeReq req Map map = new HashMap<>(); String fileName = fileDTO.getKey(); map.put("name", fileName); - map.put("type", "文本文件"); + map.put("type", getTypeFromFileName(fileName)); map.put("updateTime", DateUtils.formatUnixTimestamp(fileDTO.getLastModified(), ChronoUnit.MILLIS)); map.put("completePath", PathUtil.joinFilePath(req.getPath(), fileName)); map.put("dir", isDir(fileName)); diff --git a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/service/COSBaseService.java b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/service/COSBaseService.java index c9c9402d6d..53059afced 100644 --- a/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/service/COSBaseService.java +++ b/src/backend/job-file-worker/service-job-file-worker/src/main/java/com/tencent/bk/job/file/worker/cos/service/COSBaseService.java @@ -26,25 +26,28 @@ import com.tencent.bk.job.file.worker.cos.JobTencentInnerCOSClient; import com.tencent.bk.job.file.worker.model.req.BaseReq; -import com.tencent.bk.job.ticket.model.credential.CommonCredentialDTO; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.Map; +@Slf4j @Service public class COSBaseService { public JobTencentInnerCOSClient getCOSClientFromBaseReq(BaseReq req) { // endPointDomain // appId - CommonCredentialDTO credential = req.getCredential(); + CommonCredential credential = req.getCredential(); Map fileSourceInfoMap = req.getFileSourceInfoMap(); + log.debug("req={}", req); return new JobTencentInnerCOSClient(credential.getAccessKey(), credential.getSecretKey(), - getEndPointDomain(req), fileSourceInfoMap.get("appId").toString()); + getEndPointDomain(req), fileSourceInfoMap.get("app_id").toString()); } public String getEndPointDomain(BaseReq req) { Map fileSourceInfoMap = req.getFileSourceInfoMap(); - return (String) (fileSourceInfoMap.get("endPointDomain")); + return (String) (fileSourceInfoMap.get("end_point_domain")); } } diff --git a/src/backend/job-gateway/build.gradle b/src/backend/job-gateway/build.gradle index 7de4a162cc..a7fc72b557 100644 --- a/src/backend/job-gateway/build.gradle +++ b/src/backend/job-gateway/build.gradle @@ -72,3 +72,11 @@ test { useJUnitPlatform() } apply from: "$rootDir/task_job_package.gradle" +task copyToLatestJar(type: Copy) { + group = "local" + from('build/libs') + include "job-gateway-${version}.jar" + destinationDir file('build/libs/') + rename "job-gateway-${version}.jar", "job-gateway.jar" +} +copyToLatestJar.dependsOn assemble diff --git a/src/backend/job-gateway/src/main/resources/application.yml b/src/backend/job-gateway/src/main/resources/application.yml index e47c50effd..72bc9f56d1 100644 --- a/src/backend/job-gateway/src/main/resources/application.yml +++ b/src/backend/job-gateway/src/main/resources/application.yml @@ -148,6 +148,16 @@ spring: - RecordEsbAccessLog - AddEsbLangHeader + - id: job-file-gateway-esb-v3 + uri: lb://job-file-gateway + predicates: + - JobEsbV2Path=/api/job/v3/job-file-gateway/{api_name} + filters: + - CheckEsbJwt + - SetPath=/esb/api/v3/{api_name} + - RecordEsbAccessLog + - AddEsbLangHeader + - id: job-file-gateway-iam uri: lb://job-file-gateway predicates: diff --git a/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/v3/EsbCredentialV3Resource.java b/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/v3/EsbCredentialV3Resource.java new file mode 100644 index 0000000000..8776ae0df4 --- /dev/null +++ b/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/v3/EsbCredentialV3Resource.java @@ -0,0 +1,52 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.manage.api.esb.v3; + +import com.tencent.bk.job.common.annotation.EsbAPI; +import com.tencent.bk.job.common.esb.model.EsbResp; +import com.tencent.bk.job.manage.model.esb.v3.request.EsbCreateOrUpdateCredentialV3Req; +import com.tencent.bk.job.manage.model.esb.v3.response.EsbCredentialSimpleInfoV3DTO; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 凭据API-V3 + */ +@RequestMapping("/esb/api/v3") +@RestController +@EsbAPI +public interface EsbCredentialV3Resource { + + @PostMapping("/create_credential") + EsbResp createCredential( + @RequestBody EsbCreateOrUpdateCredentialV3Req req); + + @PostMapping("/update_credential") + EsbResp updateCredential( + @RequestBody EsbCreateOrUpdateCredentialV3Req req); + +} diff --git a/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/model/esb/v3/request/EsbCreateOrUpdateCredentialV3Req.java b/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/model/esb/v3/request/EsbCreateOrUpdateCredentialV3Req.java new file mode 100644 index 0000000000..594011defa --- /dev/null +++ b/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/model/esb/v3/request/EsbCreateOrUpdateCredentialV3Req.java @@ -0,0 +1,87 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.manage.model.esb.v3.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tencent.bk.job.common.esb.model.EsbReq; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 新建凭据请求 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class EsbCreateOrUpdateCredentialV3Req extends EsbReq { + /** + * 业务ID + */ + @JsonProperty("bk_biz_id") + private Long appId; + + /** + * 凭据ID + */ + private String id; + + /** + * 凭据名称 + */ + private String name; + + /** + * 凭据类型 + */ + private String type; + + /** + * 描述 + */ + private String description; + + /** + * AccessKey + */ + @JsonProperty("credential_access_key") + private String credentialAccessKey; + + /** + * SecretKey + */ + @JsonProperty("credential_secret_key") + private String credentialSecretKey; + + /** + * Username + */ + @JsonProperty("credential_username") + private String credentialUsername; + + /** + * Password + */ + @JsonProperty("credential_password") + private String credentialPassword; +} diff --git a/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/model/esb/v3/response/EsbCredentialSimpleInfoV3DTO.java b/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/model/esb/v3/response/EsbCredentialSimpleInfoV3DTO.java new file mode 100644 index 0000000000..f119357a6d --- /dev/null +++ b/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/model/esb/v3/response/EsbCredentialSimpleInfoV3DTO.java @@ -0,0 +1,38 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.manage.model.esb.v3.response; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class EsbCredentialSimpleInfoV3DTO { + + private String id; + +} diff --git a/src/backend/job-manage/service-job-manage/build.gradle b/src/backend/job-manage/service-job-manage/build.gradle index 40da634964..6b5e5cdf57 100644 --- a/src/backend/job-manage/service-job-manage/build.gradle +++ b/src/backend/job-manage/service-job-manage/build.gradle @@ -30,6 +30,7 @@ dependencies { compile project(":job-manage:model-job-manage") compile project(":job-crontab:api-job-crontab") compile project(":job-analysis:api-job-analysis") + compile project(":job-ticket:api-job-ticket") compile project(":commons:common") compile project(":commons:common-security") compile project(":commons:common-redis") diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/v3/EsbCredentialResourceV3Impl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/v3/EsbCredentialResourceV3Impl.java new file mode 100644 index 0000000000..ad3b8f5d9f --- /dev/null +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/v3/EsbCredentialResourceV3Impl.java @@ -0,0 +1,162 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.manage.api.esb.impl.v3; + +import com.tencent.bk.job.common.esb.model.EsbResp; +import com.tencent.bk.job.common.exception.InvalidParamException; +import com.tencent.bk.job.common.i18n.service.MessageI18nService; +import com.tencent.bk.job.common.iam.service.AuthService; +import com.tencent.bk.job.common.web.model.InnerServiceResponse; +import com.tencent.bk.job.manage.api.esb.v3.EsbCredentialV3Resource; +import com.tencent.bk.job.manage.client.ServiceCredentialResourceClient; +import com.tencent.bk.job.manage.model.esb.v3.request.EsbCreateOrUpdateCredentialV3Req; +import com.tencent.bk.job.manage.model.esb.v3.response.EsbCredentialSimpleInfoV3DTO; +import com.tencent.bk.job.ticket.consts.CredentialTypeEnum; +import com.tencent.bk.job.ticket.model.inner.resp.ServiceBasicCredentialDTO; +import com.tencent.bk.job.ticket.model.web.req.CredentialCreateUpdateReq; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RestController; + +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.APP_ID_SECRET_KEY; +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.PASSWORD; +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.SECRET_KEY; +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.USERNAME_PASSWORD; + +@RestController +@Slf4j +public class EsbCredentialResourceV3Impl implements EsbCredentialV3Resource { + private final ServiceCredentialResourceClient credentialService; + private final AuthService authService; + private final MessageI18nService i18nService; + + @Autowired + public EsbCredentialResourceV3Impl(ServiceCredentialResourceClient credentialService, AuthService authService, MessageI18nService i18nService) { + this.credentialService = credentialService; + this.authService = authService; + this.i18nService = i18nService; + } + + @Override + public EsbResp createCredential(EsbCreateOrUpdateCredentialV3Req req) { + checkCreateParam(req); + return saveCredential(req); + } + + @Override + public EsbResp updateCredential(EsbCreateOrUpdateCredentialV3Req req) { + checkUpdateParam(req); + return saveCredential(req); + } + + private void checkAppId(Long appId) { + if (appId == null) { + throw new InvalidParamException("bk_biz_id", "bk_biz_id cannot be null"); + } + } + + private void checkCreateParam(EsbCreateOrUpdateCredentialV3Req req) { + checkAppId(req.getAppId()); + String name = req.getName(); + String type = req.getType(); + if (StringUtils.isBlank(name)) { + throw new InvalidParamException("name", "name cannot be null or blank"); + } + if (StringUtils.isBlank(type)) { + throw new InvalidParamException("type", "type cannot be null or blank"); + } + } + + private void checkUpdateParam(EsbCreateOrUpdateCredentialV3Req req) { + checkAppId(req.getAppId()); + if (StringUtils.isBlank(req.getId())) { + throw new InvalidParamException("id", "id cannot be null or blank"); + } + } + + private EsbResp saveCredential(EsbCreateOrUpdateCredentialV3Req req) { + CredentialCreateUpdateReq createUpdateReq = convertToCreateUpdateReq(req); + InnerServiceResponse resp; + if (req.getId() == null) { + resp = credentialService.createCredential( + req.getUserName(), + req.getAppId(), + createUpdateReq + ); + } else { + resp = credentialService.updateCredential( + req.getUserName(), + req.getAppId(), + createUpdateReq + ); + } + if (resp.getAuthResult() != null) { + return authService.buildEsbAuthFailResp( + resp.getAuthResult().getRequiredActionResources() + ); + } else if (!resp.isSuccess()) { + return EsbResp.buildCommonFailResp( + resp.getCode(), + resp.getErrorDetail(), + i18nService + ); + } + ServiceBasicCredentialDTO data = resp.getData(); + return EsbResp.buildSuccessResp(new EsbCredentialSimpleInfoV3DTO(data.getId())); + } + + private CredentialCreateUpdateReq convertToCreateUpdateReq( + EsbCreateOrUpdateCredentialV3Req req + ) { + String type = req.getType(); + CredentialCreateUpdateReq createUpdateReq = new CredentialCreateUpdateReq(); + createUpdateReq.setId(req.getId()); + createUpdateReq.setName(req.getName()); + createUpdateReq.setType(CredentialTypeEnum.valueOf(req.getType())); + createUpdateReq.setDescription(req.getDescription()); + if (SECRET_KEY.name().equals(type)) { + createUpdateReq.setValue1(req.getCredentialSecretKey()); + } else if (PASSWORD.name().equals(type)) { + createUpdateReq.setValue1(req.getCredentialPassword()); + } else if (APP_ID_SECRET_KEY.name().equals(type)) { + createUpdateReq.setValue1(req.getCredentialAccessKey()); + createUpdateReq.setValue2(req.getCredentialSecretKey()); + } else if (USERNAME_PASSWORD.name().equals(type)) { + createUpdateReq.setValue1(req.getCredentialUsername()); + createUpdateReq.setValue2(req.getCredentialPassword()); + } else { + throw new InvalidParamException( + "type", + String.format( + "Unsupported type:%s, supported types:%s", + type, + CredentialTypeEnum.getAllNameStr() + ) + ); + } + return createUpdateReq; + } +} diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/client/ServiceCredentialResourceClient.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/client/ServiceCredentialResourceClient.java new file mode 100644 index 0000000000..a877e724ba --- /dev/null +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/client/ServiceCredentialResourceClient.java @@ -0,0 +1,35 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.manage.client; + +import com.tencent.bk.job.ticket.api.inner.ServiceCredentialResource; +import org.springframework.cloud.openfeign.FeignClient; + +/** + * 凭据服务内部接口远程调用客户端 + */ +@FeignClient(value = "job-ticket", contextId = "credential") +public interface ServiceCredentialResourceClient extends ServiceCredentialResource { +} diff --git a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/consts/CredentialTypeEnum.java b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/consts/CredentialTypeEnum.java index d0caf0cad3..1d37b6b9ba 100644 --- a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/consts/CredentialTypeEnum.java +++ b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/consts/CredentialTypeEnum.java @@ -31,10 +31,22 @@ public enum CredentialTypeEnum { SECRET_KEY(4, "单一SecretKey"); private final Integer value; - private final String name; + private final String description; - CredentialTypeEnum(Integer type, String name) { + public static String getAllNameStr() { + StringBuilder sb = new StringBuilder(); + CredentialTypeEnum[] values = CredentialTypeEnum.values(); + for (int i = 0; i < values.length; i++) { + sb.append(values[i].name()); + if (i < values.length - 1) { + sb.append(","); + } + } + return sb.toString(); + } + + CredentialTypeEnum(Integer type, String description) { this.value = type; - this.name = name; + this.description = description; } } diff --git a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/credential/CommonCredentialDTO.java b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/credential/CommonCredential.java similarity index 98% rename from src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/credential/CommonCredentialDTO.java rename to src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/credential/CommonCredential.java index 875c725fe7..8e3c71a321 100644 --- a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/credential/CommonCredentialDTO.java +++ b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/credential/CommonCredential.java @@ -33,7 +33,7 @@ @AllArgsConstructor @Data @EqualsAndHashCode -public class CommonCredentialDTO { +public class CommonCredential { String accessKey; String secretKey; String username; diff --git a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/inner/resp/ServiceBasicCredentialDTO.java b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/inner/resp/ServiceBasicCredentialDTO.java new file mode 100644 index 0000000000..cd21b182cb --- /dev/null +++ b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/inner/resp/ServiceBasicCredentialDTO.java @@ -0,0 +1,43 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * 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.bk.job.ticket.model.inner.resp; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel("凭据基本信息") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ServiceBasicCredentialDTO { + /** + * 主键Id + */ + @ApiModelProperty("主键Id") + private String id; +} diff --git a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/inner/resp/ServiceCredentialDTO.java b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/inner/resp/ServiceCredentialDTO.java index 081a6f877f..1fa62554f3 100644 --- a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/inner/resp/ServiceCredentialDTO.java +++ b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/inner/resp/ServiceCredentialDTO.java @@ -24,6 +24,7 @@ package com.tencent.bk.job.ticket.model.inner.resp; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -52,8 +53,8 @@ public class ServiceCredentialDTO { @ApiModelProperty("类型") private String type; /** - * 值 + * 凭据 */ - @ApiModelProperty("值") - private String value; + @ApiModelProperty("凭据") + private CommonCredential credential; } diff --git a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/web/req/CredentialCreateUpdateReq.java b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/web/req/CredentialCreateUpdateReq.java index e116e22d86..b5f0dcffa3 100644 --- a/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/web/req/CredentialCreateUpdateReq.java +++ b/src/backend/job-ticket/api-job-ticket-pojo/src/main/java/com/tencent/bk/job/ticket/model/web/req/CredentialCreateUpdateReq.java @@ -24,20 +24,19 @@ package com.tencent.bk.job.ticket.model.web.req; -import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.ticket.consts.CredentialTypeEnum; -import com.tencent.bk.job.ticket.model.credential.AccessKeySecretKey; -import com.tencent.bk.job.ticket.model.credential.Password; -import com.tencent.bk.job.ticket.model.credential.SecretKey; -import com.tencent.bk.job.ticket.model.credential.UsernamePassword; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.*; +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.APP_ID_SECRET_KEY; +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.PASSWORD; +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.SECRET_KEY; +import static com.tencent.bk.job.ticket.consts.CredentialTypeEnum.USERNAME_PASSWORD; @Data -@ApiModel("凭据创建请求") +@ApiModel("凭据创建/更新请求") public class CredentialCreateUpdateReq { @ApiModelProperty(value = "ID,更新凭据的时候需要传入,新建时不需要", required = false) @@ -73,21 +72,22 @@ public class CredentialCreateUpdateReq { @ApiModelProperty("值3") private String value3; - public String getSerializedValue() { + public CommonCredential toCommonCredential() { + CommonCredential credential = new CommonCredential(); + credential.setType(type.name()); if (type == SECRET_KEY) { - SecretKey secretKey = new SecretKey(value1); - return JsonUtils.toJson(secretKey); + credential.setSecretKey(value1); } else if (type == PASSWORD) { - Password password = new Password(value1); - return JsonUtils.toJson(password); + credential.setPassword(value1); } else if (type == APP_ID_SECRET_KEY) { - AccessKeySecretKey accessKeySecretKey = new AccessKeySecretKey(value1, value2); - return JsonUtils.toJson(accessKeySecretKey); + credential.setAccessKey(value1); + credential.setSecretKey(value2); } else if (type == USERNAME_PASSWORD) { - UsernamePassword usernamePassword = new UsernamePassword(value1, value2); - return JsonUtils.toJson(usernamePassword); + credential.setUsername(value1); + credential.setPassword(value2); } else { return null; } + return credential; } } diff --git a/src/backend/job-ticket/api-job-ticket/build.gradle b/src/backend/job-ticket/api-job-ticket/build.gradle index d656e92f79..32fbc72ace 100644 --- a/src/backend/job-ticket/api-job-ticket/build.gradle +++ b/src/backend/job-ticket/api-job-ticket/build.gradle @@ -25,6 +25,7 @@ dependencies { compile project(':commons:common') compile project(':commons:common-iam') + compile project(':commons:common-web') compile project(':job-ticket:api-job-ticket-pojo') implementation "org.springframework:spring-web" implementation "javax.ws.rs:javax.ws.rs-api" diff --git a/src/backend/job-ticket/api-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResource.java b/src/backend/job-ticket/api-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResource.java index 736b342de2..a5b0c6fb21 100644 --- a/src/backend/job-ticket/api-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResource.java +++ b/src/backend/job-ticket/api-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResource.java @@ -26,12 +26,19 @@ import com.tencent.bk.job.common.annotation.InternalAPI; import com.tencent.bk.job.common.model.ServiceResponse; +import com.tencent.bk.job.common.web.model.InnerServiceResponse; +import com.tencent.bk.job.ticket.model.inner.resp.ServiceBasicCredentialDTO; import com.tencent.bk.job.ticket.model.inner.resp.ServiceCredentialDTO; +import com.tencent.bk.job.ticket.model.web.req.CredentialCreateUpdateReq; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -50,4 +57,30 @@ ServiceResponse getCredentialById( @PathVariable("id") String id ); + + @ApiOperation(value = "新建凭据", produces = "application/json") + @PostMapping("/create") + InnerServiceResponse createCredential( + @ApiParam(value = "用户名,网关自动传入", required = true) + @RequestHeader("username") + String username, + @ApiParam(value = "业务ID", required = true) + @PathVariable("appId") Long appId, + @ApiParam(value = "创建或更新请求体", required = true) + @RequestBody + CredentialCreateUpdateReq createUpdateReq + ); + + @ApiOperation(value = "更新凭据", produces = "application/json") + @PutMapping("/update") + InnerServiceResponse updateCredential( + @ApiParam(value = "用户名,网关自动传入", required = true) + @RequestHeader("username") + String username, + @ApiParam(value = "业务ID", required = true) + @PathVariable("appId") Long appId, + @ApiParam(value = "创建或更新请求体", required = true) + @RequestBody + CredentialCreateUpdateReq createUpdateReq + ); } diff --git a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResourceImpl.java b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResourceImpl.java index 5163856bc6..903622bb9f 100644 --- a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResourceImpl.java +++ b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/api/inner/ServiceCredentialResourceImpl.java @@ -24,10 +24,19 @@ package com.tencent.bk.job.ticket.api.inner; +import com.tencent.bk.job.common.iam.constant.ActionId; +import com.tencent.bk.job.common.iam.constant.ResourceTypeEnum; +import com.tencent.bk.job.common.iam.model.AuthResult; +import com.tencent.bk.job.common.iam.service.AuthService; import com.tencent.bk.job.common.model.ServiceResponse; +import com.tencent.bk.job.common.web.model.InnerServiceResponse; +import com.tencent.bk.job.ticket.model.inner.resp.ServiceBasicCredentialDTO; import com.tencent.bk.job.ticket.model.inner.resp.ServiceCredentialDTO; +import com.tencent.bk.job.ticket.model.web.req.CredentialCreateUpdateReq; import com.tencent.bk.job.ticket.service.CredentialService; +import com.tencent.bk.sdk.iam.util.PathBuilder; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RestController; @@ -36,10 +45,12 @@ @Slf4j public class ServiceCredentialResourceImpl implements ServiceCredentialResource { + private final AuthService authService; private final CredentialService credentialService; @Autowired - public ServiceCredentialResourceImpl(CredentialService credentialService) { + public ServiceCredentialResourceImpl(AuthService authService, CredentialService credentialService) { + this.authService = authService; this.credentialService = credentialService; } @@ -48,4 +59,52 @@ public ServiceResponse getCredentialById(Long appId, Strin ServiceCredentialDTO serviceCredentialDTO = credentialService.getServiceCredentialById(appId, id); return ServiceResponse.buildSuccessResp(serviceCredentialDTO); } + + @Override + public InnerServiceResponse createCredential( + String username, + Long appId, + CredentialCreateUpdateReq createUpdateReq + ) { + return saveCredential(username, appId, createUpdateReq); + } + + @Override + public InnerServiceResponse updateCredential( + String username, + Long appId, + CredentialCreateUpdateReq createUpdateReq + ) { + return saveCredential(username, appId, createUpdateReq); + } + + private InnerServiceResponse saveCredential( + String username, + Long appId, + CredentialCreateUpdateReq createUpdateReq + ) { + AuthResult authResult = null; + if (StringUtils.isBlank(createUpdateReq.getId())) { + authResult = checkCreateTicketPermission(username, appId); + } else { + authResult = checkManageTicketPermission(username, appId, createUpdateReq.getId()); + } + if (!authResult.isPass()) { + return InnerServiceResponse.buildAuthFailResp(authResult); + } + String credentialId = credentialService.saveCredential(username, appId, createUpdateReq); + return InnerServiceResponse.buildSuccessResp(new ServiceBasicCredentialDTO(credentialId)); + } + + public AuthResult checkCreateTicketPermission(String username, Long appId) { + // 需要拥有在业务下创建凭证的权限 + return authService.auth(true, username, ActionId.CREATE_TICKET, ResourceTypeEnum.BUSINESS, + appId.toString(), null); + } + + public AuthResult checkManageTicketPermission(String username, Long appId, String credentialId) { + // 需要拥有在业务下管理某个具体凭证的权限 + return authService.auth(true, username, ActionId.MANAGE_TICKET, ResourceTypeEnum.TICKET, + credentialId, PathBuilder.newBuilder(ResourceTypeEnum.BUSINESS.getId(), appId.toString()).build()); + } } diff --git a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/dao/impl/CredentialDAOImpl.java b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/dao/impl/CredentialDAOImpl.java index 5ab117b90d..cef7723fbc 100644 --- a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/dao/impl/CredentialDAOImpl.java +++ b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/dao/impl/CredentialDAOImpl.java @@ -24,16 +24,23 @@ package com.tencent.bk.job.ticket.dao.impl; +import com.fasterxml.jackson.core.type.TypeReference; import com.tencent.bk.job.common.util.Base64Util; import com.tencent.bk.job.common.util.JobUUID; import com.tencent.bk.job.common.util.crypto.AESUtils; +import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.ticket.config.JobTicketConfig; import com.tencent.bk.job.ticket.dao.CredentialDAO; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import com.tencent.bk.job.ticket.model.dto.CredentialDTO; import io.micrometer.core.instrument.util.StringUtils; import lombok.extern.slf4j.Slf4j; import lombok.val; -import org.jooq.*; +import org.jooq.Condition; +import org.jooq.DSLContext; +import org.jooq.Record10; +import org.jooq.Result; +import org.jooq.UpdateConditionStep; import org.jooq.conf.ParamType; import org.jooq.generated.tables.Credential; import org.jooq.generated.tables.records.CredentialRecord; @@ -80,8 +87,10 @@ public String insertCredential(DSLContext dslContext, CredentialDTO credentialDT credentialDTO.getName(), credentialDTO.getType(), credentialDTO.getDescription(), - AESUtils.encryptToBase64EncodedCipherText(credentialDTO.getValue(), - jobTicketConfig.getEncryptPassword()), + AESUtils.encryptToBase64EncodedCipherText( + JsonUtils.toJson(credentialDTO.getCredential()), + jobTicketConfig.getEncryptPassword() + ), credentialDTO.getCreator(), credentialDTO.getCreateTime(), credentialDTO.getLastModifyUser(), @@ -107,7 +116,8 @@ public String updateCredentialById(DSLContext dslContext, CredentialDTO credenti .set(defaultTable.NAME, credentialDTO.getName()) .set(defaultTable.TYPE, credentialDTO.getType()) .set(defaultTable.DESCRIPTION, credentialDTO.getDescription()) - .set(defaultTable.VALUE, AESUtils.encryptToBase64EncodedCipherText(credentialDTO.getValue(), + .set(defaultTable.VALUE, AESUtils.encryptToBase64EncodedCipherText( + JsonUtils.toJson(credentialDTO.getCredential()), jobTicketConfig.getEncryptPassword())) .set(defaultTable.LAST_MODIFY_USER, credentialDTO.getLastModifyUser()) .set(defaultTable.LAST_MODIFY_TIME, System.currentTimeMillis()) @@ -267,8 +277,8 @@ private Integer countCredentialByConditions(DSLContext dslContext, List record) { + private CredentialDTO convertRecordToDto( + Record10 record) { try { return new CredentialDTO( record.get(defaultTable.ID), @@ -276,8 +286,12 @@ private CredentialDTO convertRecordToDto(Record10() { + }), record.get(defaultTable.CREATOR), record.get(defaultTable.CREATE_TIME), record.get(defaultTable.LAST_MODIFY_USER), diff --git a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/model/dto/CredentialDTO.java b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/model/dto/CredentialDTO.java index b496cbcb5e..cc9a623c0b 100644 --- a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/model/dto/CredentialDTO.java +++ b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/model/dto/CredentialDTO.java @@ -24,12 +24,8 @@ package com.tencent.bk.job.ticket.model.dto; -import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.ticket.consts.CredentialTypeEnum; -import com.tencent.bk.job.ticket.model.credential.AccessKeySecretKey; -import com.tencent.bk.job.ticket.model.credential.Password; -import com.tencent.bk.job.ticket.model.credential.SecretKey; -import com.tencent.bk.job.ticket.model.credential.UsernamePassword; +import com.tencent.bk.job.ticket.model.credential.CommonCredential; import com.tencent.bk.job.ticket.model.inner.resp.ServiceCredentialDTO; import com.tencent.bk.job.ticket.model.web.resp.CredentialVO; import lombok.AllArgsConstructor; @@ -63,7 +59,7 @@ public class CredentialDTO { /** * 值JSON串 */ - private String value; + private CommonCredential credential; /** * 创建人 */ @@ -91,11 +87,9 @@ public CredentialVO toVO() { credentialVO.setValue2("******"); credentialVO.setValue3("******"); if (type.equals(CredentialTypeEnum.USERNAME_PASSWORD.name())) { - UsernamePassword usernamePassword = JsonUtils.fromJson(value, UsernamePassword.class); - credentialVO.setValue1(usernamePassword.getUsername()); + credentialVO.setValue1(credential.getUsername()); } else if (type.equals(CredentialTypeEnum.APP_ID_SECRET_KEY.name())) { - AccessKeySecretKey accessKeySecretKey = JsonUtils.fromJson(value, AccessKeySecretKey.class); - credentialVO.setValue1(accessKeySecretKey.getAccessKey()); + credentialVO.setValue1(credential.getAccessKey()); } credentialVO.setCreator(creator); credentialVO.setCreateTime(createTime); @@ -110,23 +104,19 @@ public ServiceCredentialDTO toServiceCredentialDTO() { serviceCredentialDTO.setAppId(appId); serviceCredentialDTO.setName(name); serviceCredentialDTO.setType(type); - serviceCredentialDTO.setValue(value); + serviceCredentialDTO.setCredential(credential); return serviceCredentialDTO; } public String getFirstValue() { if (type.equals(CredentialTypeEnum.USERNAME_PASSWORD.name())) { - UsernamePassword usernamePassword = JsonUtils.fromJson(this.value, UsernamePassword.class); - return usernamePassword.getUsername(); + return credential.getUsername(); } else if (type.equals(CredentialTypeEnum.PASSWORD.name())) { - Password password = JsonUtils.fromJson(this.value, Password.class); - return password.getPassword(); + return credential.getPassword(); } else if (type.equals(CredentialTypeEnum.SECRET_KEY.name())) { - SecretKey secretKey = JsonUtils.fromJson(this.value, SecretKey.class); - return secretKey.getSecretKey(); + return credential.getSecretKey(); } else if (type.equals(CredentialTypeEnum.APP_ID_SECRET_KEY.name())) { - AccessKeySecretKey accessKeySecretKey = JsonUtils.fromJson(this.value, AccessKeySecretKey.class); - return accessKeySecretKey.getAccessKey(); + return credential.getAccessKey(); } else { throw new RuntimeException("Not support type:" + type); } @@ -134,21 +124,13 @@ public String getFirstValue() { public void setFirstValue(String val) { if (type.equals(CredentialTypeEnum.USERNAME_PASSWORD.name())) { - UsernamePassword usernamePassword = JsonUtils.fromJson(this.value, UsernamePassword.class); - usernamePassword.setUsername(val); - this.value = JsonUtils.toJson(usernamePassword); + this.credential.setUsername(val); } else if (type.equals(CredentialTypeEnum.PASSWORD.name())) { - Password password = JsonUtils.fromJson(this.value, Password.class); - password.setPassword(val); - this.value = JsonUtils.toJson(password); + this.credential.setPassword(val); } else if (type.equals(CredentialTypeEnum.SECRET_KEY.name())) { - SecretKey secretKey = JsonUtils.fromJson(this.value, SecretKey.class); - secretKey.setSecretKey(val); - this.value = JsonUtils.toJson(secretKey); + this.credential.setSecretKey(val); } else if (type.equals(CredentialTypeEnum.APP_ID_SECRET_KEY.name())) { - AccessKeySecretKey accessKeySecretKey = JsonUtils.fromJson(this.value, AccessKeySecretKey.class); - accessKeySecretKey.setAccessKey(val); - this.value = JsonUtils.toJson(accessKeySecretKey); + this.credential.setAccessKey(val); } else { throw new RuntimeException("Not support type:" + type); } @@ -156,15 +138,13 @@ public void setFirstValue(String val) { public String getSecondValue() { if (type.equals(CredentialTypeEnum.USERNAME_PASSWORD.name())) { - UsernamePassword usernamePassword = JsonUtils.fromJson(this.value, UsernamePassword.class); - return usernamePassword.getPassword(); + return credential.getPassword(); } else if (type.equals(CredentialTypeEnum.PASSWORD.name())) { return null; } else if (type.equals(CredentialTypeEnum.SECRET_KEY.name())) { return null; } else if (type.equals(CredentialTypeEnum.APP_ID_SECRET_KEY.name())) { - AccessKeySecretKey accessKeySecretKey = JsonUtils.fromJson(this.value, AccessKeySecretKey.class); - return accessKeySecretKey.getSecretKey(); + return credential.getSecretKey(); } else { throw new RuntimeException("Not support type:" + type); } @@ -172,13 +152,9 @@ public String getSecondValue() { public void setSecondValue(String val) { if (type.equals(CredentialTypeEnum.USERNAME_PASSWORD.name())) { - UsernamePassword usernamePassword = JsonUtils.fromJson(this.value, UsernamePassword.class); - usernamePassword.setPassword(val); - this.value = JsonUtils.toJson(usernamePassword); + this.credential.setPassword(val); } else if (type.equals(CredentialTypeEnum.APP_ID_SECRET_KEY.name())) { - AccessKeySecretKey accessKeySecretKey = JsonUtils.fromJson(this.value, AccessKeySecretKey.class); - accessKeySecretKey.setSecretKey(val); - this.value = JsonUtils.toJson(accessKeySecretKey); + this.credential.setSecretKey(val); } else if (type.equals(CredentialTypeEnum.PASSWORD.name())) { } else if (type.equals(CredentialTypeEnum.SECRET_KEY.name())) { } else { diff --git a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/service/impl/CredentialServiceImpl.java b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/service/impl/CredentialServiceImpl.java index 097890cdb3..4e7747926b 100644 --- a/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/service/impl/CredentialServiceImpl.java +++ b/src/backend/job-ticket/service-job-ticket/src/main/java/com/tencent/bk/job/ticket/service/impl/CredentialServiceImpl.java @@ -153,7 +153,7 @@ private CredentialDTO buildCredentialDTO(String username, Long appId, Credential credentialDTO.setName(createUpdateReq.getName()); credentialDTO.setType(createUpdateReq.getType().name()); credentialDTO.setDescription(createUpdateReq.getDescription()); - credentialDTO.setValue(createUpdateReq.getSerializedValue()); + credentialDTO.setCredential(createUpdateReq.toCommonCredential()); credentialDTO.setLastModifyUser(username); credentialDTO.setLastModifyTime(System.currentTimeMillis()); return credentialDTO;