Skip to content
This repository has been archived by the owner on Jan 19, 2024. It is now read-only.

Commit

Permalink
docs: Document ttlSecondsAfterFinished (#126) (#147)
Browse files Browse the repository at this point in the history
* docs:  Document ttlSecondsAfterFinished (#126)

Signed-off-by: Paolo Chila <[email protected]>

* fixup! docs:  Document ttlSecondsAfterFinished (#126)
  • Loading branch information
pchila authored Jan 11, 2022
1 parent 022cdfe commit d93645c
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
- [Send start/finished event if the job config.yaml can't be found](#send-startfinished-event-if-the-job-configyaml-cant-be-found)
- [Additional Event Data](#additional-event-data)
- [Remote Control Plane](#remote-control-plane)
- [Job clean-up](#job-clean-up)
- [How to validate a job configuration](#how-to-validate-a-job-configuration)
- [Endless Possibilities](#endless-possibilities)
- [Credits](#credits)
Expand Down Expand Up @@ -567,6 +568,38 @@ If you are using the service in a remote control plane setup make sure the distr
events used in the `job/config.yaml`. Just edit the `PUBSUB_TOPIC` environment variable in the distributor deployment
configuration to fit your needs.

### Job clean-up

Jobs objects are kept in kubernetes after completion to allow checking for status or logs inspections/retrieval.
This is not always desirable so kubernetes allows for [automatic clean-up of finished jobs](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/)
using `ttlSecondsAfterFinished` property in the job spec.

Jobs created by the executor service will still be available for a time after (successful or failed) completion.
The default value of the time-to-live (TTL) for completed jobs is `21600` seconds (6 hours).

In order to set a different TTL for jobs add the `ttlSecondsAfterFinished` property in the task definition, for example:

```yaml
tasks:
- name: "Run locust tests"
files:
- locust/basic.py
- locust/import.py
- locust/locust.conf
image: "locustio/locust"
cmd:
- locust
args:
- '--config'
- /keptn/locust/locust.conf
- '-f'
- /keptn/locust/basic.py
- '--host'
- $(HOST)
# the corresponding job for this task will be cleaned up 10 minutes (600 seconds) after completion
ttlSecondsAfterFinished: 600
```

## How to validate a job configuration

`job-lint` is a simple cli tool that validates any given job configuration file and shows possible errors.
Expand Down
46 changes: 46 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,4 +346,50 @@ actions:
assert.Check(t, cmp.Equal(config.Actions[0].Tasks[1].ImagePullPolicy, "Always"))
assert.Check(t, cmp.Equal(config.Actions[0].Tasks[2].ImagePullPolicy, "Never"))
assert.Check(t, cmp.Equal(config.Actions[0].Tasks[3].ImagePullPolicy, "IfNotPresent"))
}

func TestTTLSecondsAfterFinished(t *testing.T) {
configYaml := `
apiVersion: v2
actions:
- name: "Run some fancy job with various ttl after job completes"
events:
- name: "sh.keptn.event.test.triggered"
jsonpath:
property: "$.test.teststrategy"
match: "health"
tasks:
- name: "task1-noinputttl"
workingDir: "/bin"
image: "somefancyimage"
cmd:
- cmd
args:
- arg1
- arg2
- name: "task2-ttl10mins"
workingDir: "/bin"
image: "somefancyimage"
cmd:
- cmd
ttlSecondsAfterFinished: 600
- name: "task3-zerosecondsttl"
workingDir: "/bin"
image: "somefancyimage"
cmd:
- cmd
ttlSecondsAfterFinished: 0
`

config, err := NewConfig([]byte(configYaml))

assert.NilError(t, err)

assert.Equal(t, len(config.Actions), 1)
assert.Equal(t, len(config.Actions[0].Tasks), 3)
assert.Assert(t, config.Actions[0].Tasks[0].TTLSecondsAfterFinished == nil)
assert.Assert(t, config.Actions[0].Tasks[1].TTLSecondsAfterFinished != nil)
assert.Check(t, cmp.Equal(*config.Actions[0].Tasks[1].TTLSecondsAfterFinished, int32(600)))
assert.Assert(t, config.Actions[0].Tasks[2].TTLSecondsAfterFinished != nil)
assert.Check(t, cmp.Equal(*config.Actions[0].Tasks[2].TTLSecondsAfterFinished, int32(0)))
}
73 changes: 73 additions & 0 deletions pkg/k8sutils/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,79 @@ func TestImagePullPolicy(t *testing.T) {

}

func TestTTLSecondsAfterFinished(t *testing.T) {

var DefaultTTLAfterFinished int32 = 21600
var TenMinutesTTLAfterFinished int32 = 600
var ImmediatedlyDeletableTTLAfterFinished int32 = 0

tests := []struct {
name string
ttlSecondsAfterFinished *int32
expectedTTLSecondsAfterFinished int32
}{
{
name: "No ttl specified in input - we should have the default job executor of 21600",
ttlSecondsAfterFinished: nil,
expectedTTLSecondsAfterFinished: DefaultTTLAfterFinished,
},
{
name: "10 mins ttl specified in input",
ttlSecondsAfterFinished: &TenMinutesTTLAfterFinished,
expectedTTLSecondsAfterFinished: TenMinutesTTLAfterFinished,
},
{
name: "0 seconds ttl specified in input - job eligible for deletion immediately",
ttlSecondsAfterFinished: &ImmediatedlyDeletableTTLAfterFinished,
expectedTTLSecondsAfterFinished: ImmediatedlyDeletableTTLAfterFinished,
},
}
for i, test := range tests {
t.Run(
test.name, func(t *testing.T) {

k8sClientSet := k8sfake.NewSimpleClientset()
k8s := k8sImpl{clientset: k8sClientSet}

jobName:= fmt.Sprintf("ipp-job-%d", i)

task := config.Task{
Name: fmt.Sprintf("noIppTask-%d", i),
Image: "someImage:someversion",
Cmd: []string{"someCmd"},
TTLSecondsAfterFinished: test.ttlSecondsAfterFinished,
}

eventData := keptnv2.EventData{
Project: "keptnproject",
Stage: "dev",
Service: "keptnservice",
}

namespace := "test-namespace"

err := k8s.CreateK8sJob(
jobName, &config.Action{Name: jobName}, task, &eventData, JobSettings{
JobNamespace: namespace,
DefaultResourceRequirements: &corev1.ResourceRequirements{
Limits: make(corev1.ResourceList),
Requests: make(corev1.ResourceList),
},
}, "", namespace,
)
assert.NilError(t, err)

job, err := k8sClientSet.BatchV1().Jobs(namespace).Get(context.TODO(), jobName, metav1.GetOptions{})
assert.NilError(t, err)

assert.Assert(t, job.Spec.TTLSecondsAfterFinished != nil)
assert.Equal(t, *job.Spec.TTLSecondsAfterFinished, test.expectedTTLSecondsAfterFinished)
},
)
}

}

func createK8sSecretObj(name string, namespace string, data map[string][]byte) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
Expand Down

0 comments on commit d93645c

Please sign in to comment.