Skip to content

Commit d308449

Browse files
control-service: Adopt use of the V1CronJob API (#767)
To allow for the automatic job clean up of manually ran data jobs and builder jobs, the VDK control service must use the V1CronJob API. However, V1CronJobs are available from Kubernetes 1.21 onwards, and VDK must be able to run on older versions of Kubernetes. This change manages this by duplicating relevant methods, and relying on a feature flag to determine whether the Kubernetes cluster supports V1CronJobs, and defaulting back to V1beta1CronJobs in the case where it does not. Testing done: all existing unit and intergration tests pass, added unit tests Signed-off-by: Gabriel Georgiev <gageorgiev@vmware.com>
1 parent 602adbb commit d308449

File tree

8 files changed

+575
-87
lines changed

8 files changed

+575
-87
lines changed

projects/control-service/projects/base/src/main/java/com/vmware/taurus/base/FeatureFlags.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class FeatureFlags {
2626
@Value("${featureflag.authorization.enabled:false}")
2727
boolean authorizationEnabled = false;
2828

29+
2930
@Value("${datajobs.security.kerberos.enabled:false}")
3031
boolean krbAuthEnabled = false;
3132

projects/control-service/projects/pipelines_control_service/src/integration-test/resources/application-test.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ datajobs.vdk.image=registry.hub.docker.com/versatiledatakit/quickstart-vdk:relea
1414

1515
datajobs.deployment.k8s.kubeconfig=${DEPLOYMENT_K8S_KUBECONFIG}
1616
datajobs.deployment.k8s.namespace=${DEPLOYMENT_K8S_NAMESPACE}
17+
datajobs.control.k8s.k8sSupportsV1CronJob=false
1718

1819
datajobs.control.k8s.kubeconfig=${CONTROL_K8S_KUBECONFIG}
1920
datajobs.control.k8s.namespace=${CONTROL_K8S_NAMESPACE}

projects/control-service/projects/pipelines_control_service/src/main/java/com/vmware/taurus/service/KubernetesService.java

Lines changed: 426 additions & 59 deletions
Large diffs are not rendered by default.

projects/control-service/projects/pipelines_control_service/src/main/java/com/vmware/taurus/service/kubernetes/ControlKubernetesService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ public class ControlKubernetesService extends KubernetesService {
2121

2222
// those should be null/empty when Control service is deployed in k8s hence default is empty
2323
public ControlKubernetesService(@Value("${datajobs.control.k8s.namespace:}") String namespace,
24-
@Value("${datajobs.control.k8s.kubeconfig:}") String kubeconfig) {
25-
super(namespace, kubeconfig, log);
24+
@Value("${datajobs.control.k8s.kubeconfig:}") String kubeconfig,
25+
@Value("${datajobs.control.k8s.k8sSupportsV1CronJob}") boolean k8sSupportsV1CronJob) {
26+
super(namespace, kubeconfig, k8sSupportsV1CronJob, log);
2627
}
2728
}

projects/control-service/projects/pipelines_control_service/src/main/java/com/vmware/taurus/service/kubernetes/DataJobsKubernetesService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@
2323
public class DataJobsKubernetesService extends KubernetesService {
2424

2525
public DataJobsKubernetesService(@Value("${datajobs.deployment.k8s.namespace:}") String namespace,
26-
@Value("${datajobs.deployment.k8s.kubeconfig:}") String kubeconfig) {
27-
super(namespace, kubeconfig, log);
26+
@Value("${datajobs.deployment.k8s.kubeconfig:}") String kubeconfig,
27+
@Value("${datajobs.control.k8s.k8sSupportsV1CronJob}") boolean k8sSupportsV1CronJob) {
28+
super(namespace, kubeconfig, k8sSupportsV1CronJob, log);
2829
if (StringUtils.isBlank(kubeconfig) && !new File(kubeconfig).isFile()) {
2930
log.warn("Data Jobs (Deployment) Kubernetes service may not have been correctly bootstrapped. {} file is missing " +
3031
"Will try to use same cluster as control Plane. But this is not recommended in production.",

projects/control-service/projects/pipelines_control_service/src/main/resources/application.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ featureflag.authorization.enabled=false
4343
datajobs.authorization.webhook.endpoint=
4444
datajobs.authorization.jwt.claim.username=username
4545

46+
4647
# Data Jobs post webhook settings (Create and Delete)
4748
datajobs.post.create.webhook.endpoint=
4849
datajobs.post.create.webhook.internal.errors.retries=3
@@ -77,6 +78,7 @@ logging.level.io.swagger.models.parameters.AbstractSerializableParameter=ERROR
7778

7879
datajobs.control.k8s.namespace=
7980
datajobs.control.k8s.kubeconfig=${HOME}/.kube/config
81+
datajobs.control.k8s.k8sSupportsV1CronJob=false
8082
# Location to a K8s cronjob yaml file which will be used as a template
8183
# for all data jobs. If the location is missing, the default internal
8284
# cronjob yaml resource will be used (see k8s-data-job-template.yaml).

projects/control-service/projects/pipelines_control_service/src/test/java/com/vmware/taurus/service/KubernetesServiceStartJobWithArgumentsIT.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class KubernetesServiceStartJobWithArgumentsIT {
3232
public void getMockKubernetesServiceForVdkRunExtraArgsTests() throws Exception {
3333

3434
kubernetesService = Mockito.mock(KubernetesService.class);
35+
Mockito.when(kubernetesService.getK8sSupportsV1CronJob()).thenReturn(false);
3536
V1beta1CronJob internalCronjobTemplate = getValidCronJobForVdkRunExtraArgsTests();
3637
BatchV1beta1Api mockBatch = Mockito.mock(BatchV1beta1Api.class);
3738
Mockito.when(kubernetesService.initBatchV1beta1Api()).thenReturn(mockBatch);
@@ -131,15 +132,15 @@ public void testStartCronJobWithEmptyArgumentsForVdkRun() {
131132
}
132133

133134
private V1beta1CronJob getValidCronJobForVdkRunExtraArgsTests() throws Exception {
134-
KubernetesService service = new DataJobsKubernetesService("default", "someConfig");
135+
KubernetesService service = new DataJobsKubernetesService("default", "someConfig", false);
135136
// V1betaCronJob initializing snippet copied from tests above, using reflection
136137
service.afterPropertiesSet();
137-
Method loadInternalCronjobTemplate = KubernetesService.class.getDeclaredMethod("loadInternalCronjobTemplate");
138-
if (loadInternalCronjobTemplate == null) {
139-
Assertions.fail("The method 'loadInternalCronjobTemplate' does not exist.");
138+
Method loadInternalV1beta1CronjobTemplate = KubernetesService.class.getDeclaredMethod("loadInternalV1beta1CronjobTemplate");
139+
if (loadInternalV1beta1CronjobTemplate == null) {
140+
Assertions.fail("The method 'loadInternalV1beta1CronjobTemplate' does not exist.");
140141
}
141-
loadInternalCronjobTemplate.setAccessible(true);
142-
V1beta1CronJob internalCronjobTemplate = (V1beta1CronJob) loadInternalCronjobTemplate.invoke(service);
142+
loadInternalV1beta1CronjobTemplate.setAccessible(true);
143+
V1beta1CronJob internalCronjobTemplate = (V1beta1CronJob) loadInternalV1beta1CronjobTemplate.invoke(service);
143144
var container = internalCronjobTemplate.getSpec()
144145
.getJobTemplate()
145146
.getSpec()

0 commit comments

Comments
 (0)