For Tanzu Application Platform (as of 1.4), as stated in the documentation here , Out of the Box (OOTB) Supply Chains supports the following Workload Types:
type=web
... intended for scalable web applications. A Knative Service resource is created. Scale to Zero, Zero to N are supported.type=server
... intended for traditional web applications. K8s standard Deployment and Service resources are created.type=worker
... intended for background applications processing queues. A K8s standard Deployment is created.
This time, add type=cronjob
here so that K8s standard CronJob resource can be created.
TAP's workload is managed by Cartographer. Customizing the resources created by Workload is typically done by adding a ClusterSupplyChain resource. However, when creating a Supply Chain from scratch, it is necessary to define the components that make up the Supply Chain like bellow
- Retrieve the source code
- Scan the vulnerability of the source code vulnerability
- Test the source code
- Build the container image
- Scan the vulnerability of the container image
- Create manifests
- Package and push the manifests
- etc ... (Tutorial here)
Redefining what is defined in TAP's OOTB Supply Chain is a pain.
TAP allows you to customize only the "Create manifests" part in the OOTB Supply Chain.
Documentation here.
The documentation gives an example of creating an Ingress resource in addition to a resource of type=server
.
You can define the manifest template you want the supply chain to generate in Cartographer's ClusterConfigTemplate.
Try it in the environment created in this article.
table of contents
- Defining a ClusterConfigTemplate
- (Optional) Change settings with Overlays
- Creating CronJob Workloads
Defining a ClusterConfigTemplate
Define CronJob's template in ClusterConfigTemplate as follows:
cat <<EOF > cronjob-template.yaml
apiVersion: carto.run/v1alpha1
kind: ClusterConfigTemplate
metadata:
name: cronjob-template
spec:
configPath: .data
lifecycle: mutable
ytt: |
#@ load("@ytt:data", "data")
#@ load("@ytt:yaml", "yaml")
#@ def merge_labels(fixed_values):
#@ labels = {}
#@ if hasattr(data.values.workload.metadata, "labels"):
#@ labels.update(data.values.workload.metadata.labels)
#@ end
#@ labels.update(fixed_values)
#@ return labels
#@ end
#@ def update_config(config):
#@ values = {}
#@ values.update(config)
#@ spec = dict(values["spec"])
#@ spec.update({"restartPolicy": data.values.params.restartPolicy if hasattr(data.values.params, "restartPolicy") else "Never"})
#@ workload = dict(spec["containers"][0])
#@ if hasattr(data.values.params, "command"):
#@ workload.update({"command": data.values.params.command})
#@ end
#@ if hasattr(data.values.params, "args"):
#@ workload.update({"args": data.values.params.args})
#@ end
#@ spec["containers"][0] = workload
#@ values["spec"] = spec
#@ return values
#@ end
#@ def delivery():
apiVersion: batch/v1
kind: CronJob
metadata:
name: #@ data.values.workload.metadata.name
annotations:
kapp.k14s.io/update-strategy: "fallback-on-replace"
ootb.apps.tanzu.vmware.com/servicebinding-workload: "true"
kapp.k14s.io/change-rule: "upsert after upserting servicebinding.io/ServiceBindings"
labels: #@ merge_labels({ "app.kubernetes.io/component": "run", "carto.run/workload-name": data.values.workload.metadata.name })
spec:
schedule: #@ data.values.params.schedule if hasattr(data.values.params, "schedule") else "0 15 * * *"
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3
concurrencyPolicy: Forbid
jobTemplate:
metadata:
labels: #@ data.values.config.metadata.labels
spec:
backoffLimit: 0
template: #@ update_config(data.values.config)
#@ end
---
apiVersion: v1
kind: ConfigMap
metadata:
name: #@ data.values.workload.metadata.name + "-cronjob"
labels: #@ merge_labels({ "app.kubernetes.io/component": "config" })
data:
delivery.yml: #@ yaml.encode(delivery())
EOF
Instead of K8s standard CronJob, If you want to use an extended scheduler like Argo Workflows or Furiko, you can also change this ClusterConfigTemplate.
This CronJob manifest will eventually be deployed by the Deliverable, so the Service Account that manages the Deliverable must have permission to create the CronJob.
Labeling the ClusterRole apps.tanzu.vmware.com/aggregate-to-deliverable: "true"
binds it to the Service Account that manages the Deliverable.
cat <<EOF > deliverable-with-cronjob.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: deliverable-with-cronjob
labels:
apps.tanzu.vmware.com/aggregate-to-deliverable: "true"
rules:
- apiGroups:
- batch
resources:
- cronjobs
verbs:
- get
- list
- watch
- create
- patch
- update
- delete
- deletecollection
EOF
apply these.
# In case of Muti Cluster configuration, in Build Cluster
kubectl apply -f cronjob-template.yaml
# In case of Muti Cluster configuration, in Run Cluster
kubectl apply -f deliverable-with-cronjob.yml
Finally, add a setting to add Workload Type to tap-values.yaml
.
ootb_supply_chain_basic: # if supply_chain value is basic
# or ootb_supply_chain_testing: if supply_chain value is testing
# or ootb_supply_chain_testing_scanning: if supply_chain value is testing_scanning
supported_workloads:
- type: web
cluster_config_template_name: config-template
- type: server
cluster_config_template_name: server-template
- type: worker
cluster_config_template_name: worker-template
- type: cronjob
cluster_config_template_name: cronjob-template # <---
Reflect changes in tap-values.yaml
.
tanzu package installed update -n tap-install tap --values-file tap-values.yaml
Once the update is complete, you can see that the source-to-url Supply Chain has been added with type=cronjob
.
$ tanzu apps cluster-supply-chain get source-to-url
---
# source-to-url: Ready
---
Supply Chain Selectors
TYPE KEY OPERATOR VALUE
expressions apps.tanzu.vmware.com/workload-type In web
expressions apps.tanzu.vmware.com/workload-type In server
expressions apps.tanzu.vmware.com/workload-type In worker
expressions apps.tanzu.vmware.com/workload-type In cronjob
Currently, the Service Binding function cannot be used. Bind to CronJob is not supported.
(Optional) Change settings with Overlays
You may not like the procedure of updating the TAP by running the bellow commands after installing TAP as it is not declarative installation of TAP.
kubectl apply -f cronjob-template.yaml
kubectl apply -f deliverable-with-cronjob.yml
ClusterConfigTemplate and ClusterRole can be created at the same time when installing/updating TAP with tanzu package install
or tanzu package installed update
.
In this case, create a ClusterConfigTemplate and a ClusterRole as overlays as follows:
# In case of Muti Cluster configuration, in Build Cluster
kubectl -n tap-install create secret generic ootb-templates-cronjob-template \
-o yaml \
--dry-run=client \
--from-file=cronjob-template.yaml \
| kubectl apply -f-
# In case of Muti Cluster configuration, in Run Cluster
kubectl -n tap-install create secret generic tap-auth-deliverable-with-cronjob \
-o yaml \
--dry-run=client \
--from-file=deliverable-with-cronjob.yml \
| kubectl apply -f-
Add the following settings to tap-values.yaml
.
package_overlays:
- name: ootb-templates
secrets:
- name: ootb-templates-cronjob-template # in Build Cluster for Muti Cluster configuration
- name: tap-auth
secrets:
- name: tap-auth-deliverable-with-cronjob # in Run Cluster for Muti Cluster configuration
For first-time installation,
tanzu package install tap -p tap.tanzu.vmware.com -v 1.4.2 --values-file tap-values.yaml -n tap-install
For update
tanzu package installed update -n tap-install tap --values-file tap-values.yaml
Now you can use type=cronjob
.
Creating CronJob Workloads
Let's create various CronJobs.
A Simple CronJob
Let's create a sample from Kubernetes official documentation.
Create a Workload to create a CronJob with the following command. This time, --image
specifies the container image to be run by CronJob.
tanzu apps workload apply \
-n demo \
--type cronjob \
--image ghcr.io/making/busybox \
--param-yaml 'command=["/bin/sh", "-c", "date; echo Hello from TAP"]' \
--param schedule="* * * * *" \
--app cronjob-demo \
cronjob-demo
As in the official document, when running with
--image busybox:1.28
, the following error occurred in the ImageRepository resource.unable to pull image "busybox:1.28": Expected an Image but got: application/vnd.docker.distribution.manifest.list.v2+json
To fix the problem, I did a relocation like this:docker pull busybox docker tag busybox ghcr.io/making/busybox docker push busybox
After a while a CronJob will be created and more Jobs will be executed.
$ tanzu apps workload get cronjob-demo --namespace demo
๐ก Overview
name: cronjob-demo
type: cronjob
namespace: demo
๐พ Source
type: image
image: ghcr.io/making/busybox
๐ฆ Supply Chain
name: basic-image-to-url
NAME READY HEALTHY UPDATED RESOURCE
image-provider True True 10m imagerepositories.source.apps.tanzu.vmware.com/cronjob-demo
config-provider True True 10m podintents.conventions.carto.run/cronjob-demo
app-config True True 10m configmaps/cronjob-demo-cronjob
service-bindings True True 10m configmaps/cronjob-demo-with-claims
api-descriptors True True 10m configmaps/cronjob-demo-with-api-descriptors
config-writer True True 10m runnables.carto.run/cronjob-demo-config-writer
๐ Delivery
name: delivery-basic
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 9m34s imagerepositories.source.apps.tanzu.vmware.com/cronjob-demo-delivery
deployer True True 60s apps.kappctrl.k14s.io/cronjob-demo
๐ฌ Messages
No messages found.
๐ถ Pods
NAME READY STATUS RESTARTS AGE
cronjob-demo-28018560-zdp85 0/1 Completed 0 4s
cronjob-demo-config-writer-l68rw-pod 0/1 Completed 0 10m
To see logs: "tanzu apps workload tail cronjob-demo --namespace demo --timestamp --since 1h"
Check the created CronJobs and Jobs.
$ kubectl get cronjob,job -n demo
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/cronjob-demo * * * * * False 0 23s 81s
NAME COMPLETIONS DURATION AGE
job.batch/cronjob-demo-28018560 1/1 7s 23s
Check the logs. time is displayed.
$ kubectl logs -n demo cronjob-demo-28018560-zdp85
Mon Apr 10 08:00:04 UTC 2023
Hello from TAP
Since the schedule
is * * * * *
, this Job will run every minute.
After confirming, delete the workload.
tanzu apps workload delete -n demo cronjob-demo
A CronJob that just runs curl
Create a Workload to create a CronJob with the following command.
tanzu apps workload apply \
-n demo \
--type cronjob \
--image ghcr.io/making/curl \
--param-yaml 'command=["curl"]' \
--param-yaml 'args=["-s", "https://httpbin.org/get"]' \
--param schedule="* * * * *" \
--app hello-curl \
hello-curl
After a while a CronJob will be created and more Jobs will be executed.
$ tanzu apps workload get hello-curl --namespace demo
๐ก Overview
name: hello-curl
type: cronjob
namespace: demo
๐พ Source
type: image
image: ghcr.io/making/curl
๐ฆ Supply Chain
name: basic-image-to-url
NAME READY HEALTHY UPDATED RESOURCE
image-provider True True 106s imagerepositories.source.apps.tanzu.vmware.com/hello-curl
config-provider True True 102s podintents.conventions.carto.run/hello-curl
app-config True True 102s configmaps/hello-curl-cronjob
service-bindings True True 102s configmaps/hello-curl-with-claims
api-descriptors True True 102s configmaps/hello-curl-with-api-descriptors
config-writer True True 91s runnables.carto.run/hello-curl-config-writer
๐ Delivery
name: delivery-basic
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 44s imagerepositories.source.apps.tanzu.vmware.com/hello-curl-delivery
deployer True True 42s apps.kappctrl.k14s.io/hello-curl
๐ฌ Messages
No messages found.
๐ถ Pods
NAME READY STATUS RESTARTS AGE
hello-curl-28018564-2rlgc 0/1 Completed 0 11s
hello-curl-config-writer-k76bd-pod 0/1 Completed 0 101s
To see logs: "tanzu apps workload tail hello-curl --namespace demo --timestamp --since 1h"
Check the created CronJobs and Jobs.
$ kubectl get cronjob,job -n demo
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/hello-curl * * * * * False 0 42s 76s
NAME COMPLETIONS DURATION AGE
job.batch/hello-curl-28018564 1/1 8s 42s
Check the logs. The execution result of curl is output.
$ kubectl logs -n demo hello-curl-28018564-2rlgc
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/8.0.1-DEV",
"X-Amzn-Trace-Id": "Root=1-6433c2f5-5f649b191de9f1ea4e83fb8f"
},
"origin": "220.242.176.124",
"url": "https://httpbin.org/get"
}
After confirming, delete the workload.
tanzu apps workload delete -n demo hello-curl
CronJob to run Python Script
Next, create a container image to be run by CronJob from the source code. Convert the Python code from https://github.com/making/hello-python into a container image with Cloud Native Buildpacks and run CronJob.
Create a Workload to create a CronJob with the following command. This time, specify the URL of the source code with --git-repo
.
tanzu apps workload apply \
-n demo \
--type cronjob \
--git-repo https://github.com/making/hello-python\
--git-branch main\
--param schedule="* * * * *" \
--app hello-python \
--label apps.tanzu.vmware.com/has-tests=true \
hello-python
After a while a CronJob will be created and more Jobs will be executed.
$ tanzu apps workload get hello-python --namespace demo
๐ก Overview
name: hello-python
type: cronjob
namespace: demo
๐พ Source
type: git
url: https://github.com/making/hello-python
branch: main
๐ฆ Supply Chain
name: source-to-url
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 4m58s gitrepositories.source.toolkit.fluxcd.io/hello-python
image-provider True True 3m58s images.kpack.io/hello-python
config-provider True True 3m52s podintents.conventions.carto.run/hello-python
app-config True True 3m52s configmaps/hello-python-cronjob
service-bindings True True 3m52s configmaps/hello-python-with-claims
api-descriptors True True 3m52s configmaps/hello-python-with-api-descriptors
config-writer True True 3m38s runnables.carto.run/hello-python-config-writer
๐ Delivery
name: delivery-basic
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 2m54s imagerepositories.source.apps.tanzu.vmware.com/hello-python-delivery
deployer True True 2m52s apps.kappctrl.k14s.io/hello-python
๐ฌ Messages
No messages found.
๐ถ Pods
NAME READY STATUS RESTARTS AGE
hello-python-28018837-25db8 0/1 Completed 0 32s
hello-python-build-1-build-pod 0/1 Completed 0 4m57s
hello-python-config-writer-ch8z4-pod 0/1 Completed 0 3m50s
Check the created CronJobs and Jobs.
$ kubectl get cronjob,job -n demo
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/hello-python * * * * * False 0 45s 3m6s
NAME COMPLETIONS DURATION AGE
job.batch/hello-python-28018837 1/1 5s 45s
Check the logs.
$ kubectl logs -n demo hello-python-28018837-25db8
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.28.2",
"X-Amzn-Trace-Id": "Root=1-643402ed-0e6ea59220b36d3636bd2a41"
},
"origin": "220.242.176.124",
"url": "https://httpbin.org/get"
}
After confirming, delete the workload.
tanzu apps workload delete -n demo hello-python
CronJob to run Spring Batch Job
Next, the batch processing source code https://github.com/making/billing-job implemented by Spring Batch will be converted into a container image with Cloud Native Buildpacks and executed by CronJob.
Create a Workload to create a CronJob with the following command.
tanzu apps workload apply \
-n demo \
--type cronjob \
--git-repo https://github.com/making/billing-job \
--git-branch master \
--param schedule="0 15 * * *" \
--app billing-job \
--label apps.tanzu.vmware.com/has-tests=true \
--build-env BP_JVM_VERSION=17 \
--env BPL_JVM_THREAD_COUNT=8 \
--env JAVA_TOOL_OPTIONS=-Dmanagement.health.probes.enabled=false \
billing-job
--env JAVA_TOOL_OPTIONS=-Dmanagement.health.probes.enabled=false
is added to disable the probe settings that are automatically added when using Spring Boot Actuator.
Documentation here
A CronJob will be created after a while. Since we have scheduled it to run at 00:00 JST, the Job has not yet been created.
$ tanzu apps workload get billing-job --namespace demo
๐ก Overview
name: billing-job
type: cronjob
namespace: demo
๐พ Source
type: git
url: https://github.com/making/billing-job
branch: master
๐ฆ Supply Chain
name: source-to-url
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 4m51s gitrepositories.source.toolkit.fluxcd.io/billing-job
image-provider True True 3m39s images.kpack.io/billing-job
config-provider True True 3m34s podintents.conventions.carto.run/billing-job
app-config True True 3m34s configmaps/billing-job-cronjob
service-bindings True True 3m33s configmaps/billing-job-with-claims
api-descriptors True True 3m33s configmaps/billing-job-with-api-descriptors
config-writer True True 3m17s runnables.carto.run/billing-job-config-writer
๐ Delivery
name: delivery-basic
NAME READY HEALTHY UPDATED RESOURCE
source-provider True True 2m48s imagerepositories.source.apps.tanzu.vmware.com/billing-job-delivery
deployer True True 2m46s apps.kappctrl.k14s.io/billing-job
๐ฌ Messages
No messages found.
๐ถ Pods
NAME READY STATUS RESTARTS AGE
billing-job-build-1-build-pod 0/1 Completed 0 4m52s
billing-job-config-writer-mlhff-pod 0/1 Completed 0 3m33s
To see logs: "tanzu apps workload tail billing-job --namespace demo --timestamp --since 1h"
Check the created CronJob.
$ kubectl get cronjob,job -n demo
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/billing-job 0 15 * * * False 0 <none> 3m48s
Create a Job manually.
kubectl create job -n demo --from cronjob/billing-job test-run
Check the created CronJobs and Jobs.
$ kubectl get cronjob,job -n demo
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/billing-job 0 15 * * * False 0 <none> 5m12s
NAME COMPLETIONS DURATION AGE
job.batch/test-run 1/1 13s 26s
Check the logs.
$ kubectl logs -n demo test-run-c9r5d
Setting Active Processor Count to 8
Calculating JVM memory based on 4528180K available memory
For more information on this calculation, see https://paketo.io/docs/reference/java-reference/#memory-calculator
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx4191438K -XX:MaxMetaspaceSize=72549K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 4528180K, Thread Count: 8, Loaded Class Count: 10395, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 124 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Dmanagement.health.probes.enabled="false" -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -XX:+ExitOnOutOfMemoryError -XX:ActiveProcessorCount=8 -XX:MaxDirectMemorySize=10M -Xmx4191438K -XX:MaxMetaspaceSize=72549K -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.5)
2023-04-10T16:38:45.371Z INFO 1 --- [ main] lol.maki.billing.BillingJobApplication : Starting BillingJobApplication v0.0.1-SNAPSHOT using Java 17.0.6 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2023-04-10T16:38:45.376Z INFO 1 --- [ main] lol.maki.billing.BillingJobApplication : No active profile set, falling back to 1 default profile: "default"
2023-04-10T16:38:46.207Z INFO 1 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2023-04-10T16:38:46.436Z INFO 1 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:b918459b-19ff-41d4-8f50-d482bba0dee8 user=SA
2023-04-10T16:38:46.440Z INFO 1 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2023-04-10T16:38:46.829Z INFO 1 --- [ main] lol.maki.billing.BillingJobApplication : Started BillingJobApplication in 1.968 seconds (process running for 2.419)
2023-04-10T16:38:46.832Z INFO 1 --- [ main] o.s.b.a.b.JobLauncherApplicationRunner : Running default command line with: []
2023-04-10T16:38:46.844Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.845Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.860Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.860Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE I1 where I1.JOB_NAME = ? and I1.JOB_INSTANCE_ID in (SELECT max(I2.JOB_INSTANCE_ID) from BATCH_JOB_INSTANCE I2 where I2.JOB_NAME = ?)]
2023-04-10T16:38:46.868Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.869Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.871Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.871Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.872Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.872Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.878Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.879Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]
2023-04-10T16:38:46.889Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.889Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT into BATCH_JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, VERSION, CREATE_TIME, LAST_UPDATED) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:46.892Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing SQL batch update [INSERT into BATCH_JOB_EXECUTION_PARAMS(JOB_EXECUTION_ID, PARAMETER_NAME, PARAMETER_TYPE, PARAMETER_VALUE, IDENTIFYING) values (?, ?, ?, ?, ?)] with a batch size of 100
2023-04-10T16:38:46.893Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT into BATCH_JOB_EXECUTION_PARAMS(JOB_EXECUTION_ID, PARAMETER_NAME, PARAMETER_TYPE, PARAMETER_VALUE, IDENTIFYING) values (?, ?, ?, ?, ?)]
2023-04-10T16:38:46.901Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.902Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO BATCH_JOB_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, JOB_EXECUTION_ID) VALUES(?, ?, ?)]
2023-04-10T16:38:46.904Z INFO 1 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=BillingJob]] launched with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}]
2023-04-10T16:38:46.922Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.923Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:46.928Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.928Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT COUNT(*) FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?]
2023-04-10T16:38:46.932Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.932Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_JOB_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, CREATE_TIME = ?, LAST_UPDATED = ? where JOB_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:46.936Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.936Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT SE.STEP_EXECUTION_ID, SE.STEP_NAME, SE.START_TIME, SE.END_TIME, SE.STATUS, SE.COMMIT_COUNT, SE.READ_COUNT, SE.FILTER_COUNT, SE.WRITE_COUNT, SE.EXIT_CODE, SE.EXIT_MESSAGE, SE.READ_SKIP_COUNT, SE.WRITE_SKIP_COUNT, SE.PROCESS_SKIP_COUNT, SE.ROLLBACK_COUNT, SE.LAST_UPDATED, SE.VERSION, SE.CREATE_TIME, JE.JOB_EXECUTION_ID, JE.START_TIME, JE.END_TIME, JE.STATUS, JE.EXIT_CODE, JE.EXIT_MESSAGE, JE.CREATE_TIME, JE.LAST_UPDATED, JE.VERSION from BATCH_JOB_EXECUTION JE join BATCH_STEP_EXECUTION SE on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID where JE.JOB_INSTANCE_ID = ? and SE.STEP_NAME = ? order by SE.CREATE_TIME desc, SE.STEP_EXECUTION_ID desc]
2023-04-10T16:38:46.940Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.940Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT COUNT(*) from BATCH_JOB_EXECUTION JE JOIN BATCH_STEP_EXECUTION SE on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID where JE.JOB_INSTANCE_ID = ? and SE.STEP_NAME = ?]
2023-04-10T16:38:46.942Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.942Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT into BATCH_STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED, CREATE_TIME) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:46.943Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.943Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO BATCH_STEP_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, STEP_EXECUTION_ID) VALUES(?, ?, ?)]
2023-04-10T16:38:46.945Z INFO 1 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [BilliProcessing]
2023-04-10T16:38:46.946Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.947Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:46.948Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:46.948Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:46.955Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:46.955Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.023Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing SQL batch update [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.023Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.027Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.028Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.029Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.029Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.030Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:47.030Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.034Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing SQL batch update [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.035Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.037Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.038Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.039Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.039Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.040Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:47.040Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.042Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.042Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.045Z INFO 1 --- [ main] o.s.batch.core.step.AbstractStep : Step: [BilliProcessing] executed in 99ms
2023-04-10T16:38:47.045Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.045Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.046Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:47.046Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.048Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.048Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_JOB_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE JOB_EXECUTION_ID = ?]
2023-04-10T16:38:47.051Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:47.052Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.055Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
2023-04-10T16:38:47.056Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT COUNT(*) FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?]
2023-04-10T16:38:47.057Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
2023-04-10T16:38:47.057Z DEBUG 1 --- [ main] o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [UPDATE BATCH_JOB_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, CREATE_TIME = ?, LAST_UPDATED = ? where JOB_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.069Z INFO 1 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=BillingJob]] completed with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}] and the following status: [COMPLETED] in 129ms
2023-04-10T16:38:47.082Z INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2023-04-10T16:38:47.088Z INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
Native Memory Tracking:
...
After confirming, delete the workload.
tanzu apps workload delete -n demo billing-job
CronJobs can now be created from TAP. Customizing TAP opens up new possibilities.
FYI, the workload for backing up this blog and saving it to S3 is here.