Skip to content

Commit

Permalink
add documentation and validation
Browse files Browse the repository at this point in the history
  • Loading branch information
penDerGraft committed Apr 19, 2020
1 parent 701f70e commit d914162
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,31 @@
# run-k8s-job
# Run Kubernetes Job Action

Run an arbitrary docker image as a job on a Kubernetes cluster and report the output to stdout.

## Why?

For services/apps running on Kubernetes the `run-k8s-job` action allows you to define an arbitrary task as an explict step in a GitHub workflow, without having to deal with a lot of Kubernetes-specific details (you just need a Docker image). This can be useful for creating automated stage gates in a deployment pipeline, or kicking off any task that may be repeated based on the GitHub [events that trigger workflows](https://help.github.com/en/actions/reference/events-that-trigger-workflows).

It's also not always entirely straightforward to get the output of a previously executed Kubernetes job. This action will grab job status and any logs and output them to the actions console.

Some example uses might be:
- smoke/integration tests against a live environment
- load tests
- database migrations


## Required Inputs

- `cluster-url` the base URL for your Kubernetes cluster.
- `cluster-token` the OAuth Bearer token for your Kubernetes cluster.
- `image` the docker image to be run as a job. The image must be publically accessible.
- `ca-file` the path to the root CA certificates (in PEM format) for establishing a TLS connection to the Kubernetes server. Note: this is not is not strictly a required input, but the step will fail if one is not provided and the `disable-tls` input is not explicitly set to false. It is **highly recommended** that a CA file be specified.

## Optional Inputs
- `job-name` prefix for the auto-generated job name in Kubernetes. Defaults to the name of the repo.
- `namespace` the Kubernetes namespace where the job should run. Defaults to `default`
- `disable-tls` connect to the Kubernetes server insecurely (without TLS). Should only be used for testing purposes as it leaves the connection vulnerable to [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).




23 changes: 14 additions & 9 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@ inputs:
cluster-token:
description: 'Kubernetes API authentication token'
required: true
ca-file:
description: 'Path to the file containing the root CA cert for the kubernetes cluster'
image:
description: 'Name of the docker image in a remote repository (i.e. "debian")'
required: true
ca-file:
description: 'Path to the file containing the root CA cert for the kubernetes API server'
required: false
job-name:
description: 'Name of the job (note: used only as a prefix for an auto-generated job name)'
required: false
default: ${{github.repository}}-job
namespace:
description: 'Kubernetes namespace where the job will run'
required: true
job-name:
description: 'Name of the job (note: used as a prefix only for an auto-generated job name)'
required: false
default: ${{github.repository}}
image:
description: 'Name of the docker image in a remote repository (i.e. "debian")'
required: true
default: 'default'
disable-tls:
description: 'Connect to Kubernetes API server without TLS (not recommended)'
required: false
default: "false"

runs:
using: docker
Expand Down
37 changes: 34 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package main

import (
"context"
"os"
"strconv"
"time"

"github.com/sethvargo/go-githubactions"
Expand All @@ -19,16 +21,41 @@ func main() {
image := action.GetInput("image")
jobName := action.GetInput("job-name")
caFilePath := action.GetInput("ca-file")
tlsFlag := action.GetInput("disable-tls")

action = action.WithFieldsMap(map[string]string{
"job": jobName,
})
if len(clusterURL) == 0 {
action.Fatalf("'cluster-url' is a required input but was empty")
}

if len(token) == 0 {
action.Fatalf("'cluster-token' is a required input but was empty")
}

if len(image) == 0 {
action.Fatalf("'image' is a required input but was empty")
}

disableTLS, err := strconv.ParseBool(tlsFlag)
if err != nil {
action.Fatalf("'disable-tls input must be either 'true' or 'false', was %s", tlsFlag)
}

if !disableTLS {
if len(caFilePath) == 0 {
action.Fatalf("you must either specify the file path to the root ca or explicitly disable tls using the 'disable-tls' input")
}

if _, err := os.Stat(caFilePath); os.IsNotExist(err) {
action.Fatalf("could not locate file %s; please make sure the file is available in the runner's context", caFilePath)
}
}

config, err := clientcmd.BuildConfigFromFlags(clusterURL, "")
if err != nil {
action.Fatalf("%v", err)
}

config.Insecure = disableTLS
config.CAFile = caFilePath
config.BearerToken = token

Expand All @@ -37,6 +64,10 @@ func main() {
action.Fatalf("%v", err)
}

action = action.WithFieldsMap(map[string]string{
"job": jobName,
})

runner := NewJobRunner(clientset.BatchV1().Jobs(namespace), clientset.CoreV1().Pods(namespace), 5*time.Second, action)

ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
Expand Down

0 comments on commit d914162

Please sign in to comment.