Skip to content

Commit

Permalink
adding samples for daemon jobs
Browse files Browse the repository at this point in the history
Signed-off-by: REGGEENR <[email protected]>
  • Loading branch information
reggeenr committed Jul 25, 2022
1 parent dcf8250 commit 8bb4de5
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 10 deletions.
8 changes: 8 additions & 0 deletions daemonjob/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM icr.io/codeengine/golang:alpine
COPY daemonjob.go /
RUN go build -o /daemonjob /daemonjob.go

# Copy exe into a smaller image
FROM icr.io/codeengine/alpine
COPY --from=0 /daemonjob /daemonjob
CMD /daemonjob
28 changes: 28 additions & 0 deletions daemonjob/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Test JOb

This sample shows up to run a batch job as a daemon. This is very similar to the
[testjob](../testjob) sample but this job will not stop being executed but will run until the end of time. It can be customized using the following environment variables:
- `MSG` : specifies the message printed to the logs. By default it will be
a simple "Hello World" type of message
- `TARGET` : When the default message is printed, you can change the word
"World" to something else by setting the `TARGET` environment variable.
- `SLEEP` : will tell the code to sleep for the specified number of seconds
before exiting.

The code will also print the list of environment variables to the log file
for debugging purposes.

The sample script will also submit the job twice. First by creating a
job defintion, followed by submitting it, and then it will submit a new
job directly without first creating a job definition. In the second case
it will also change the message printed via the `MSG` environment variable.

- - -

As noted in [the main README](../README.md), this sample has two pieces:

- a `build` script which will build the container image(s) used
- a `run` script which deploys resources that use those images

The main purpose of this example is the `run` script, but the `build`
script is included for complete educational (and reuse) purposes.
17 changes: 17 additions & 0 deletions daemonjob/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# Env Vars:
# REGISTRY: name of the image registry/namespace to store the images
# NOCACHE: set this to "--no-cache" to turn off the Docker build cache
#
# NOTE: to run this you MUST set the REGISTRY environment variable to
# your own image registry/namespace otherwise the `docker push` commands
# will fail due to an auth failure. Which means, you also need to be logged
# into that registry before you run it.

set -ex
export REGISTRY=${REGISTRY:-icr.io/codeengine}

# Build the job image and push it
docker build ${NOCACHE} -t ${REGISTRY}/daemonjob -f Dockerfile .
docker push ${REGISTRY}/daemonjob
42 changes: 42 additions & 0 deletions daemonjob/daemonjob.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

import (
"fmt"
"os"
"sort"
"strconv"
"strings"
"time"
)

func main() {
// Start a endless for loop
for {
// MSG env var allows you to edit our message
msg := os.Getenv("MSG")
if msg == "" {
target := os.Getenv("TARGET")
if target == "" {
target = "World"
}
msg = "Hello " + target + "!"
}

// Just for debugging... show the env vars if DEBUG is set
envs := os.Environ()
sort.StringSlice(envs).Sort()
fmt.Printf("Envs:\n%s\n", strings.Join(envs, "\n"))

// If the 'SLEEP' env var is set then sleep for that many seconds
if t := os.Getenv("SLEEP"); t != "" {
len, _ := strconv.Atoi(t)
fmt.Printf("Sleeping %d", len)
time.Sleep(time.Duration(len) * time.Second)
}

fmt.Printf("%s\n", msg)

// Sleep for another 60 seconds and then re-do the execution
time.Sleep(time.Duration(60) * time.Second)
}
}
58 changes: 58 additions & 0 deletions daemonjob/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash

# Env Vars:
# NUM: number of instances of the job to run
# REGISTRY: name of the image registry/namespace to get the images

# Clean up previous run
function clean() {
set +ex
echo Cleaning...
(
ibmcloud ce job delete -n tester-daemonjob -f
ibmcloud ce jobrun delete -n tester-daemonjob-doit -f
ibmcloud ce jobrun delete -n tester-daemonjob-doit2 -f
rm -f out
) > /dev/null 2>&1
}

clean
[[ "$1" == "clean" ]] && exit 0

set -ex
export REGISTRY=${REGISTRY:-icr.io/codeengine}
export NUM=${NUM:-10}

# Create a Job definition that will run 10 instances
ibmcloud ce job create --name tester-daemonjob --array-indices=1-${NUM} \
--image ${REGISTRY}/daemonjob --mode daemon

# Now submit the job using that definition - and wait for it to finish
ibmcloud ce jobrun submit --name tester-daemonjob-doit --job tester-daemonjob --wait

# Now look at a view of the logs to make sure it worked
ibmcloud ce jobrun logs --instance tester-daemonjob-doit-1-0 | tee out

# Verify it ran ok
if ! grep "Hello World" out > /dev/null ; then
echo "Missing expected outout"
exit 1
fi

# Now submit a job w/o creating a job definition first - and wait to finish
ibmcloud ce jobrun submit --name tester-daemonjob-doit2 --array-indices=1-${NUM} \
--image ${REGISTRY}/daemonjob --mode daemon --env MSG="Hi there" --wait

# Show the stats about the job
ibmcloud ce jobrun get --name tester-daemonjob-doit2

# Now look at a view of the logs to make sure it worked
ibmcloud ce jobrun logs --instance tester-daemonjob-doit2-1-0 | tee out

if ! grep "Hi there" out > /dev/null ; then
echo "Missing expected outout"
exit 1
fi

# Clean up
clean
35 changes: 25 additions & 10 deletions helloworld/helloworld.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,18 +202,33 @@ func main() {
// Otherwise we're an App and we need to start the HTTP server
// to processing incoming requests
if jobIndex := os.Getenv("JOB_INDEX"); jobIndex != "" {
sleep := os.Getenv("SLEEP")
if sleep != "" {
len, _ := strconv.Atoi(sleep)
if len > 0 {
Debug(false, "Sleeping %d", len)
time.Sleep(time.Duration(len) * time.Second)

// Jobs can be either started in 'task' mode and run to completion or in 'daemon' mode which
jobMode := os.Getenv("JOB_MODE")

// Start a endless for loop
for {
sleep := os.Getenv("SLEEP")
if sleep != "" {
len, _ := strconv.Atoi(sleep)
if len > 0 {
Debug(false, "Sleeping %d", len)
time.Sleep(time.Duration(len) * time.Second)
}
}
}

fmt.Printf("Hello from helloworld! I'm a batch job! Index: %s\n\n",
jobIndex)
PrintMessage(os.Stdout, os.Getenv("SHOW") == "")
fmt.Printf("Hello from helloworld! I'm a %s job! Index: %s\n\n",
jobMode, jobIndex)
PrintMessage(os.Stdout, os.Getenv("SHOW") == "")

if jobMode == "task" {
// If this job is of type task, let exit the loop
break
}

// Sleep for another 60 seconds and then re-do the execution
time.Sleep(time.Duration(60) * time.Second)
}

} else {
// Debug the http handler for all requests
Expand Down

0 comments on commit 8bb4de5

Please sign in to comment.