Skip to content

Commit b7c8c47

Browse files
authored
feat: Supports interrupting the pre-release phase (#2876)
1 parent a984c44 commit b7c8c47

12 files changed

Lines changed: 395 additions & 17 deletions

File tree

apiserver/paasng/paas_wl/bk_app/cnative/specs/constants.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@
2828
TENANT_GUARD_ANNO_KEY = "bkapp.paas.bk.tencent.com/tenant-guard"
2929
# workloads 注入到 annotations 的部署ID字段
3030
BKPAAS_DEPLOY_ID_ANNO_KEY = "bkapp.paas.bk.tencent.com/bkpaas-deploy-id"
31+
32+
# 标记 "最近一次被平台请求中断的部署" 的注解键名, 主要用于中断 operator 的部署
33+
#
34+
# 取值: 被请求中断的那次部署的 deploy_id (字符串), 与 BKPAAS_DEPLOY_ID_ANNO_KEY 同源
35+
# 写入方: apiserver 在用户主动中断部署, 把当前部署的 deploy_id patch 到此注解,
36+
# 用于向 operator 发出实时中断信号
37+
# 读取方: operator 在调和 BkApp 时, 仅当本注解的值与 BKPAAS_DEPLOY_ID_ANNO_KEY 的值同时存在且相等时,
38+
# 认为"当前正在进行的这次部署已被用户主动中断"
39+
INTERRUPTED_DEPLOY_ID_ANNO_KEY = "bkapp.paas.bk.tencent.com/interrupted-deploy-id"
40+
3141
# workloads 注入到 annotations 的增强服务信息字段
3242
BKPAAS_ADDONS_ANNO_KEY = "bkapp.paas.bk.tencent.com/addons"
3343
# 注解中存储 region 的键名

apiserver/paasng/paasng/platform/engine/deploy/bg_command/bkapp_hook.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,13 @@ def _perform(self, hook_name: str) -> PodPhase:
9292
return PodPhase.RUNNING
9393

9494
def _mark_step_stop(self, status: PodPhase):
95+
self.deployment.refresh_from_db(fields=["release_int_requested_at"])
96+
is_interrupted = status != PodPhase.SUCCEEDED and self.deployment.has_requested_int
97+
9598
if status == PodPhase.SUCCEEDED:
9699
self.stream.write_message(Style.Warning("Pre-release execution succeed"))
100+
elif is_interrupted:
101+
self.stream.write_message(Style.Warning("Pre-release interrupted"))
97102
elif status == PodPhase.FAILED:
98103
self.stream.write_message(Style.Error("Pre-release failed, please check logs for more details"))
99104
else:
@@ -106,5 +111,9 @@ def _mark_step_stop(self, status: PodPhase):
106111

107112
if status == PodPhase.SUCCEEDED:
108113
step.mark_and_write_to_stream(self.stream, JobStatus.SUCCESSFUL)
109-
elif status == PodPhase.FAILED:
114+
return
115+
if is_interrupted:
116+
step.mark_and_write_to_stream(self.stream, JobStatus.INTERRUPTED, {"message": "Pre-release interrupted"})
117+
return
118+
if status == PodPhase.FAILED:
110119
step.mark_and_write_to_stream(self.stream, JobStatus.FAILED)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
# TencentBlueKing is pleased to support the open source community by making
3+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
4+
# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
5+
# Licensed under the MIT License (the "License"); you may not use this file except
6+
# in compliance with the License. You may obtain a copy of the License at
7+
#
8+
# http://opensource.org/licenses/MIT
9+
#
10+
# Unless required by applicable law or agreed to in writing, software distributed under
11+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12+
# either express or implied. See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# We undertake not to change the open source license (MIT license) applicable
16+
# to the current version of the project delivered to anyone in the future.
17+
18+
import logging
19+
20+
from paas_wl.bk_app.cnative.specs.constants import (
21+
INTERRUPTED_DEPLOY_ID_ANNO_KEY,
22+
ApiVersion,
23+
)
24+
from paas_wl.core.resource import generate_bkapp_name
25+
from paas_wl.infras.resources.base import crd
26+
from paas_wl.infras.resources.base.kres import PatchType
27+
from paas_wl.infras.resources.utils.basic import get_client_by_app
28+
from paasng.platform.engine.models.deployment import Deployment
29+
30+
logger = logging.getLogger(__name__)
31+
32+
33+
def interrupt_cnative_pre_release(deployment: Deployment) -> None:
34+
"""中断云原生应用的 PreRelease 阶段.
35+
36+
:param deployment: 待中断的 Deployment 对象 (云原生应用).
37+
"""
38+
env = deployment.app_environment
39+
wl_app = env.wl_app
40+
bkapp_name = generate_bkapp_name(env)
41+
deploy_id = str(deployment.bkapp_release_id)
42+
43+
with get_client_by_app(wl_app) as client:
44+
# 写入 deploy-interrupted annotation, 通知 operator 协调中断的部署
45+
body = {"metadata": {"annotations": {INTERRUPTED_DEPLOY_ID_ANNO_KEY: deploy_id}}}
46+
try:
47+
crd.BkApp(client, api_version=ApiVersion.V1ALPHA2).patch(
48+
name=bkapp_name,
49+
namespace=wl_app.namespace,
50+
body=body,
51+
ptype=PatchType.MERGE,
52+
)
53+
except Exception:
54+
logger.exception(
55+
"Failed to patch BkApp deploy-interrupted annotation, bkapp=%s deploy_id=%s",
56+
bkapp_name,
57+
deploy_id,
58+
)

apiserver/paasng/paasng/platform/engine/deploy/interruptions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@
1919
from django.utils import timezone
2020
from django.utils.translation import gettext as _
2121

22+
from paasng.platform.applications.constants import ApplicationType
2223
from paasng.platform.engine.constants import JobStatus
2324
from paasng.platform.engine.deploy.bg_build.bg_build import interrupt_build_proc
25+
from paasng.platform.engine.deploy.bg_command.bkapp_hook_interrupt import interrupt_cnative_pre_release
2426
from paasng.platform.engine.exceptions import DeployInterruptionFailed
2527
from paasng.platform.engine.models.deployment import Deployment
2628
from paasng.platform.engine.workflow import DeploymentCoordinator
29+
from paasng.platform.modules.constants import DeployHookType
2730

2831
logger = logging.getLogger(__name__)
2932

@@ -64,3 +67,21 @@ def interrupt_deployment(deployment: Deployment, user: User):
6467
# This exception means that build has not been started yet, transform
6568
# the error message.
6669
raise DeployInterruptionFailed("任务正处于预备执行状态,无法中断,请稍候重试")
70+
71+
if _is_cnative_pre_release_phase(deployment):
72+
interrupt_cnative_pre_release(deployment)
73+
74+
75+
def _is_cnative_pre_release_phase(deployment: Deployment) -> bool:
76+
"""Return whether the deployment is currently in the cloud-native pre-release phase
77+
that is interruptible.
78+
"""
79+
env = deployment.app_environment
80+
if env.application.type != ApplicationType.CLOUD_NATIVE:
81+
return False
82+
83+
if deployment.bkapp_release_id is None:
84+
return False
85+
86+
pre_release_hook = env.module.deploy_hooks.get_by_type(DeployHookType.PRE_RELEASE_HOOK)
87+
return bool(pre_release_hook and pre_release_hook.enabled)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# -*- coding: utf-8 -*-
2+
# TencentBlueKing is pleased to support the open source community by making
3+
# 蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
4+
# Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
5+
# Licensed under the MIT License (the "License"); you may not use this file except
6+
# in compliance with the License. You may obtain a copy of the License at
7+
#
8+
# http://opensource.org/licenses/MIT
9+
#
10+
# Unless required by applicable law or agreed to in writing, software distributed under
11+
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12+
# either express or implied. See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# We undertake not to change the open source license (MIT license) applicable
16+
# to the current version of the project delivered to anyone in the future.
17+
18+
from contextlib import contextmanager
19+
from unittest import mock
20+
21+
import pytest
22+
23+
from paas_wl.bk_app.applications.models import WlApp
24+
from paas_wl.bk_app.cnative.specs.constants import INTERRUPTED_DEPLOY_ID_ANNO_KEY
25+
from paas_wl.core.resource import generate_bkapp_name
26+
from paas_wl.infras.resources.base.kres import PatchType
27+
from paasng.platform.engine.deploy.bg_command.bkapp_hook_interrupt import interrupt_cnative_pre_release
28+
29+
pytestmark = pytest.mark.django_db(databases=["default", "workloads"])
30+
31+
32+
class TestInterruptCNativePreRelease:
33+
@pytest.fixture(autouse=True)
34+
def _setup_wl_app(self, bk_cnative_app, bk_deployment):
35+
engine_app = bk_deployment.app_environment.engine_app
36+
WlApp.objects.get_or_create(name=engine_app.name, region=engine_app.region)
37+
bk_deployment.bkapp_release_id = 1
38+
bk_deployment.save(update_fields=["bkapp_release_id", "updated"])
39+
40+
@pytest.fixture()
41+
def mocked_bkapp(self):
42+
"""patch get_client_by_app 与 crd.BkApp, 返回 BkApp 实例 mock"""
43+
44+
@contextmanager
45+
def fake_get_client(_wl_app):
46+
yield mock.MagicMock()
47+
48+
with (
49+
mock.patch(
50+
"paasng.platform.engine.deploy.bg_command.bkapp_hook_interrupt.get_client_by_app",
51+
side_effect=fake_get_client,
52+
),
53+
mock.patch("paasng.platform.engine.deploy.bg_command.bkapp_hook_interrupt.crd.BkApp") as m_bkapp_cls,
54+
):
55+
yield m_bkapp_cls.return_value
56+
57+
def test_interrupt(self, bk_deployment, mocked_bkapp):
58+
env = bk_deployment.app_environment
59+
wl_app = env.wl_app
60+
bkapp_name = generate_bkapp_name(env)
61+
deploy_id = str(bk_deployment.bkapp_release_id)
62+
63+
interrupt_cnative_pre_release(bk_deployment)
64+
mocked_bkapp.patch.assert_called_once_with(
65+
name=bkapp_name,
66+
namespace=wl_app.namespace,
67+
body={"metadata": {"annotations": {INTERRUPTED_DEPLOY_ID_ANNO_KEY: deploy_id}}},
68+
ptype=PatchType.MERGE,
69+
)
70+
71+
def test_interrupt_best_effort(self, bk_deployment, mocked_bkapp):
72+
"""patch BkApp 抛异常时, 不应向上抛出, 且会记录日志"""
73+
mocked_bkapp.patch.side_effect = RuntimeError("patch failed")
74+
75+
with mock.patch(
76+
"paasng.platform.engine.deploy.bg_command.bkapp_hook_interrupt.logger.exception"
77+
) as mocked_log:
78+
interrupt_cnative_pre_release(bk_deployment)
79+
80+
assert mocked_bkapp.patch.called
81+
assert mocked_log.call_count == 1

operator/api/v1alpha2/constants.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ const (
117117
ImageCredentialsRefAnnoKey = "bkapp.paas.bk.tencent.com/image-credentials"
118118
// DeployIDAnnoKey 注解中存储 bkpaas 部署ID的键名
119119
DeployIDAnnoKey = "bkapp.paas.bk.tencent.com/bkpaas-deploy-id"
120+
// InterruptedDeployIDAnnoKey 注解中存储 "最近一次被平台请求中断的部署 ID" 的键名
121+
// 取值为该次部署的 deploy_id (字符串), 与 DeployIDAnnoKey 同源. 调和时, 仅当本注解的值
122+
// 与 DeployIDAnnoKey 的值同时存在且相等, 才认为"当前部署已被中断"。
123+
InterruptedDeployIDAnnoKey = "bkapp.paas.bk.tencent.com/interrupted-deploy-id"
120124
// PaaSAnalysisSiteIDAnnoKey 注解中存储 PA site id 的键名
121125
PaaSAnalysisSiteIDAnnoKey = "bkapp.paas.bk.tencent.com/paas-analysis-site-id"
122126
)

operator/go.sum

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
225225
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
226226
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
227227
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
228-
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
229-
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
230228
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
231229
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
232230
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -246,15 +244,11 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
246244
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
247245
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
248246
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
249-
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
250-
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
251247
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
252248
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
253249
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
254250
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
255251
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
256-
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
257-
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
258252
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
259253
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
260254
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -268,20 +262,14 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
268262
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
269263
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
270264
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
271-
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
272-
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
273265
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
274266
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
275267
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
276-
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
277-
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
278268
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
279269
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
280270
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
281271
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
282272
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
283-
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
284-
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
285273
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
286274
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
287275
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
@@ -296,8 +284,6 @@ golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roY
296284
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
297285
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
298286
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
299-
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
300-
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
301287
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
302288
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
303289
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

operator/pkg/controllers/bkapp/deploy_action.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,17 @@ func (r *DeployActionReconciler) Reconcile(ctx context.Context, bkapp *paasv1alp
114114

115115
// validate that there are no running hooks currently, return error if found any running hooks.
116116
func (r *DeployActionReconciler) validateNoRunningHooks(ctx context.Context, bkapp *paasv1alpha2.BkApp) error {
117-
// 如果上一次的部署是被用户主动中断, 则继续执行后续的部署调和流程, 忽略可能处于 progressing 状态的旧 hook
118-
// TODO 考虑支持更实时的中断请求, 包括直接删除执行中的 hook 等?
117+
// 如果上一次的部署是被用户主动中断, 则继续执行后续的部署调和流程
119118
if platdeploy.GetLastDeployStatus(bkapp) == "interrupted" {
120119
return nil
121120
}
121+
122+
// 兜底: 平台侧已经写入实时中断信号 (InterruptedDeployIDAnnoKey 指向上次的 DeployId),
123+
// 但还没有写入 LastDeployStatusAnnoKey, 通过中断信号的匹配识别上次部署已经被中断
124+
if platdeploy.IsDeployInterrupted(bkapp, bkapp.Status.DeployId) {
125+
return nil
126+
}
127+
122128
// Check pre-release hook
123129
if hookres.IsPreReleaseProgressing(bkapp) {
124130
_, err := hooks.CheckAndUpdatePreReleaseHookStatus(

operator/pkg/controllers/bkapp/deploy_action_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,29 @@ var _ = Describe("Test DeployActionReconciler", func() {
211211

212212
expectDeployActionInitialized(ret, bkapp, "2")
213213
})
214+
215+
It("deploy ID changed with running hook when previous deploy matches interrupt signal", func() {
216+
bkapp.SetAnnotations(
217+
map[string]string{
218+
paasv1alpha2.DeployIDAnnoKey: "2",
219+
paasv1alpha2.InterruptedDeployIDAnnoKey: "1",
220+
},
221+
)
222+
bkapp.Status.DeployId = "1"
223+
bkapp.Status.SetHookStatus(paasv1alpha2.HookStatus{
224+
Type: paasv1alpha2.HookPreRelease,
225+
Phase: paasv1alpha2.HealthProgressing,
226+
StartTime: lo.ToPtr(metav1.Now()),
227+
})
228+
229+
hook, err := hookres.BuildPreReleaseHook(bkapp, bkapp.Status.FindHookStatus(paasv1alpha2.HookPreRelease))
230+
Expect(err).To(BeNil())
231+
Expect(hook.Pod).NotTo(BeNil())
232+
233+
client := builder.WithObjects(bkapp, hook.Pod).Build()
234+
ret := NewDeployActionReconciler(client).Reconcile(context.Background(), bkapp)
235+
236+
expectDeployActionInitialized(ret, bkapp, "2")
237+
})
214238
})
215239
})

0 commit comments

Comments
 (0)