This is an automated email from the ASF dual-hosted git repository.
gyfora pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-kubernetes-operator.git
The following commit(s) were added to refs/heads/main by this push:
new 1f6a7505 [FLINK-29413] Make it possible to associate triggered and
completed savepoints
1f6a7505 is described below
commit 1f6a75056acae90e9fab182fd076ee6755b35bbb
Author: Matyas Orhidi <[email protected]>
AuthorDate: Tue Sep 27 13:50:06 2022 +0200
[FLINK-29413] Make it possible to associate triggered and completed
savepoints
---
docs/content/docs/custom-resource/reference.md | 14 ++
.../kubernetes/operator/crd/status/Savepoint.java | 41 ++++-
.../{Savepoint.java => SavepointFormatType.java} | 31 +---
.../operator/crd/status/SavepointInfo.java | 6 +-
.../operator/observer/SavepointObserver.java | 7 +-
.../operator/service/AbstractFlinkService.java | 37 +++--
.../kubernetes/operator/utils/SavepointUtils.java | 15 ++
.../kubernetes/operator/TestingFlinkService.java | 9 +-
.../operator/observer/SavepointObserverTest.java | 22 ++-
.../deployment/ApplicationObserverTest.java | 175 ++++++++++++++++++++-
.../sessionjob/SessionJobObserverTest.java | 6 +-
.../crds/flinkdeployments.flink.apache.org-v1.yml | 22 +++
.../crds/flinksessionjobs.flink.apache.org-v1.yml | 22 +++
13 files changed, 355 insertions(+), 52 deletions(-)
diff --git a/docs/content/docs/custom-resource/reference.md
b/docs/content/docs/custom-resource/reference.md
index 400c078a..924e89f5 100644
--- a/docs/content/docs/custom-resource/reference.md
+++ b/docs/content/docs/custom-resource/reference.md
@@ -274,6 +274,19 @@ This page serves as a full reference for FlinkDeployment
custom resource definit
| timeStamp | long | Millisecond timestamp at the start of the savepoint
operation. |
| location | java.lang.String | External pointer of the savepoint can be used
to recover jobs. |
| triggerType |
org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType |
Savepoint trigger mechanism. |
+| formatType |
org.apache.flink.kubernetes.operator.crd.status.SavepointFormatType | |
+| triggerNonce | java.lang.Long | Nonce value used when the savepoint was
triggered manually {@link SavepointTriggerType#MANUAL}, defaults to 0. |
+
+### SavepointFormatType
+**Class**: org.apache.flink.kubernetes.operator.crd.status.SavepointFormatType
+
+**Description**: Savepoint format type.
+
+| Value | Docs |
+| ----- | ---- |
+| CANONICAL | A canonical, common for all state backends format. |
+| NATIVE | A format specific for the chosen state backend. |
+| UNKNOWN | Savepoint format unknown, if the savepoint was not triggered by
the operator. |
### SavepointInfo
**Class**: org.apache.flink.kubernetes.operator.crd.status.SavepointInfo
@@ -286,6 +299,7 @@ This page serves as a full reference for FlinkDeployment
custom resource definit
| triggerId | java.lang.String | Trigger id of a pending savepoint operation. |
| triggerTimestamp | long | Trigger timestamp of a pending savepoint
operation. |
| triggerType |
org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType |
Savepoint trigger mechanism. |
+| formatType |
org.apache.flink.kubernetes.operator.crd.status.SavepointFormatType | |
| savepointHistory |
java.util.List<org.apache.flink.kubernetes.operator.crd.status.Savepoint> |
List of recent savepoints. |
| lastPeriodicSavepointTimestamp | long | Trigger timestamp of last periodic
savepoint operation. |
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/Savepoint.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/Savepoint.java
index e2681e86..6e1c51c3 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/Savepoint.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/Savepoint.java
@@ -19,14 +19,12 @@ package org.apache.flink.kubernetes.operator.crd.status;
import org.apache.flink.annotation.Experimental;
-import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/** Represents information about a finished savepoint. */
@Experimental
@Data
-@AllArgsConstructor
@NoArgsConstructor
public class Savepoint {
/** Millisecond timestamp at the start of the savepoint operation. */
@@ -38,7 +36,42 @@ public class Savepoint {
/** Savepoint trigger mechanism. */
private SavepointTriggerType triggerType = SavepointTriggerType.UNKNOWN;
- public static Savepoint of(String location, SavepointTriggerType type) {
- return new Savepoint(System.currentTimeMillis(), location, type);
+ private SavepointFormatType formatType = SavepointFormatType.UNKNOWN;
+
+ /**
+ * Nonce value used when the savepoint was triggered manually {@link
+ * SavepointTriggerType#MANUAL}, defaults to 0.
+ */
+ private Long triggerNonce = 0L;
+
+ public Savepoint(
+ long timeStamp,
+ String location,
+ SavepointTriggerType triggerType,
+ SavepointFormatType formatType,
+ Long triggerNonce) {
+ this.timeStamp = timeStamp;
+ this.location = location;
+ this.triggerType = triggerType;
+ this.formatType = formatType;
+ setTriggerNonce(triggerNonce);
+ }
+
+ public static Savepoint of(String location, SavepointTriggerType
triggerType) {
+ return new Savepoint(
+ System.currentTimeMillis(), location, triggerType,
SavepointFormatType.UNKNOWN, 0L);
+ }
+
+ public static Savepoint of(
+ String location, SavepointTriggerType triggerType,
SavepointFormatType formatType) {
+ return new Savepoint(System.currentTimeMillis(), location,
triggerType, formatType, 0L);
+ }
+
+ public void setTriggerNonce(Long triggerNonce) {
+ if (triggerNonce == null) {
+ this.triggerNonce = 0L;
+ } else {
+ this.triggerNonce = triggerNonce;
+ }
}
}
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/Savepoint.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/SavepointFormatType.java
similarity index 53%
copy from
flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/Savepoint.java
copy to
flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/SavepointFormatType.java
index e2681e86..0fff963c 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/Savepoint.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/SavepointFormatType.java
@@ -17,28 +17,13 @@
package org.apache.flink.kubernetes.operator.crd.status;
-import org.apache.flink.annotation.Experimental;
+/** Savepoint format type. */
+public enum SavepointFormatType {
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/** Represents information about a finished savepoint. */
-@Experimental
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class Savepoint {
- /** Millisecond timestamp at the start of the savepoint operation. */
- private long timeStamp;
-
- /** External pointer of the savepoint can be used to recover jobs. */
- private String location;
-
- /** Savepoint trigger mechanism. */
- private SavepointTriggerType triggerType = SavepointTriggerType.UNKNOWN;
-
- public static Savepoint of(String location, SavepointTriggerType type) {
- return new Savepoint(System.currentTimeMillis(), location, type);
- }
+ /** A canonical, common for all state backends format. */
+ CANONICAL,
+ /** A format specific for the chosen state backend. */
+ NATIVE,
+ /** Savepoint format unknown, if the savepoint was not triggered by the
operator. */
+ UNKNOWN
}
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/SavepointInfo.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/SavepointInfo.java
index 253f8ec1..ebfd30d9 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/SavepointInfo.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/crd/status/SavepointInfo.java
@@ -46,16 +46,20 @@ public class SavepointInfo {
/** Savepoint trigger mechanism. */
private SavepointTriggerType triggerType = SavepointTriggerType.UNKNOWN;
+ private SavepointFormatType formatType = SavepointFormatType.UNKNOWN;
+
/** List of recent savepoints. */
private List<Savepoint> savepointHistory = new ArrayList<>();
/** Trigger timestamp of last periodic savepoint operation. */
private long lastPeriodicSavepointTimestamp = 0L;
- public void setTrigger(String triggerId, SavepointTriggerType triggerType)
{
+ public void setTrigger(
+ String triggerId, SavepointTriggerType triggerType,
SavepointFormatType formatType) {
this.triggerId = triggerId;
this.triggerTimestamp = System.currentTimeMillis();
this.triggerType = triggerType;
+ this.formatType = formatType;
}
public void resetTrigger() {
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/observer/SavepointObserver.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/observer/SavepointObserver.java
index aa2d69de..f0c8ee78 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/observer/SavepointObserver.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/observer/SavepointObserver.java
@@ -26,6 +26,7 @@ import
org.apache.flink.kubernetes.operator.crd.AbstractFlinkResource;
import org.apache.flink.kubernetes.operator.crd.status.CommonStatus;
import org.apache.flink.kubernetes.operator.crd.status.Savepoint;
import org.apache.flink.kubernetes.operator.crd.status.SavepointInfo;
+import org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType;
import org.apache.flink.kubernetes.operator.exception.ReconciliationException;
import org.apache.flink.kubernetes.operator.reconciler.ReconciliationUtils;
import org.apache.flink.kubernetes.operator.service.FlinkService;
@@ -127,7 +128,11 @@ public class SavepointObserver<
new Savepoint(
savepointInfo.getTriggerTimestamp(),
savepointFetchResult.getLocation(),
- savepointInfo.getTriggerType());
+ savepointInfo.getTriggerType(),
+ savepointInfo.getFormatType(),
+ SavepointTriggerType.MANUAL ==
savepointInfo.getTriggerType()
+ ?
resource.getSpec().getJob().getSavepointTriggerNonce()
+ : null);
ReconciliationUtils.updateLastReconciledSavepointTriggerNonce(savepointInfo,
resource);
savepointInfo.updateLastSavepoint(savepoint);
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/AbstractFlinkService.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/AbstractFlinkService.java
index 0b60fabc..6ae12f80 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/AbstractFlinkService.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/AbstractFlinkService.java
@@ -38,11 +38,13 @@ import
org.apache.flink.kubernetes.operator.crd.spec.JobSpec;
import org.apache.flink.kubernetes.operator.crd.spec.UpgradeMode;
import
org.apache.flink.kubernetes.operator.crd.status.JobManagerDeploymentStatus;
import org.apache.flink.kubernetes.operator.crd.status.Savepoint;
+import org.apache.flink.kubernetes.operator.crd.status.SavepointFormatType;
import org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType;
import
org.apache.flink.kubernetes.operator.exception.DeploymentFailedException;
import org.apache.flink.kubernetes.operator.observer.SavepointFetchResult;
import org.apache.flink.kubernetes.operator.reconciler.ReconciliationUtils;
import org.apache.flink.kubernetes.operator.utils.FlinkUtils;
+import org.apache.flink.kubernetes.operator.utils.SavepointUtils;
import org.apache.flink.runtime.client.JobStatusMessage;
import org.apache.flink.runtime.execution.ExecutionState;
import
org.apache.flink.runtime.highavailability.nonha.standalone.StandaloneClientHAServices;
@@ -53,7 +55,6 @@ import
org.apache.flink.runtime.messages.webmonitor.MultipleJobsDetails;
import org.apache.flink.runtime.rest.FileUpload;
import org.apache.flink.runtime.rest.RestClient;
import org.apache.flink.runtime.rest.handler.async.AsynchronousOperationResult;
-import org.apache.flink.runtime.rest.handler.async.TriggerResponse;
import org.apache.flink.runtime.rest.messages.DashboardConfiguration;
import org.apache.flink.runtime.rest.messages.EmptyMessageParameters;
import org.apache.flink.runtime.rest.messages.EmptyRequestBody;
@@ -65,7 +66,6 @@ import
org.apache.flink.runtime.rest.messages.job.savepoints.SavepointInfo;
import
org.apache.flink.runtime.rest.messages.job.savepoints.SavepointStatusHeaders;
import
org.apache.flink.runtime.rest.messages.job.savepoints.SavepointStatusMessageParameters;
import
org.apache.flink.runtime.rest.messages.job.savepoints.SavepointTriggerHeaders;
-import
org.apache.flink.runtime.rest.messages.job.savepoints.SavepointTriggerMessageParameters;
import
org.apache.flink.runtime.rest.messages.job.savepoints.SavepointTriggerRequestBody;
import org.apache.flink.runtime.rest.util.RestConstants;
import
org.apache.flink.runtime.state.memory.NonPersistentMetadataCheckpointStorageLocation;
@@ -259,6 +259,7 @@ public abstract class AbstractFlinkService implements
FlinkService {
var jobId = jobIdString != null ? JobID.fromHexString(jobIdString) :
null;
Optional<String> savepointOpt = Optional.empty();
+ var savepointFormatType = SavepointUtils.getSavepointFormatType(conf);
try (ClusterClient<String> clusterClient = getClusterClient(conf)) {
var clusterId = clusterClient.getClusterId();
switch (upgradeMode) {
@@ -300,9 +301,7 @@ public abstract class AbstractFlinkService implements
FlinkService {
conf.get(FLINK_VERSION)
.isNewerVersionThan(
FlinkVersion.v1_14)
- ? conf.get(
-
KubernetesOperatorConfigOptions
-
.OPERATOR_SAVEPOINT_FORMAT_TYPE)
+ ?
savepointFormatType
: null)
.get(timeout, TimeUnit.SECONDS);
savepointOpt = Optional.of(savepoint);
@@ -338,7 +337,11 @@ public abstract class AbstractFlinkService implements
FlinkService {
deploymentStatus.getJobStatus().setState(JobStatus.FINISHED.name());
savepointOpt.ifPresent(
location -> {
- Savepoint sp = Savepoint.of(location,
SavepointTriggerType.UPGRADE);
+ Savepoint sp =
+ Savepoint.of(
+ location,
+ SavepointTriggerType.UPGRADE,
+
SavepointFormatType.valueOf(savepointFormatType.name()));
deploymentStatus.getJobStatus().getSavepointInfo().updateLastSavepoint(sp);
});
@@ -436,16 +439,19 @@ public abstract class AbstractFlinkService implements
FlinkService {
LOG.info("Triggering new savepoint");
try (RestClusterClient<String> clusterClient =
(RestClusterClient<String>) getClusterClient(conf)) {
- SavepointTriggerHeaders savepointTriggerHeaders =
SavepointTriggerHeaders.getInstance();
- SavepointTriggerMessageParameters
savepointTriggerMessageParameters =
+ var savepointTriggerHeaders =
SavepointTriggerHeaders.getInstance();
+ var savepointTriggerMessageParameters =
savepointTriggerHeaders.getUnresolvedMessageParameters();
savepointTriggerMessageParameters.jobID.resolve(JobID.fromHexString(jobId));
- final String savepointDirectory =
+ var savepointDirectory =
Preconditions.checkNotNull(conf.get(CheckpointingOptions.SAVEPOINT_DIRECTORY));
- final long timeout =
+ var timeout =
configManager.getOperatorConfiguration().getFlinkClientTimeout().getSeconds();
- TriggerResponse response =
+
+ var savepointFormatType =
SavepointUtils.getSavepointFormatType(conf);
+
+ var response =
clusterClient
.sendRequest(
savepointTriggerHeaders,
@@ -455,15 +461,16 @@ public abstract class AbstractFlinkService implements
FlinkService {
false,
conf.get(FLINK_VERSION)
.isNewerVersionThan(FlinkVersion.v1_14)
- ? conf.get(
-
KubernetesOperatorConfigOptions
-
.OPERATOR_SAVEPOINT_FORMAT_TYPE)
+ ? savepointFormatType
: null,
null))
.get(timeout, TimeUnit.SECONDS);
LOG.info("Savepoint successfully triggered: " +
response.getTriggerId().toHexString());
- savepointInfo.setTrigger(response.getTriggerId().toHexString(),
triggerType);
+ savepointInfo.setTrigger(
+ response.getTriggerId().toHexString(),
+ triggerType,
+ SavepointFormatType.valueOf(savepointFormatType.name()));
}
}
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/utils/SavepointUtils.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/utils/SavepointUtils.java
index 2fab2efe..bc56c638 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/utils/SavepointUtils.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/utils/SavepointUtils.java
@@ -19,8 +19,10 @@ package org.apache.flink.kubernetes.operator.utils;
import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.configuration.Configuration;
+import org.apache.flink.core.execution.SavepointFormatType;
import
org.apache.flink.kubernetes.operator.config.KubernetesOperatorConfigOptions;
import org.apache.flink.kubernetes.operator.crd.AbstractFlinkResource;
+import org.apache.flink.kubernetes.operator.crd.spec.FlinkVersion;
import org.apache.flink.kubernetes.operator.crd.status.JobStatus;
import org.apache.flink.kubernetes.operator.crd.status.SavepointInfo;
import org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType;
@@ -35,6 +37,8 @@ import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
+import static
org.apache.flink.kubernetes.operator.config.FlinkConfigBuilder.FLINK_VERSION;
+
/** Savepoint utilities. */
public class SavepointUtils {
@@ -164,4 +168,15 @@ public class SavepointUtils {
? "Periodic savepoint failed"
: "Savepoint failed for savepointTriggerNonce: " +
triggerNonce;
}
+
+ public static SavepointFormatType getSavepointFormatType(Configuration
configuration) {
+ var savepointFormatType =
org.apache.flink.core.execution.SavepointFormatType.CANONICAL;
+ if (configuration.get(FLINK_VERSION) != null
+ &&
configuration.get(FLINK_VERSION).isNewerVersionThan(FlinkVersion.v1_14)) {
+ savepointFormatType =
+ configuration.get(
+
KubernetesOperatorConfigOptions.OPERATOR_SAVEPOINT_FORMAT_TYPE);
+ }
+ return savepointFormatType;
+ }
}
diff --git
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/TestingFlinkService.java
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/TestingFlinkService.java
index 27b453d0..961830c6 100644
---
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/TestingFlinkService.java
+++
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/TestingFlinkService.java
@@ -37,6 +37,7 @@ import
org.apache.flink.kubernetes.operator.crd.spec.UpgradeMode;
import org.apache.flink.kubernetes.operator.crd.status.FlinkDeploymentStatus;
import
org.apache.flink.kubernetes.operator.crd.status.JobManagerDeploymentStatus;
import org.apache.flink.kubernetes.operator.crd.status.Savepoint;
+import org.apache.flink.kubernetes.operator.crd.status.SavepointFormatType;
import org.apache.flink.kubernetes.operator.crd.status.SavepointInfo;
import org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType;
import
org.apache.flink.kubernetes.operator.exception.DeploymentFailedException;
@@ -44,6 +45,7 @@ import
org.apache.flink.kubernetes.operator.observer.SavepointFetchResult;
import org.apache.flink.kubernetes.operator.service.AbstractFlinkService;
import
org.apache.flink.kubernetes.operator.standalone.StandaloneKubernetesConfigOptionsInternal;
import org.apache.flink.kubernetes.operator.utils.FlinkUtils;
+import org.apache.flink.kubernetes.operator.utils.SavepointUtils;
import org.apache.flink.runtime.client.JobStatusMessage;
import org.apache.flink.runtime.execution.ExecutionState;
import org.apache.flink.runtime.jobgraph.SavepointConfigOptions;
@@ -127,6 +129,8 @@ public class TestingFlinkService extends
AbstractFlinkService {
public void clear() {
jobs.clear();
sessions.clear();
+ triggerCounter = 0;
+ savepointCounter = 0;
}
public Set<String> getSessions() {
@@ -253,7 +257,10 @@ public class TestingFlinkService extends
AbstractFlinkService {
SavepointInfo savepointInfo,
Configuration conf) {
var triggerId = "trigger_" + triggerCounter++;
- savepointInfo.setTrigger(triggerId, triggerType);
+
+ var savepointFormatType = SavepointUtils.getSavepointFormatType(conf);
+ savepointInfo.setTrigger(
+ triggerId, triggerType,
SavepointFormatType.valueOf(savepointFormatType.name()));
savepointTriggers.put(triggerId, false);
}
diff --git
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/SavepointObserverTest.java
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/SavepointObserverTest.java
index af42289f..222fc0e6 100644
---
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/SavepointObserverTest.java
+++
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/SavepointObserverTest.java
@@ -25,6 +25,7 @@ import
org.apache.flink.kubernetes.operator.config.KubernetesOperatorConfigOptio
import org.apache.flink.kubernetes.operator.crd.FlinkDeployment;
import org.apache.flink.kubernetes.operator.crd.status.FlinkDeploymentStatus;
import org.apache.flink.kubernetes.operator.crd.status.Savepoint;
+import org.apache.flink.kubernetes.operator.crd.status.SavepointFormatType;
import org.apache.flink.kubernetes.operator.crd.status.SavepointInfo;
import org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType;
import org.apache.flink.kubernetes.operator.utils.EventRecorder;
@@ -63,7 +64,9 @@ public class SavepointObserverTest {
SavepointInfo spInfo = new SavepointInfo();
Assertions.assertTrue(spInfo.getSavepointHistory().isEmpty());
- Savepoint sp = new Savepoint(1, "sp1", SavepointTriggerType.MANUAL);
+ Savepoint sp =
+ new Savepoint(
+ 1, "sp1", SavepointTriggerType.MANUAL,
SavepointFormatType.CANONICAL, 123L);
spInfo.updateLastSavepoint(sp);
observer.cleanupSavepointHistory(spInfo,
configManager.getDefaultConfig());
@@ -81,7 +84,9 @@ public class SavepointObserverTest {
SavepointInfo spInfo = new SavepointInfo();
- Savepoint sp1 = new Savepoint(1, "sp1", SavepointTriggerType.MANUAL);
+ Savepoint sp1 =
+ new Savepoint(
+ 1, "sp1", SavepointTriggerType.MANUAL,
SavepointFormatType.CANONICAL, 123L);
spInfo.updateLastSavepoint(sp1);
observer.cleanupSavepointHistory(spInfo, conf);
Assertions.assertIterableEquals(
@@ -89,7 +94,9 @@ public class SavepointObserverTest {
Assertions.assertIterableEquals(
Collections.emptyList(), flinkService.getDisposedSavepoints());
- Savepoint sp2 = new Savepoint(2, "sp2", SavepointTriggerType.MANUAL);
+ Savepoint sp2 =
+ new Savepoint(
+ 2, "sp2", SavepointTriggerType.MANUAL,
SavepointFormatType.CANONICAL, 123L);
spInfo.updateLastSavepoint(sp2);
observer.cleanupSavepointHistory(spInfo, conf);
Assertions.assertIterableEquals(
@@ -110,7 +117,9 @@ public class SavepointObserverTest {
configManager.updateDefaultConfig(conf);
SavepointInfo spInfo = new SavepointInfo();
- Savepoint sp1 = new Savepoint(1, "sp1", SavepointTriggerType.MANUAL);
+ Savepoint sp1 =
+ new Savepoint(
+ 1, "sp1", SavepointTriggerType.MANUAL,
SavepointFormatType.CANONICAL, 123L);
spInfo.updateLastSavepoint(sp1);
observer.cleanupSavepointHistory(spInfo, conf);
Assertions.assertIterableEquals(
@@ -118,7 +127,9 @@ public class SavepointObserverTest {
Assertions.assertIterableEquals(
Collections.emptyList(), flinkService.getDisposedSavepoints());
- Savepoint sp2 = new Savepoint(2, "sp2", SavepointTriggerType.MANUAL);
+ Savepoint sp2 =
+ new Savepoint(
+ 2, "sp2", SavepointTriggerType.MANUAL,
SavepointFormatType.CANONICAL, 123L);
spInfo.updateLastSavepoint(sp2);
observer.cleanupSavepointHistory(spInfo, conf);
Assertions.assertIterableEquals(
@@ -159,5 +170,6 @@ public class SavepointObserverTest {
assertEquals(savepointInfo.getLastSavepoint(),
savepointInfo.getSavepointHistory().get(0));
assertEquals(
SavepointTriggerType.PERIODIC,
savepointInfo.getLastSavepoint().getTriggerType());
+ assertEquals(0L, savepointInfo.getLastSavepoint().getTriggerNonce());
}
}
diff --git
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/deployment/ApplicationObserverTest.java
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/deployment/ApplicationObserverTest.java
index c4575aa9..44570f39 100644
---
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/deployment/ApplicationObserverTest.java
+++
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/deployment/ApplicationObserverTest.java
@@ -24,10 +24,12 @@ import
org.apache.flink.kubernetes.operator.TestingFlinkService;
import org.apache.flink.kubernetes.operator.config.FlinkConfigManager;
import
org.apache.flink.kubernetes.operator.config.KubernetesOperatorConfigOptions;
import org.apache.flink.kubernetes.operator.crd.FlinkDeployment;
+import org.apache.flink.kubernetes.operator.crd.spec.FlinkVersion;
import org.apache.flink.kubernetes.operator.crd.spec.JobState;
import
org.apache.flink.kubernetes.operator.crd.status.JobManagerDeploymentStatus;
import org.apache.flink.kubernetes.operator.crd.status.JobStatus;
import org.apache.flink.kubernetes.operator.crd.status.ReconciliationState;
+import org.apache.flink.kubernetes.operator.crd.status.SavepointFormatType;
import org.apache.flink.kubernetes.operator.crd.status.SavepointTriggerType;
import
org.apache.flink.kubernetes.operator.exception.DeploymentFailedException;
import org.apache.flink.kubernetes.operator.reconciler.ReconciliationUtils;
@@ -46,8 +48,10 @@ import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
+import java.util.Map;
import java.util.stream.Collectors;
+import static
org.apache.flink.kubernetes.operator.config.KubernetesOperatorConfigOptions.OPERATOR_SAVEPOINT_FORMAT_TYPE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -68,6 +72,7 @@ public class ApplicationObserverTest {
public void before() {
var eventRecorder = new EventRecorder(kubernetesClient, (r, e) -> {});
observer = new ApplicationObserver(flinkService, configManager,
eventRecorder);
+ flinkService.clear();
}
@Test
@@ -224,6 +229,8 @@ public class ApplicationObserverTest {
@Test
public void observeSavepoint() throws Exception {
FlinkDeployment deployment = TestUtils.buildApplicationCluster();
+ Long timedOutNonce = 1L;
+ deployment.getSpec().getJob().setSavepointTriggerNonce(timedOutNonce);
Configuration conf =
configManager.getDeployConfig(deployment.getMetadata(),
deployment.getSpec());
flinkService.submitApplicationCluster(deployment.getSpec().getJob(),
conf, false);
@@ -283,17 +290,31 @@ public class ApplicationObserverTest {
kubernetesClient.v1().events().inNamespace(deployment.getMetadata().getNamespace())
.list().getItems().stream()
.filter(e -> e.getReason().contains("SavepointError"))
+ .filter(
+ e ->
+ e.getMessage()
+ .equals(
+ "Savepoint failed for
savepointTriggerNonce: "
+ +
timedOutNonce))
.count());
assertEquals(
1,
kubernetesClient.v1().events().inNamespace(deployment.getMetadata().getNamespace())
.list().getItems().stream()
.filter(e -> e.getReason().contains("SavepointError"))
+ .filter(
+ e ->
+ e.getMessage()
+ .equals(
+ "Savepoint failed for
savepointTriggerNonce: "
+ +
timedOutNonce))
.collect(Collectors.toList())
.get(0)
.getCount());
// savepoint success
+ Long firstNonce = 123L;
+ deployment.getSpec().getJob().setSavepointTriggerNonce(firstNonce);
flinkService.triggerSavepoint(
deployment.getStatus().getJobStatus().getJobId(),
SavepointTriggerType.MANUAL,
@@ -313,9 +334,19 @@ public class ApplicationObserverTest {
.getSavepointInfo()
.getLastSavepoint()
.getLocation());
+ assertEquals(
+ firstNonce,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getTriggerNonce());
assertFalse(SavepointUtils.savepointInProgress(deployment.getStatus().getJobStatus()));
// second attempt success
+ Long secondNonce = 456L;
+ deployment.getSpec().getJob().setSavepointTriggerNonce(secondNonce);
flinkService.triggerSavepoint(
deployment.getStatus().getJobStatus().getJobId(),
SavepointTriggerType.MANUAL,
@@ -337,9 +368,19 @@ public class ApplicationObserverTest {
.getSavepointInfo()
.getLastSavepoint()
.getLocation());
+ assertEquals(
+ secondNonce,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getTriggerNonce());
assertFalse(SavepointUtils.savepointInProgress(deployment.getStatus().getJobStatus()));
// application failure after checkpoint trigger
+ Long thirdNonce = 789L;
+ deployment.getSpec().getJob().setSavepointTriggerNonce(thirdNonce);
flinkService.triggerSavepoint(
deployment.getStatus().getJobStatus().getJobId(),
SavepointTriggerType.MANUAL,
@@ -359,6 +400,14 @@ public class ApplicationObserverTest {
.getSavepointInfo()
.getLastSavepoint()
.getLocation());
+ assertEquals(
+ secondNonce,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getTriggerNonce());
assertFalse(SavepointUtils.savepointInProgress(deployment.getStatus().getJobStatus()));
assertEquals(
@@ -366,12 +415,24 @@ public class ApplicationObserverTest {
kubernetesClient.v1().events().inNamespace(deployment.getMetadata().getNamespace())
.list().getItems().stream()
.filter(e -> e.getReason().contains("SavepointError"))
+ .filter(
+ e ->
+ e.getMessage()
+ .equals(
+ "Savepoint failed for
savepointTriggerNonce: "
+ + thirdNonce))
.count());
assertEquals(
- 2,
+ 1,
kubernetesClient.v1().events().inNamespace(deployment.getMetadata().getNamespace())
.list().getItems().stream()
.filter(e -> e.getReason().contains("SavepointError"))
+ .filter(
+ e ->
+ e.getMessage()
+ .equals(
+ "Savepoint failed for
savepointTriggerNonce: "
+ + thirdNonce))
.collect(Collectors.toList())
.get(0)
.getCount());
@@ -431,6 +492,118 @@ public class ApplicationObserverTest {
.size());
}
+ @Test
+ public void testSavepointFormat() throws Exception {
+ FlinkDeployment deployment = TestUtils.buildApplicationCluster();
+ Configuration conf =
+ configManager.getDeployConfig(deployment.getMetadata(),
deployment.getSpec());
+ flinkService.submitApplicationCluster(deployment.getSpec().getJob(),
conf, false);
+ bringToReadyStatus(deployment);
+ assertTrue(ReconciliationUtils.isJobRunning(deployment.getStatus()));
+
+ // canonical savepoint
+ Long firstNonce = 123L;
+ deployment.getSpec().getJob().setSavepointTriggerNonce(firstNonce);
+ flinkService.triggerSavepoint(
+ deployment.getStatus().getJobStatus().getJobId(),
+ SavepointTriggerType.MANUAL,
+ deployment.getStatus().getJobStatus().getSavepointInfo(),
+ conf);
+
+ observer.observe(deployment, readyContext);
+ observer.observe(deployment, readyContext);
+
assertFalse(SavepointUtils.savepointInProgress(deployment.getStatus().getJobStatus()));
+ assertEquals(
+ firstNonce,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getTriggerNonce());
+ assertEquals(
+ SavepointFormatType.CANONICAL,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getFormatType());
+
+ // native savepoint
+ Long secondNonce = 456L;
+ deployment.getSpec().getJob().setSavepointTriggerNonce(secondNonce);
+ deployment
+ .getSpec()
+ .setFlinkConfiguration(
+ Map.of(
+ OPERATOR_SAVEPOINT_FORMAT_TYPE.key(),
+
org.apache.flink.core.execution.SavepointFormatType.NATIVE.name()));
+ conf = configManager.getDeployConfig(deployment.getMetadata(),
deployment.getSpec());
+ flinkService.triggerSavepoint(
+ deployment.getStatus().getJobStatus().getJobId(),
+ SavepointTriggerType.MANUAL,
+ deployment.getStatus().getJobStatus().getSavepointInfo(),
+ conf);
+
+ observer.observe(deployment, readyContext);
+ observer.observe(deployment, readyContext);
+
assertFalse(SavepointUtils.savepointInProgress(deployment.getStatus().getJobStatus()));
+ assertEquals(
+ secondNonce,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getTriggerNonce());
+ assertEquals(
+ SavepointFormatType.NATIVE,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getFormatType());
+
+ // canonical for flink savepoint
+ Long thirdNonce = 789L;
+ deployment.getSpec().getJob().setSavepointTriggerNonce(thirdNonce);
+ deployment.getSpec().setFlinkVersion(FlinkVersion.v1_14);
+ deployment
+ .getSpec()
+ .setFlinkConfiguration(
+ Map.of(
+ OPERATOR_SAVEPOINT_FORMAT_TYPE.key(),
+
org.apache.flink.core.execution.SavepointFormatType.NATIVE.name()));
+ conf = configManager.getDeployConfig(deployment.getMetadata(),
deployment.getSpec());
+ flinkService.triggerSavepoint(
+ deployment.getStatus().getJobStatus().getJobId(),
+ SavepointTriggerType.MANUAL,
+ deployment.getStatus().getJobStatus().getSavepointInfo(),
+ conf);
+
+ observer.observe(deployment, readyContext);
+ observer.observe(deployment, readyContext);
+
assertFalse(SavepointUtils.savepointInProgress(deployment.getStatus().getJobStatus()));
+ assertEquals(
+ thirdNonce,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getTriggerNonce());
+ assertEquals(
+ SavepointFormatType.CANONICAL,
+ deployment
+ .getStatus()
+ .getJobStatus()
+ .getSavepointInfo()
+ .getLastSavepoint()
+ .getFormatType());
+ }
+
private void bringToReadyStatus(FlinkDeployment deployment) {
ReconciliationUtils.updateStatusForDeployedSpec(deployment, new
Configuration());
JobStatus jobStatus = new JobStatus();
diff --git
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/sessionjob/SessionJobObserverTest.java
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/sessionjob/SessionJobObserverTest.java
index 17075ed6..f42287f4 100644
---
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/sessionjob/SessionJobObserverTest.java
+++
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/observer/sessionjob/SessionJobObserverTest.java
@@ -197,7 +197,6 @@ public class SessionJobObserverTest {
public void testObserveSavepoint() throws Exception {
final var sessionJob = TestUtils.buildSessionJob();
final var readyContext =
TestUtils.createContextWithReadyFlinkDeployment();
-
// submit job
reconciler.reconcile(sessionJob, readyContext);
var jobID = sessionJob.getStatus().getJobStatus().getJobId();
@@ -213,12 +212,16 @@ public class SessionJobObserverTest {
Assertions.assertFalse(
SavepointUtils.savepointInProgress(sessionJob.getStatus().getJobStatus()));
+ Long firstNonce = 123L;
+ sessionJob.getSpec().getJob().setSavepointTriggerNonce(firstNonce);
flinkService.triggerSavepoint(
jobID, SavepointTriggerType.MANUAL, savepointInfo, new
Configuration());
Assertions.assertTrue(
SavepointUtils.savepointInProgress(sessionJob.getStatus().getJobStatus()));
Assertions.assertEquals("trigger_0", savepointInfo.getTriggerId());
+ Long secondNonce = 456L;
+ sessionJob.getSpec().getJob().setSavepointTriggerNonce(secondNonce);
flinkService.triggerSavepoint(
jobID, SavepointTriggerType.MANUAL, savepointInfo, new
Configuration());
Assertions.assertTrue(
@@ -231,6 +234,7 @@ public class SessionJobObserverTest {
observer.observe(sessionJob, readyContext); // pending
observer.observe(sessionJob, readyContext); // success
Assertions.assertEquals("savepoint_0",
savepointInfo.getLastSavepoint().getLocation());
+ Assertions.assertEquals(secondNonce,
savepointInfo.getLastSavepoint().getTriggerNonce());
Assertions.assertFalse(
SavepointUtils.savepointInProgress(sessionJob.getStatus().getJobStatus()));
}
diff --git
a/helm/flink-kubernetes-operator/crds/flinkdeployments.flink.apache.org-v1.yml
b/helm/flink-kubernetes-operator/crds/flinkdeployments.flink.apache.org-v1.yml
index ba33f580..4f0563db 100644
---
a/helm/flink-kubernetes-operator/crds/flinkdeployments.flink.apache.org-v1.yml
+++
b/helm/flink-kubernetes-operator/crds/flinkdeployments.flink.apache.org-v1.yml
@@ -9162,6 +9162,14 @@ spec:
- UPGRADE
- UNKNOWN
type: string
+ formatType:
+ enum:
+ - CANONICAL
+ - NATIVE
+ - UNKNOWN
+ type: string
+ triggerNonce:
+ type: integer
type: object
triggerId:
type: string
@@ -9174,6 +9182,12 @@ spec:
- UPGRADE
- UNKNOWN
type: string
+ formatType:
+ enum:
+ - CANONICAL
+ - NATIVE
+ - UNKNOWN
+ type: string
savepointHistory:
items:
properties:
@@ -9188,6 +9202,14 @@ spec:
- UPGRADE
- UNKNOWN
type: string
+ formatType:
+ enum:
+ - CANONICAL
+ - NATIVE
+ - UNKNOWN
+ type: string
+ triggerNonce:
+ type: integer
type: object
type: array
lastPeriodicSavepointTimestamp:
diff --git
a/helm/flink-kubernetes-operator/crds/flinksessionjobs.flink.apache.org-v1.yml
b/helm/flink-kubernetes-operator/crds/flinksessionjobs.flink.apache.org-v1.yml
index ec20e56c..1ab22032 100644
---
a/helm/flink-kubernetes-operator/crds/flinksessionjobs.flink.apache.org-v1.yml
+++
b/helm/flink-kubernetes-operator/crds/flinksessionjobs.flink.apache.org-v1.yml
@@ -112,6 +112,14 @@ spec:
- UPGRADE
- UNKNOWN
type: string
+ formatType:
+ enum:
+ - CANONICAL
+ - NATIVE
+ - UNKNOWN
+ type: string
+ triggerNonce:
+ type: integer
type: object
triggerId:
type: string
@@ -124,6 +132,12 @@ spec:
- UPGRADE
- UNKNOWN
type: string
+ formatType:
+ enum:
+ - CANONICAL
+ - NATIVE
+ - UNKNOWN
+ type: string
savepointHistory:
items:
properties:
@@ -138,6 +152,14 @@ spec:
- UPGRADE
- UNKNOWN
type: string
+ formatType:
+ enum:
+ - CANONICAL
+ - NATIVE
+ - UNKNOWN
+ type: string
+ triggerNonce:
+ type: integer
type: object
type: array
lastPeriodicSavepointTimestamp: