38
38
import org .apache .flink .kubernetes .operator .reconciler .ReconciliationUtils ;
39
39
import org .apache .flink .kubernetes .operator .utils .EventCollector ;
40
40
import org .apache .flink .kubernetes .operator .utils .EventRecorder ;
41
- import org .apache .flink .runtime . execution . ExecutionState ;
41
+ import org .apache .flink .kubernetes . utils . KubernetesUtils ;
42
42
import org .apache .flink .runtime .jobgraph .JobResourceRequirements ;
43
43
import org .apache .flink .runtime .jobgraph .JobVertexID ;
44
44
import org .apache .flink .runtime .jobgraph .JobVertexResourceRequirements ;
47
47
import org .apache .flink .runtime .rest .messages .job .JobDetailsInfo ;
48
48
import org .apache .flink .runtime .rest .messages .job .JobResourceRequirementsBody ;
49
49
import org .apache .flink .runtime .rest .messages .job .JobResourceRequirementsHeaders ;
50
- import org .apache .flink .runtime .rest .messages .job .metrics .IOMetricsInfo ;
51
50
import org .apache .flink .util .concurrent .Executors ;
52
51
53
52
import io .fabric8 .kubernetes .api .model .DeletionPropagation ;
54
- import io .fabric8 .kubernetes .api .model .apps . Deployment ;
53
+ import io .fabric8 .kubernetes .api .model .PodBuilder ;
55
54
import io .fabric8 .kubernetes .api .model .apps .DeploymentBuilder ;
56
55
import io .fabric8 .kubernetes .client .KubernetesClient ;
57
- import io .fabric8 .kubernetes .client .dsl .Resource ;
58
56
import io .fabric8 .kubernetes .client .server .mock .EnableKubernetesMockClient ;
59
57
import io .fabric8 .kubernetes .client .server .mock .KubernetesMockServer ;
60
58
import org .junit .jupiter .api .BeforeEach ;
61
59
import org .junit .jupiter .api .Test ;
62
60
import org .junit .jupiter .params .ParameterizedTest ;
61
+ import org .junit .jupiter .params .provider .EnumSource ;
63
62
import org .junit .jupiter .params .provider .MethodSource ;
64
63
65
64
import java .time .Duration ;
65
+ import java .time .Instant ;
66
66
import java .util .List ;
67
67
import java .util .Map ;
68
68
import java .util .Optional ;
76
76
import static org .apache .flink .kubernetes .operator .config .KubernetesOperatorConfigOptions .OPERATOR_HEALTH_PROBE_PORT ;
77
77
import static org .junit .jupiter .api .Assertions .assertEquals ;
78
78
import static org .junit .jupiter .api .Assertions .assertFalse ;
79
- import static org .junit .jupiter .api .Assertions .assertNotNull ;
80
79
import static org .junit .jupiter .api .Assertions .assertNull ;
81
80
import static org .junit .jupiter .api .Assertions .assertTrue ;
82
81
import static org .junit .jupiter .api .Assertions .fail ;
@@ -107,25 +106,19 @@ public void setup() {
107
106
executorService = Executors .newDirectExecutorService ();
108
107
}
109
108
110
- @ Test
111
- public void testDeleteClusterInternal () {
112
-
109
+ @ ParameterizedTest
110
+ @ EnumSource (DeletionPropagation .class )
111
+ public void testDeleteClusterInternal (DeletionPropagation propagation ) {
112
+ var timeout = Duration .ofSeconds (4 );
113
+ configuration .set (
114
+ KubernetesOperatorConfigOptions .OPERATOR_RESOURCE_CLEANUP_TIMEOUT , timeout );
113
115
var flinkService =
114
116
new NativeFlinkService (
115
- client , null , executorService , operatorConfig , eventRecorder ) {
116
-
117
- @ Override
118
- protected Duration deleteDeploymentBlocking (
119
- String name ,
120
- Resource <Deployment > deployment ,
121
- DeletionPropagation propagation ,
122
- Duration timeout ) {
123
- // Ensure deployment is scaled down before deletion
124
- assertEquals (0 , deployment .get ().getSpec ().getReplicas ());
125
- return super .deleteDeploymentBlocking (
126
- name , deployment , propagation , timeout );
127
- }
128
- };
117
+ client ,
118
+ null ,
119
+ executorService ,
120
+ FlinkOperatorConfiguration .fromConfiguration (configuration ),
121
+ eventRecorder );
129
122
130
123
var deployment = TestUtils .buildApplicationCluster ();
131
124
ReconciliationUtils .updateStatusForDeployedSpec (deployment , new Configuration ());
@@ -141,18 +134,55 @@ protected Duration deleteDeploymentBlocking(
141
134
.endSpec ()
142
135
.build ();
143
136
client .resource (dep ).create ();
144
- assertNotNull (
145
- client .apps ()
146
- .deployments ()
147
- .inNamespace (TestUtils .TEST_NAMESPACE )
148
- .withName (TestUtils .TEST_DEPLOYMENT_NAME )
149
- .get ());
150
137
138
+ var patched = new AtomicBoolean (false );
139
+ mockServer
140
+ .expect ()
141
+ .patch ()
142
+ .withPath (
143
+ String .format (
144
+ "/apis/apps/v1/namespaces/%s/deployments/%s" ,
145
+ TestUtils .TEST_NAMESPACE , TestUtils .TEST_DEPLOYMENT_NAME ))
146
+ .andReply (
147
+ 200 ,
148
+ req -> {
149
+ patched .set (true );
150
+ return deployment ;
151
+ })
152
+ .always ();
153
+
154
+ // We create the JM pod explicitly here, this will block the JM scale down action
155
+ // indefinitely and we use this to verify the correct timeout enforcement
156
+ var jmPod =
157
+ new PodBuilder ()
158
+ .withNewMetadata ()
159
+ .withName ("JM" )
160
+ .withLabels (
161
+ KubernetesUtils .getJobManagerSelectors (
162
+ TestUtils .TEST_DEPLOYMENT_NAME ))
163
+ .withNamespace (TestUtils .TEST_NAMESPACE )
164
+ .endMetadata ()
165
+ .build ();
166
+ client .resource (jmPod ).create ();
167
+
168
+ var start = Instant .now ();
151
169
flinkService .deleteClusterInternal (
152
170
deployment .getMetadata ().getNamespace (),
153
171
deployment .getMetadata ().getName (),
154
172
configManager .getObserveConfig (deployment ),
155
- DeletionPropagation .FOREGROUND );
173
+ propagation );
174
+ var measured = Duration .between (start , Instant .now ());
175
+
176
+ // Do not scale JM deployment during orphan deletion
177
+ if (propagation == DeletionPropagation .FOREGROUND ) {
178
+ assertTrue (patched .get ());
179
+ // We make sure that we dont use up the entire timeout for jm deletion
180
+ assertTrue (timeout .minus (measured ).toSeconds () > 0 );
181
+ // Validate that we actually waited 2 seconds
182
+ assertTrue (measured .toSeconds () > 1 );
183
+ } else {
184
+ assertFalse (patched .get ());
185
+ }
156
186
157
187
assertNull (
158
188
client .apps ()
@@ -476,22 +506,6 @@ private void testScaleConditionLastSpec(
476
506
scaled );
477
507
}
478
508
479
- private JobDetailsInfo .JobVertexDetailsInfo jobVertexDetailsInfo (
480
- JobVertexID jvi , int parallelism ) {
481
- var ioMetricsInfo = new IOMetricsInfo (0 , false , 0 , false , 0 , false , 0 , false , 0L , 0L , 0. );
482
- return new JobDetailsInfo .JobVertexDetailsInfo (
483
- jvi ,
484
- "" ,
485
- 900 ,
486
- parallelism ,
487
- ExecutionState .RUNNING ,
488
- 0 ,
489
- 0 ,
490
- 0 ,
491
- Map .of (),
492
- ioMetricsInfo );
493
- }
494
-
495
509
@ Test
496
510
public void resourceRestApiTest () throws Exception {
497
511
var testingClusterClient = new TestingClusterClient <String >(configuration );
0 commit comments