Skip to content

Commit

Permalink
Merge pull request #2864 from wangyu096/issue_2858
Browse files Browse the repository at this point in the history
feat: 容器执行支持 label selector 表达式 #2858
  • Loading branch information
jsonwan authored Apr 8, 2024
2 parents b39fad7 + fa886b7 commit e569f28
Show file tree
Hide file tree
Showing 54 changed files with 2,355 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,16 @@
| 字段 | 类型 | 必选 | 描述 |
|-----------|------------|--------|------------|
| pod_name_list | array || pod 名称列表 |
| label_selector | array || label 选择计算表达式列表,多个表达式之间为 AND 关系。表达式 见 label_select_expr 定义 |
| label_selector | array || Job 定义的label selector,由多个 Requirement 构成。多个 Requirement 之间为 AND 关系。表达式 见 requirement 定义 |
| label_selector_expr | string || k8s 官方定义的 label selector 表达式,[lable selector doc](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) |

##### label_select_expr
##### requirement

| 字段 | 类型 | 必选 | 描述 |
|-----------|------------|--------|------------|
| label_key | string || label key |
| operator | string || 计算操作符, 支持 equals、not_equals、in、not_in、exists |
| label_value | string || label value, 当计算操作符为 equals、not_equals 时候需要设置 |
| label_values | string || label value 列表, 当计算操作符为 in、not_in 时候需要设置 |
| key | string || label key |
| operator | string || 计算操作符, 支持 equals、not_equals、in、not_in、exists、not_exists |
| values | array || label value 列表, 当计算操作符为 in、not_in、equals、not_equals 时需要设置 |

##### kube_container_prop_filter

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ private Header[] getUploadFileHeaders() {
}

private String doHttpGet(String url, ArtifactoryReq reqBody, HttpHelper httpHelper) {
return httpHelper.request(
return httpHelper.requestForSuccessResp(
HttpRequest.builder(HttpMethodEnum.GET, reqBody == null ? url : url + reqBody.toUrlParams())
.setHeaders(getJsonHeaders())
.build())
.getEntity();
}

private String doHttpPost(String url, ArtifactoryReq reqBody, HttpHelper httpHelper) {
return httpHelper.request(
return httpHelper.requestForSuccessResp(
HttpRequest.builder(HttpMethodEnum.POST, url)
.setStringEntity(reqBody == null ? "{}" : JsonUtils.toJson(reqBody))
.setHeaders(getJsonHeaders())
Expand All @@ -191,7 +191,7 @@ private String doHttpPost(String url, ArtifactoryReq reqBody, HttpHelper httpHel
}

private String doHttpDelete(String url, ArtifactoryReq reqBody, HttpHelper httpHelper) {
return httpHelper.request(
return httpHelper.requestForSuccessResp(
HttpRequest.builder(HttpMethodEnum.DELETE, reqBody == null ? url : url + reqBody.toUrlParams())
.setStringEntity(reqBody == null ? "{}" : JsonUtils.toJson(reqBody))
.setHeaders(getJsonHeaders())
Expand Down Expand Up @@ -557,7 +557,7 @@ private NodeDTO uploadGenericFileWithEntity(
HttpMetricUtil.setHttpMetricName(CommonMetricNames.BKREPO_API_HTTP);
HttpMetricUtil.addTagForCurrentMetric(Tag.of("api_name", "upload:" + URL_UPLOAD_GENERIC_FILE));

respStr = longHttpHelper.request(
respStr = longHttpHelper.requestForSuccessResp(
HttpRequest.builder(HttpMethodEnum.PUT, url)
.setHttpEntity(reqEntity)
.setHeaders(getUploadFileHeaders())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,18 @@ public static BaseRuleDTO in(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.IN.getOperator(), value);
}

public static BaseRuleDTO notIn(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.NOT_IN.getOperator(), value);
}

public static BaseRuleDTO equals(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.EQUAL.getOperator(), value);
}

public static BaseRuleDTO notEquals(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.NOT_EQUAL.getOperator(), value);
}

public static BaseRuleDTO contains(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.CONTAINS.getOperator(), value);
}
Expand All @@ -73,5 +81,26 @@ public static BaseRuleDTO filterObject(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.FILTER_OBJECT.getOperator(), value);
}

public static BaseRuleDTO exists(String field) {
// cmdb 统一解析逻辑会解析value,没填的话会报错;传入 true(对过滤结果没有影响)临时规避该问题
return new BaseRuleDTO(field, RuleOperatorEnum.EXIST.getOperator(), true);
}

public static BaseRuleDTO notExists(String field) {
// cmdb 统一解析逻辑会解析value,没填的话会报错;传入 true(对过滤结果没有影响)临时规避该问题
return new BaseRuleDTO(field, RuleOperatorEnum.NOT_EXIST.getOperator(), true);
}

public static BaseRuleDTO greaterThan(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.GREATER.getOperator(), value);
}

public static BaseRuleDTO lessThan(String field, Object value) {
return new BaseRuleDTO(field, RuleOperatorEnum.LESS.getOperator(), value);
}

@Override
protected BaseRuleDTO clone() {
return new BaseRuleDTO(field, operator, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.tencent.bk.job.common.cc.model.container.PodDTO;
import com.tencent.bk.job.common.cc.model.filter.BaseRuleDTO;
import com.tencent.bk.job.common.cc.model.filter.ComposeRuleDTO;
import com.tencent.bk.job.common.cc.model.filter.IRule;
import com.tencent.bk.job.common.cc.model.filter.PropertyFilterDTO;
import com.tencent.bk.job.common.cc.model.filter.RuleConditionEnum;
import com.tencent.bk.job.common.cc.model.filter.RuleOperatorEnum;
Expand Down Expand Up @@ -1504,18 +1505,47 @@ public List<ContainerDetailDTO> listKubeContainerByTopo(ListKubeContainerByTopoR
setSupplierAccount(req);
req.setContainerFields(ContainerDTO.Fields.ALL);
req.setPodFields(PodDTO.Fields.ALL);
// 根据容器 ID 升序排列返回的数据,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
req.setPage(new Page(0, 500, ContainerDTO.Fields.ID));

return PageUtil.queryAllWithLoopPageQuery(
return PageUtil.queryAllWithLoopPageQueryInOrder(
500,
page -> {
req.setPage(new Page(page.getStart(), page.getLength()));
return listPageKubeContainerByTopo(req, false);
(ContainerDetailDTO latestElement) -> {
if (latestElement == null) {
// 第一页使用原始的请求
return req;
} else {
// 从第二页开始,需要构造 offset 条件,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
return buildNextPageListKubeContainerByTopoReq(req, latestElement.getContainer().getId());
}
},
pageReq -> listPageKubeContainerByTopo(pageReq, false),
PageData::getData,
container -> container
);
}

private ListKubeContainerByTopoReq buildNextPageListKubeContainerByTopoReq(
ListKubeContainerByTopoReq originReq,
long lastIdForCurrentPage
) {
ListKubeContainerByTopoReq nextPageReq = new ListKubeContainerByTopoReq();
nextPageReq.setPage(originReq.getPage());
nextPageReq.setNodeIdList(originReq.getNodeIdList());
nextPageReq.setPodFilter(originReq.getPodFilter());
nextPageReq.setBizId(originReq.getBizId());
nextPageReq.setBkSupplierAccount(originReq.getBkSupplierAccount());
nextPageReq.setPodFields(originReq.getPodFields());
nextPageReq.setContainerFields(originReq.getContainerFields());

// 添加 container ID 作为分页查询 offset 条件
PropertyFilterDTO rewriteContainerPropertyFilter = addRuleThenReCreate(originReq.getContainerFilter(),
BaseRuleDTO.greaterThan(KubeNamespaceDTO.Fields.ID, lastIdForCurrentPage));
nextPageReq.setContainerFilter(rewriteContainerPropertyFilter);

return nextPageReq;
}

private void setSupplierAccount(EsbReq esbReq) {
if (StringUtils.isEmpty(cmdbSupplierAccount)) {
esbReq.setBkSupplierAccount("0");
Expand Down Expand Up @@ -1606,27 +1636,49 @@ public List<KubeClusterDTO> listKubeClusters(KubeClusterQuery query) {
// 返回参数设置
req.setFields(KubeClusterDTO.Fields.ALL);

return PageUtil.queryAllWithLoopPageQuery(
// 根据集群 ID 升序排列返回的数据,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
req.setPage(new Page(0, 500, KubeClusterDTO.Fields.ID));

return PageUtil.queryAllWithLoopPageQueryInOrder(
500,
page -> {
req.setPage(new Page(page.getStart(), page.getLength()));
return listPage(
req,
false,
cmdbPageReq -> requestCmdbApi(
ApiGwType.BK_APIGW,
HttpMethodEnum.POST,
LIST_KUBE_CLUSTER,
null,
cmdbPageReq,
new TypeReference<EsbResp<BaseCcSearchResult<KubeClusterDTO>>>() {
}));
(KubeClusterDTO latestElement) -> {
if (latestElement == null) {
// 第一页使用原始的请求
return req;
} else {
// 从第二页开始,需要构造 offset 条件,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
return buildNextPageListKubeClusterReq(req, latestElement.getId());
}
},
PageData::getData,
cmdbPageReq -> requestCmdbApi(
ApiGwType.BK_APIGW,
HttpMethodEnum.POST,
LIST_KUBE_CLUSTER,
null,
cmdbPageReq,
new TypeReference<EsbResp<BaseCcSearchResult<KubeClusterDTO>>>() {
}),
resp -> resp.getData().getInfo(),
cluster -> cluster
);
}

private ListKubeClusterReq buildNextPageListKubeClusterReq(ListKubeClusterReq originReq,
long lastIdForCurrentPage) {
ListKubeClusterReq nextPageReq = new ListKubeClusterReq();
nextPageReq.setPage(originReq.getPage());
nextPageReq.setBizId(originReq.getBizId());
originReq.setFields(originReq.getFields());
nextPageReq.setBkSupplierAccount(originReq.getBkSupplierAccount());

// 添加 cluster ID 作为分页查询 offset 条件
PropertyFilterDTO rewritePropertyFilter = addRuleThenReCreate(originReq.getFilter(),
BaseRuleDTO.greaterThan(KubeClusterDTO.Fields.ID, lastIdForCurrentPage));
nextPageReq.setFilter(rewritePropertyFilter);

return nextPageReq;
}

private <R> PageData<R> listPage(CmdbPageReq req,
boolean withCount,
Function<CmdbPageReq, EsbResp<BaseCcSearchResult<R>>> query) {
Expand Down Expand Up @@ -1673,33 +1725,57 @@ public List<KubeNamespaceDTO> listKubeNamespaces(NamespaceQuery query) {
// 返回参数设置
req.setFields(KubeNamespaceDTO.Fields.ALL);

return PageUtil.queryAllWithLoopPageQuery(
// 根据 namespace ID 升序排列返回的数据,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
req.setPage(new Page(0, 500, KubeNamespaceDTO.Fields.ID));

return PageUtil.queryAllWithLoopPageQueryInOrder(
500,
page -> {
req.setPage(new Page(page.getStart(), page.getLength()));
return listPage(
req,
false,
cmdbPageReq -> requestCmdbApi(
ApiGwType.BK_APIGW,
HttpMethodEnum.POST,
LIST_KUBE_NAMESPACE,
null,
cmdbPageReq,
new TypeReference<EsbResp<BaseCcSearchResult<KubeNamespaceDTO>>>() {
}));
(KubeNamespaceDTO latestElement) -> {
if (latestElement == null) {
// 第一页使用原始的请求
return req;
} else {
// 从第二页开始,需要构造 offset 条件,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
return buildNextPageListKubeNamespaceReq(req, latestElement.getId());
}
},
PageData::getData,
cmdbPageReq -> requestCmdbApi(
ApiGwType.BK_APIGW,
HttpMethodEnum.POST,
LIST_KUBE_NAMESPACE,
null,
cmdbPageReq,
new TypeReference<EsbResp<BaseCcSearchResult<KubeNamespaceDTO>>>() {
}),
resp -> resp.getData().getInfo(),
namespace -> namespace
);
}

private ListKubeNamespaceReq buildNextPageListKubeNamespaceReq(ListKubeNamespaceReq originReq,
long lastIdForCurrentPage) {
ListKubeNamespaceReq nextPageReq = new ListKubeNamespaceReq();
nextPageReq.setPage(originReq.getPage());
nextPageReq.setBizId(originReq.getBizId());
originReq.setFields(originReq.getFields());
nextPageReq.setBkSupplierAccount(originReq.getBkSupplierAccount());

// 添加 namespace ID 作为分页查询 offset 条件
PropertyFilterDTO rewritePropertyFilter = addRuleThenReCreate(originReq.getFilter(),
BaseRuleDTO.greaterThan(KubeNamespaceDTO.Fields.ID, lastIdForCurrentPage));
nextPageReq.setFilter(rewritePropertyFilter);

return nextPageReq;
}

public List<KubeWorkloadDTO> listKubeWorkloads(WorkloadQuery query) {
ListKubeWorkloadReq req = makeCmdbBaseReq(ListKubeWorkloadReq.class);

// 查询条件
req.setBizId(query.getBizId());
req.setKind(query.getKind());
// 根据 Workload ID 升序排列返回的数据,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
req.setPage(new Page(0, 500, KubeWorkloadDTO.Fields.ID));

PropertyFilterDTO workloadPropFilter = new PropertyFilterDTO();
workloadPropFilter.setCondition(RuleConditionEnum.AND.getCondition());
Expand All @@ -1720,28 +1796,33 @@ public List<KubeWorkloadDTO> listKubeWorkloads(WorkloadQuery query) {
req.setFilter(workloadPropFilter);
}


// 返回参数设置
req.setFields(KubeWorkloadDTO.Fields.ALL);

String requestUrl = LIST_KUBE_WORKLOAD.replace("{kind}", query.getKind());

return PageUtil.queryAllWithLoopPageQuery(
return PageUtil.queryAllWithLoopPageQueryInOrder(
500,
page -> {
req.setPage(new Page(page.getStart(), page.getLength()));
return listPage(
req,
false,
cmdbPageReq -> requestCmdbApi(
ApiGwType.BK_APIGW,
HttpMethodEnum.POST,
requestUrl,
null,
cmdbPageReq,
new TypeReference<EsbResp<BaseCcSearchResult<KubeWorkloadDTO>>>() {
}));
(KubeWorkloadDTO latestElement) -> {
if (latestElement == null) {
// 第一页使用原始的请求
return req;
} else {
// 从第二页开始,需要构造 offset 条件,避免由于分页查询期间数据变更导致返回数据重复或者遗漏
return buildNextPageListKubeWorkloadReq(req, latestElement.getId());
}
},
pageReq -> listPage(
req,
false,
cmdbPageReq -> requestCmdbApi(
ApiGwType.BK_APIGW,
HttpMethodEnum.POST,
requestUrl,
null,
cmdbPageReq,
new TypeReference<EsbResp<BaseCcSearchResult<KubeWorkloadDTO>>>() {
})),
PageData::getData,
workload -> {
// cmdb API 返回的数据没有包含 kind 信息,需要补全
Expand All @@ -1750,4 +1831,38 @@ public List<KubeWorkloadDTO> listKubeWorkloads(WorkloadQuery query) {
}
);
}

private ListKubeWorkloadReq buildNextPageListKubeWorkloadReq(ListKubeWorkloadReq originReq,
long lastIdForCurrentPage) {
ListKubeWorkloadReq nextPageReq = new ListKubeWorkloadReq();
nextPageReq.setPage(originReq.getPage());
nextPageReq.setBkSupplierAccount(originReq.getBkSupplierAccount());
nextPageReq.setKind(originReq.getKind());
nextPageReq.setBizId(originReq.getBizId());
nextPageReq.setFields(originReq.getFields());

// 添加 Workload ID 作为分页查询 offset 条件
PropertyFilterDTO rewritePropertyFilter = addRuleThenReCreate(originReq.getFilter(),
BaseRuleDTO.greaterThan(KubeWorkloadDTO.Fields.ID, lastIdForCurrentPage));
nextPageReq.setFilter(rewritePropertyFilter);

return nextPageReq;
}

private PropertyFilterDTO addRuleThenReCreate(PropertyFilterDTO originPropertyFilter, IRule rule) {
PropertyFilterDTO newPropertyFilter = new PropertyFilterDTO();
newPropertyFilter.setCondition(RuleConditionEnum.AND.getCondition());
List<IRule> newRules = new ArrayList<>();
if (originPropertyFilter != null) {
if (originPropertyFilter.getCondition().equals(RuleConditionEnum.OR.getCondition())) {
// 目前场景下属性过滤仅支持 AND
throw new IllegalStateException("Unexpected condition for property filter");
}
newRules.addAll(originPropertyFilter.getRules());
}
newRules.add(rule);
newPropertyFilter.setRules(newRules);

return newPropertyFilter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
1244028=步骤 [{0}] 的目标执行对象为空
1244029=步骤 [{0}] 的源文件执行对象为空
1244030=作业引用的执行对象不存在。不存在的执行对象个数:{0},执行对象列表[{1}]
1244031=Label Selector 不合法

## 业务错误-定时任务(job-crontab)
1245008=删除定时任务失败
Expand Down
Loading

0 comments on commit e569f28

Please sign in to comment.