├── .gitignore ├── .goreleaser.yml ├── .travis.yml ├── AUTHORS.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── cmd ├── create.go ├── delete.go ├── edit.go ├── get.go ├── list.go ├── root.go ├── run.go └── version.go ├── config └── config.go ├── crontab └── crontab.go ├── go.mod ├── go.sum ├── input └── input.go ├── install.sh ├── log └── log.go ├── main.go ├── template └── template.go └── version └── version.go /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | vendor 3 | dist 4 | 5 | .vscode 6 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # This is an example goreleaser.yaml file with some sane defaults. 2 | # Make sure to check the documentation at http://goreleaser.com 3 | before: 4 | hooks: 5 | - go mod download 6 | builds: 7 | - main: ./ 8 | env: 9 | - CGO_ENABLED=0 10 | ldflags: 11 | - -s -w -X github.com/jacobtomlinson/krontab/version.GitCommit={{.Commit}} -X github.com/jacobtomlinson/krontab/version.BuildDate={{.Date}} -X github.com/jacobtomlinson/krontab/version.Version={{.Env.KRONTAB_VERSION}} 12 | goos: 13 | - windows 14 | - darwin 15 | - linux 16 | goarch: 17 | - amd64 18 | - 386 19 | - arm 20 | archive: 21 | format: binary 22 | name_template: "{{.ProjectName}}-{{.Os}}-{{.Arch}}" 23 | replacements: 24 | 386: i386 25 | amd64: x86_64 26 | checksum: 27 | name_template: 'checksums.txt' 28 | snapshot: 29 | name_template: "{{ .Tag }}-next" 30 | changelog: 31 | sort: asc 32 | filters: 33 | exclude: 34 | - '^docs:' 35 | - '^test:' 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.11.x 4 | 5 | env: 6 | - GO111MODULE=on 7 | 8 | install: 9 | - true 10 | 11 | script: 12 | - make test 13 | 14 | deploy: 15 | - provider: script 16 | skip_cleanup: true 17 | script: make deploy 18 | on: 19 | repo: jacobtomlinson/krontab 20 | tags: true 21 | condition: $TRAVIS_OS_NAME = linux 22 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | ## Development Lead 4 | 5 | - Jacob Tomlinson [jacobtomlinson](https://github.com/jacobtomlinson) 6 | 7 | ## Contributors 8 | 9 | None yet. Why not be the first? -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. 4 | 5 | You can contribute in many ways: 6 | 7 | ## Types of Contributions 8 | 9 | ### Report Bugs 10 | 11 | Report bugs at https://github.com/jacobtomlinson/krontab/issues. 12 | 13 | If you are reporting a bug, please include: 14 | 15 | * Your operating system name and version. 16 | * Any details about your local setup that might be helpful in troubleshooting. 17 | * Detailed steps to reproduce the bug. 18 | 19 | ### Fix Bugs 20 | 21 | Look through the GitHub issues for bugs. Anything tagged with "bug" 22 | is open to whoever wants to implement it. 23 | 24 | ### Implement Features 25 | 26 | Look through the GitHub issues for features. Anything tagged with "feature" 27 | is open to whoever wants to implement it. 28 | 29 | ### Write Documentation 30 | 31 | krontab could always use more documentation, whether as part of the 32 | official krontab docs, in docstrings, or even on the web in blog posts, 33 | articles, and such. 34 | 35 | ### Submit Feedback 36 | 37 | The best way to send feedback is to file an issue at https://github.com/jacobtomlinson/krontab/issues. 38 | 39 | If you are proposing a feature: 40 | 41 | * Explain in detail how it would work. 42 | * Keep the scope as narrow as possible, to make it easier to implement. 43 | * Remember that this is a volunteer-driven project, and that contributions 44 | are welcome :) 45 | 46 | ## Get Started! 47 | 48 | Ready to contribute? Here's how to set up `krontab` for local development. 49 | 50 | 1. Fork the `krontab` repo on GitHub. 51 | 2. Clone your fork locally:: 52 | ```bash 53 | $ git clone git@github.com:your_name_here/krontab.git 54 | ``` 55 | 3. Create a branch for local development:: 56 | ```bash 57 | $ git checkout -b name-of-your-bugfix-or-feature 58 | ``` 59 | Now you can make your changes locally. 60 | 61 | 4. When you're done making changes, check that your changes pass the tests:: 62 | ```bash 63 | $ make test 64 | ``` 65 | 6. Commit your changes and push your branch to GitHub:: 66 | ```bash 67 | $ git add . 68 | $ git commit -m "Your detailed description of your changes." 69 | $ git push origin name-of-your-bugfix-or-feature 70 | ``` 71 | 7. Submit a pull request through the GitHub website. 72 | 73 | Pull Request Guidelines 74 | ----------------------- 75 | 76 | Before you submit a pull request, check that it meets these guidelines: 77 | 78 | 1. The pull request should include tests. 79 | 2. If the pull request adds functionality, the docs should be updated. Put 80 | your new functionality into a function with a docstring, and add the 81 | feature to the list in README.md. 82 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build Stage 2 | FROM lacion/alpine-golang-buildimage:1.11 AS build-stage 3 | 4 | LABEL app="build-krontab" 5 | LABEL REPO="https://github.com/jacobtomlinson/krontab" 6 | 7 | ENV PROJPATH=/go/src/github.com/jacobtomlinson/krontab 8 | 9 | # Because of https://github.com/docker/docker/issues/14914 10 | ENV PATH=$PATH:$GOROOT/bin:$GOPATH/bin 11 | 12 | ADD . /go/src/github.com/jacobtomlinson/krontab 13 | WORKDIR /go/src/github.com/jacobtomlinson/krontab 14 | 15 | RUN make build-alpine 16 | 17 | # Final Stage 18 | FROM lacion/alpine-base-image:latest 19 | 20 | ARG GIT_COMMIT 21 | ARG VERSION 22 | LABEL REPO="https://github.com/jacobtomlinson/krontab" 23 | LABEL GIT_COMMIT=$GIT_COMMIT 24 | LABEL VERSION=$VERSION 25 | 26 | # Because of https://github.com/docker/docker/issues/14914 27 | ENV PATH=$PATH:/opt/krontab/bin 28 | 29 | WORKDIR /opt/krontab/bin 30 | 31 | COPY --from=build-stage /go/src/github.com/jacobtomlinson/krontab/bin/krontab /opt/krontab/bin/ 32 | RUN chmod +x /opt/krontab/bin/krontab 33 | 34 | # Create appuser 35 | RUN adduser -D -g '' krontab 36 | USER krontab 37 | 38 | ENTRYPOINT ["/usr/bin/dumb-init", "--"] 39 | 40 | CMD ["/opt/krontab/bin/krontab"] 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Crown, Jacob Tomlinson 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build build-alpine clean test help default 2 | 3 | BIN_NAME=krontab 4 | 5 | KRONTAB_VERSION := $(shell git describe --tags --dirty) 6 | GIT_COMMIT=$(shell git rev-parse HEAD) 7 | GIT_DIRTY=$(shell test -n "`git status --porcelain`" && echo "+CHANGES" || true) 8 | BUILD_DATE=$(shell date '+%Y-%m-%d-%H:%M:%S') 9 | IMAGE_NAME := "jacobtomlinson/krontab" 10 | BUILD_FLAGS="-X github.com/jacobtomlinson/krontab/version.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X github.com/jacobtomlinson/krontab/version.BuildDate=${BUILD_DATE} -X github.com/jacobtomlinson/krontab/version.Version=${KRONTAB_VERSION}" 11 | 12 | default: help 13 | 14 | help: 15 | @echo 'Management commands for krontab:' 16 | @echo 17 | @echo 'Usage:' 18 | @echo ' make build Compile the project.' 19 | @echo ' make build-all Compile the project for all supported architectures with goreleaser.' 20 | @echo ' make test Run tests on a compiled project.' 21 | @echo ' make deploy Perform a deployment of the current tag with goreleaser.' 22 | @echo ' make release Create a git tag and push to GitHub.' 23 | @echo ' make clean Clean the directory tree.' 24 | @echo 25 | 26 | build: 27 | @echo "building ${BIN_NAME} ${VERSION}" 28 | @echo "GOPATH=${GOPATH}" 29 | go build -ldflags ${BUILD_FLAGS} -o bin/${BIN_NAME} 30 | 31 | export KRONTAB_VERSION 32 | export GIT_COMMIT 33 | export GIT_DIRTY 34 | export BUILD_DATE 35 | build-all: 36 | curl -sL https://git.io/goreleaser | bash -s -- --snapshot --skip-publish --rm-dist 37 | 38 | export KRONTAB_VERSION 39 | export GIT_COMMIT 40 | export GIT_DIRTY 41 | export BUILD_DATE 42 | deploy: 43 | curl -sL https://git.io/goreleaser | bash 44 | 45 | release: 46 | @read -p "Enter tag [v{major}.{minor}.{patch}]: " tag; \ 47 | echo Tagging $$tag \ 48 | git checkout master && git pull origin master --tags && git tag -a $$tag -m "$$tag" && git push origin $$tag 49 | 50 | clean: 51 | @test ! -e bin/${BIN_NAME} || rm bin/${BIN_NAME} 52 | 53 | test: 54 | go test ./... 55 | 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # krontab 2 | 3 | [![Build Status](https://travis-ci.com/jacobtomlinson/krontab.svg?branch=master)](https://travis-ci.com/jacobtomlinson/krontab) 4 | [![Current Release](https://img.shields.io/github/release/jacobtomlinson/krontab.svg)](https://github.com/jacobtomlinson/krontab/releases/latest) 5 | 6 | A crontab replacement for Kubernetes. 7 | 8 | Create `CronJob` resources on your Kubernetes cluster in the same way you would on your *nix system. 9 | Krontab works by constructing a virtual crontab file from your CronJob resources and communicating changes back to the Kubernetes API. You can create more complex and customised jobs with custom templates and trigger your jobs manually any time from the command line. 10 | 11 | Example crontab: 12 | 13 | ```shell 14 | $ krontab -l 15 | # template: default 16 | 0 1 * * * echo hello # name: test 17 | ``` 18 | 19 | ## Installation 20 | 21 | ### Quick install 22 | 23 | ```shell 24 | curl -sL https://git.io/krontab | bash 25 | ``` 26 | 27 | ### Linux (x86 64-bit) 28 | ```shell 29 | LATEST_VERSION=$(curl -sL -o /dev/null -w %{url_effective} "https://github.com/jacobtomlinson/krontab/releases/latest" | rev | cut -f1 -d'/'| rev) 30 | curl -L https://github.com/jacobtomlinson/krontab/releases/download/${LATEST_VERSION}/krontab-linux-x86_64 -o /usr/local/bin/krontab 31 | chmod +x /usr/local/bin/krontab 32 | ``` 33 | 34 | ### Linux (arm 32-bit) 35 | ```shell 36 | LATEST_VERSION=$(curl -sL -o /dev/null -w %{url_effective} "https://github.com/jacobtomlinson/krontab/releases/latest" | rev | cut -f1 -d'/'| rev) 37 | curl -L https://github.com/jacobtomlinson/krontab/releases/download/${LATEST_VERSION}/krontab-linux-arm -o /usr/local/bin/krontab 38 | chmod +x /usr/local/bin/krontab 39 | ``` 40 | 41 | ### OS X (64-bit) 42 | ```shell 43 | LATEST_VERSION=$(curl -sL -o /dev/null -w %{url_effective} "https://github.com/jacobtomlinson/krontab/releases/latest" | rev | cut -f1 -d'/'| rev) 44 | curl -L https://github.com/jacobtomlinson/krontab/releases/download/${LATEST_VERSION}/krontab-darwin-x86_64 -o /usr/local/bin/krontab 45 | chmod +x /usr/local/bin/krontab 46 | ``` 47 | 48 | ## Configuration 49 | 50 | Authentication with your Kubernetes cluster will use your `~/.kube/config` credentials or a service account if being used from inside a pod on the cluster. Advanced configuration options are specified with environment variables. 51 | 52 | | Env var | Default | Description | 53 | | ------------- | ------------- | ------------- | 54 | | `KRONTAB_NAMESPACE` | `default` | The kubernetes namespace to use. | 55 | | `KRONTAB_OWNER` | N/A | The owner of a cronjob. This will be used when creating jobs and will be used as a filter when listing them. | 56 | 57 | ## Usage 58 | 59 | ```console 60 | $ krontab help 61 | Krontab is a crontab replacement for kubernetes. 62 | 63 | You can use it to create cron jobs on a kubernetes cluster in a familiar crontab format. 64 | Krontab works by allowing you to create job templates which are used in kubernetes. Then create 65 | specific cron jobs using the crontab. Example krontab: 66 | 67 | # Crontab example 68 | 69 | # template: default 70 | 0 1 * * * echo hello # name: test 71 | 72 | Usage: 73 | krontab [flags] 74 | krontab [command] 75 | 76 | Available Commands: 77 | create Create a krontab resource 78 | delete Delete a krontab resource 79 | edit Edit a krontab resource 80 | get Get krontab resources 81 | help Help about any command 82 | list List krontab resources 83 | run Run a krontab job 84 | version Print the version number of krontab 85 | 86 | Flags: 87 | -e, --edit-crontab Edit the crontab 88 | -h, --help help for krontab 89 | -l, --list-crontab List the crontab 90 | 91 | Use "krontab [command] --help" for more information about a command. 92 | ``` 93 | 94 | ### Templates 95 | 96 | Krontab uses templates to turn your crontab into Kubernetes CronJob resources. 97 | You will get a default template which you can view with `krontab get template default`. 98 | You can create, edit and delete your own templates too. 99 | 100 | ``` 101 | $ krontab get template default 102 | apiVersion: batch/v1beta1 103 | kind: CronJob 104 | metadata: 105 | name: test 106 | spec: 107 | schedule: 0 */6 * * * 108 | jobTemplate: 109 | metadata: 110 | name: test 111 | krontabTemplate: default 112 | spec: 113 | template: 114 | metadata: 115 | spec: 116 | restartPolicy: Never 117 | containers: 118 | - name: test 119 | image: busybox 120 | command: ["echo", "hello"] 121 | resources: 122 | limits: 123 | cpu: "1" 124 | memory: 2G 125 | requests: 126 | cpu: "0.25" 127 | memory: 0.5G 128 | ``` 129 | 130 | ### Crontab 131 | 132 | Krontab will automatically generate a crontab from your existing Kubernetes CronJob resources. You can edit 133 | them with `krontab -e` or `krontab edit crontab`. Adding new lines to your crontab will be mapped into new 134 | CrobJob resources. Editing lines will update them and deleteing lines will remove them. 135 | 136 | ```console 137 | $ krontab -e 138 | # Welcome to krontab, a crontab like editor for Kubernetes cron jobs. 139 | # 140 | # This is a virtual file and was generated from the kubernetes API. Any edits you make here will be 141 | # sent back to the kubernetes API to create/update/delete CronJob resources. Next time you open this crontab 142 | # you may notice different formatting and comments to how you save it. Comments are meaningful and contain 143 | # metadata about the job. 144 | # 145 | # Example job 146 | # ----------- 147 | # 148 | # # template: default 149 | # 0 1 * * * echo hello world # name: hello-world 150 | # 151 | # Templates 152 | # --------- 153 | # 154 | # Krontab uses templates to turn your your crontab into kubernetes compliant CronJob resources. You will find 155 | # a default template by running 'krontab get template default'. This is a minimal CrobJob resource with runs your 156 | # command in a ubuntu container. When krontab creates your jobs it will replace the container command and schedule pattern 157 | # in the template with the command and schedule pattern from the crontab. 158 | # 159 | # All cronjobs following a '# template: ' comment will be created using that template. If no template comments exist 160 | # then the default template will be used. 161 | # 162 | # Names 163 | # ----- 164 | # Kubernetes requires each job to have a name and is specified at the end of a job with a '# name: ' comment. 165 | # If you do not specify a name one will be autogenerated. 166 | 167 | 168 | # template: default 169 | 0 1 * * * echo hello world # name: test 170 | ``` 171 | 172 | ## Examples 173 | 174 | ### Create a new cron job 175 | 176 | To create a new cron job file you need to open your krontab file for editing. This will automatically open in `vim` or 177 | whatever text edit you have configured with `VISUAL` or `EDITOR`. 178 | 179 | ``` 180 | krontab -e 181 | ``` 182 | 183 | Once this file is open you can create a new job in the same way you would when using regular `crontab`. You must specify your timings as 184 | a five column cron time (minute, hour, day of month, month of year, day of week) followed by your shell command. This command will be triggered 185 | every time the current time matches the schedule you have specified. 186 | 187 | Let's create a job which echo's "hello` every hour. 188 | 189 | ``` 190 | 0 * * * * echo hello 191 | ``` 192 | 193 | When creating a `CronJob` resource on the kubernetes cluster `krontab` will need to give it a name and choose a template to use. If you omit this information 194 | like we have in our echo hello example above `krontab` will use the default template (`krontab get template default` if you want to see it) and random uuid will 195 | be created for the name. 196 | 197 | You can optionally choose to specify this information as yaml style comments in your crontab. 198 | 199 | ``` 200 | # template: default 201 | 0 * * * * echo hello # name: hello-world 202 | ``` 203 | 204 | Here `template` has been specified at the document level which will affect all jobs below it until it is redefined. But the `name` info has been specified in line with the job and will only affect that job. 205 | 206 | ### Edit a job 207 | 208 | Once you have some jobs when you run `crontab -e` you will see a crontab file which contains your existing jobs. They may not look exactly like when you created them as this 209 | crontab file is dynamically generated on the fly. You can make changes to any of the information in the crontab and they will be reflected in ths `CronJob` resources on the kubernetes cluster. 210 | 211 | _Note: All changes except renaming will perform an update task on the cluster. Renaming will result in a deletion and creation of a new job._ 212 | 213 | ### Delete a job 214 | 215 | You can delete a job by running `crontab -e` and removing the line you wish to delete. This will result in the `CronJob` resource being deleted from the cluster. 216 | 217 | ### Test a job 218 | 219 | You can manually take a job for a test drive any time, even if it is not going to be triggered any time soon. 220 | 221 | ``` 222 | krontab run job 223 | ``` 224 | 225 | **Protip:** You can run one shot jobs without having to create a cron job first. This is useful for submitting one off batch jobs. 226 | 227 | ``` 228 | krontab run job --template