mirror of
https://github.com/crazy-max/diun.git
synced 2025-12-21 21:33:22 +01:00
Add Nomad provider
I modeled it off the Kubernetes provider a bit. It supports setting task config at group and task levels using services and meta attributes.
This commit is contained in:
@@ -105,6 +105,8 @@ You can override this using the [`--config` flag or `CONFIG` env var with `serve
|
||||
- production
|
||||
file:
|
||||
directory: ./imagesdir
|
||||
nomad:
|
||||
watchByDefault: true
|
||||
```
|
||||
|
||||
## Environment variables
|
||||
|
||||
211
docs/providers/nomad.md
Normal file
211
docs/providers/nomad.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# Nomad provider
|
||||
|
||||
## About
|
||||
|
||||
The Nomad provider allows you watch tasks running using the Docker provider for registry updates.
|
||||
|
||||
## Quick start
|
||||
|
||||
Here we'll go over basic deployment using a local Nomad cluster.
|
||||
|
||||
First, we'll deploy a Diun job:
|
||||
|
||||
```hcl
|
||||
job "diun" {
|
||||
type = "service"
|
||||
|
||||
group "diun" {
|
||||
task "diun" {
|
||||
driver = "docker"
|
||||
|
||||
config {
|
||||
image = "crazymax/diun:latest"
|
||||
args = ["serve"]
|
||||
}
|
||||
|
||||
env = {
|
||||
"NOMAD_ADDR" = "http://${attr.unique.network.ip-address}:4646/",
|
||||
"DIUN_PROVIDERS_NOMAD" = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Task based configuration can be passed through Service tags or meta attributes. These can be defined at the task or even the group level where it will apply to all tasks within the group.
|
||||
|
||||
The example below will show all methods, but you only need to use one.
|
||||
|
||||
```hcl
|
||||
job "whoami" {
|
||||
type = "service"
|
||||
|
||||
group "whoami" {
|
||||
network {
|
||||
mode = "bridge"
|
||||
|
||||
port "web" {
|
||||
to = 80
|
||||
}
|
||||
}
|
||||
|
||||
// This
|
||||
meta {
|
||||
diun.enable = true
|
||||
}
|
||||
|
||||
// Or this
|
||||
service {
|
||||
tags = [
|
||||
"diun.enable=true"
|
||||
]
|
||||
}
|
||||
|
||||
task "diun" {
|
||||
driver = "docker"
|
||||
|
||||
config {
|
||||
image = "containous/whoami:latest"
|
||||
}
|
||||
|
||||
// Or this
|
||||
meta {
|
||||
diun.enable = true
|
||||
}
|
||||
|
||||
// Or this
|
||||
service {
|
||||
tags = [
|
||||
"diun.enable=true"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
!!! hint
|
||||
Environment variable `DIUN_PROVIDERS_NOMAD=true` can be used to enable this provider with default values.
|
||||
|
||||
Default values are assigned by the Nomad client. If not provided in your Diun configuration, the client will default to using the same config values as the `nomad` cli client.
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `NOMAD_ADDR`
|
||||
* `NOMAD_REGION`
|
||||
* `NOMAD_NAMESPACE`
|
||||
* `NOMAD_HTTP_AUTH`
|
||||
* `NOMAD_CACERT`
|
||||
* `NOMAD_CAPATH`
|
||||
* `NOMAD_CLIENT_CERT`
|
||||
* `NOMAD_CLIENT_KEY`
|
||||
* `NOMAD_TLS_SERVER_NAME`
|
||||
* `NOMAD_SKIP_VERIFY`
|
||||
* `NOMAD_TOKEN`
|
||||
|
||||
|
||||
### `address`
|
||||
|
||||
The Nomad server address as URL.
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
providers:
|
||||
nomad:
|
||||
address: "http://localhost:4646"
|
||||
```
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `DIUN_PROVIDERS_NOMAD_ENDPOINT`
|
||||
|
||||
Nomad server endpoint as URL, which is only used when the behavior based on environment variables described below
|
||||
does not apply.
|
||||
|
||||
### `region`
|
||||
|
||||
Nomad region to query from
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
providers:
|
||||
nomad:
|
||||
region: "region1"
|
||||
```
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `DIUN_PROVIDERS_NOMAD_REGION`
|
||||
|
||||
### `namespace`
|
||||
|
||||
Nomad namespace to query from
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
providers:
|
||||
nomad:
|
||||
namespace: "namespace1"
|
||||
```
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `DIUN_PROVIDERS_NOMAD_NAMESPACE`
|
||||
|
||||
### `secretID`
|
||||
|
||||
SecretID to connect to Nomad API. This token must have permission to query and view Nomad jobs.
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
providers:
|
||||
nomad:
|
||||
secretID: "secret"
|
||||
```
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `DIUN_PROVIDERS_NOMAD_SECRETID`
|
||||
|
||||
### `tlsInsecure`
|
||||
|
||||
Controls whether client does not verify the server's certificate chain and hostname (default `false`).
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
providers:
|
||||
nomad:
|
||||
tlsInsecure: false
|
||||
```
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `DIUN_PROVIDERS_NOMAD_TLSINSECURE`
|
||||
|
||||
### `watchByDefault`
|
||||
|
||||
Enable watch by default. If false, tasks that don't have `diun.enable = true` in their meta or service tags will be ignored
|
||||
(default `false`).
|
||||
|
||||
!!! example "File"
|
||||
```yaml
|
||||
providers:
|
||||
nomad:
|
||||
watchByDefault: false
|
||||
```
|
||||
|
||||
!!! abstract "Environment variables"
|
||||
* `DIUN_PROVIDERS_NOMAD_WATCHBYDEFAULT`
|
||||
|
||||
## Nomad annotations
|
||||
|
||||
You can configure more finely the way to analyze the image of your tasks through Nomad meta attributes or service tags:
|
||||
|
||||
| Name | Default | Description |
|
||||
|---------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `diun.enable` | | Set to true to enable image analysis of this task |
|
||||
| `diun.regopt` | | [Registry options](../config/regopts.md) name to use |
|
||||
| `diun.watch_repo` | `false` | Watch all tags of this task image ([be careful](../faq.md#docker-hub-rate-limits) with this setting) |
|
||||
| `diun.notify_on` | `new;update` | Semicolon separated list of status to be notified: `new`, `update`. |
|
||||
| `diun.sort_tags` | `reverse` | [Sort tags method](../faq.md#tags-sorting-when-using-watch_repo) if `diun.watch_repo` enabled. One of `default`, `reverse`, `semver`, `lexicographical` |
|
||||
| `diun.max_tags` | `0` | Maximum number of tags to watch if `diun.watch_repo` enabled. `0` means all of them |
|
||||
| `diun.include_tags` | | Semicolon separated list of regular expressions to include tags. Can be useful if you enable `diun.watch_repo` |
|
||||
| `diun.exclude_tags` | | Semicolon separated list of regular expressions to exclude tags. Can be useful if you enable `diun.watch_repo` |
|
||||
| `diun.hub_link` | _automatic_ | Set registry hub link for this image |
|
||||
| `diun.platform` | _automatic_ | Platform to use (e.g. `linux/amd64`) |
|
||||
10
go.mod
10
go.mod
@@ -19,6 +19,7 @@ require (
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||
github.com/gregdel/pushover v1.1.0
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b
|
||||
github.com/hashicorp/nomad/api v0.0.0-20221121184155-2372c6d20c54
|
||||
github.com/imdario/mergo v0.3.13
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.2
|
||||
github.com/matcornic/hermes/v2 v2.1.0
|
||||
@@ -36,7 +37,7 @@ require (
|
||||
github.com/russross/blackfriday/v2 v2.1.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/streadway/amqp v1.0.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/tidwall/pretty v1.2.1
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3
|
||||
@@ -86,9 +87,12 @@ require (
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hashicorp/cronexpr v1.1.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/huandu/xstrings v1.2.0 // indirect
|
||||
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
@@ -102,6 +106,8 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
|
||||
26
go.sum
26
go.sum
@@ -443,7 +443,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
|
||||
github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -482,8 +482,9 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregdel/pushover v1.1.0 h1:dwHyvrcpZCOS9V1fAnKPaGRRI5OC55cVaKhMybqNsKQ=
|
||||
github.com/gregdel/pushover v1.1.0/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
@@ -495,17 +496,25 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b h1:wDUNC2eKiL35DbLvsDhiblTUXHxcOPwQSCzi7xpQUN4=
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b/go.mod h1:VzxiSdG6j1pi7rwGm/xYI5RbtpBgM8sARDXlvEvxlu0=
|
||||
github.com/hashicorp/cronexpr v1.1.1 h1:NJZDd87hGXjoZBdvyCF9mX4DCq5Wy7+A/w+A7q0wn6c=
|
||||
github.com/hashicorp/cronexpr v1.1.1/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20221121184155-2372c6d20c54 h1:eyCj5YuMoOAcHOP2i+NXylxvjQkzSHd5diuQqVT0vMw=
|
||||
github.com/hashicorp/nomad/api v0.0.0-20221121184155-2372c6d20c54/go.mod h1:CkWF80BBiX2ha+nczdcXGjt6LeYgUVvaNEwRg2YVgE0=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
@@ -564,8 +573,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
@@ -612,8 +621,12 @@ github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mistifyio/go-zfs/v3 v3.0.0/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/moby/buildkit v0.10.1-0.20220712094726-874eef9b70db h1:q7oAjNPIsQWTaT1GVvzAWeRJ70qPJHNtmQS046Thd3U=
|
||||
github.com/moby/buildkit v0.10.1-0.20220712094726-874eef9b70db/go.mod h1:yle9eiU1fiJ/WhC4VTLOaQ6rxFou1mc4AhwScHwysi0=
|
||||
@@ -755,8 +768,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
|
||||
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
||||
@@ -768,6 +781,7 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/shoenig/test v0.4.4 h1:juucmjQTPYUfO2+rID1wfQqsreSlk+2I8K/bQFsUZ9c=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
@@ -808,6 +822,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
@@ -817,8 +832,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
dockerfilePrd "github.com/crazy-max/diun/v4/internal/provider/dockerfile"
|
||||
filePrd "github.com/crazy-max/diun/v4/internal/provider/file"
|
||||
kubernetesPrd "github.com/crazy-max/diun/v4/internal/provider/kubernetes"
|
||||
nomadPrd "github.com/crazy-max/diun/v4/internal/provider/nomad"
|
||||
swarmPrd "github.com/crazy-max/diun/v4/internal/provider/swarm"
|
||||
"github.com/crazy-max/gohealthchecks"
|
||||
"github.com/hako/durafmt"
|
||||
@@ -175,6 +176,11 @@ func (di *Diun) Run() {
|
||||
di.createJob(job)
|
||||
}
|
||||
|
||||
// Nomad provider
|
||||
for _, job := range nomadPrd.New(di.cfg.Providers.Nomad).ListJob() {
|
||||
di.createJob(job)
|
||||
}
|
||||
|
||||
di.wg.Wait()
|
||||
log.Info().
|
||||
Int("added", entries.CountNew).
|
||||
|
||||
28
internal/model/provider_nomad.go
Normal file
28
internal/model/provider_nomad.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/crazy-max/diun/v4/pkg/utl"
|
||||
)
|
||||
|
||||
// PrdNomad holds nomad provider configuration
|
||||
type PrdNomad struct {
|
||||
Address string `yaml:"address" json:"address,omitempty" validate:"omitempty"`
|
||||
Region string `yaml:"region,omitempty" json:"region,omitempty" validate:"omitempty"`
|
||||
SecretID string `yaml:"secretID,omitempty" json:"secretID,omitempty" validate:"omitempty"`
|
||||
Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty" validate:"omitempty"`
|
||||
TLSInsecure *bool `yaml:"tlsInsecure" json:"tlsInsecure,omitempty" validate:"required"`
|
||||
WatchByDefault *bool `yaml:"watchByDefault" json:"watchByDefault,omitempty" validate:"required"`
|
||||
}
|
||||
|
||||
// GetDefaults gets the default values
|
||||
func (s *PrdNomad) GetDefaults() *PrdNomad {
|
||||
n := &PrdNomad{}
|
||||
n.SetDefaults()
|
||||
return n
|
||||
}
|
||||
|
||||
// SetDefaults sets the default values
|
||||
func (s *PrdNomad) SetDefaults() {
|
||||
s.TLSInsecure = utl.NewFalse()
|
||||
s.WatchByDefault = utl.NewFalse()
|
||||
}
|
||||
@@ -7,6 +7,7 @@ type Providers struct {
|
||||
Kubernetes *PrdKubernetes `yaml:"kubernetes,omitempty" json:"kubernetes,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||
File *PrdFile `yaml:"file,omitempty" json:"file,omitempty"`
|
||||
Dockerfile *PrdDockerfile `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"`
|
||||
Nomad *PrdNomad `yaml:"nomad,omitempty" json:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||
}
|
||||
|
||||
// GetDefaults gets the default values
|
||||
|
||||
49
internal/provider/nomad/nomad.go
Normal file
49
internal/provider/nomad/nomad.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package nomad
|
||||
|
||||
import (
|
||||
"github.com/crazy-max/diun/v4/internal/model"
|
||||
"github.com/crazy-max/diun/v4/internal/provider"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Client represents an active nomad provider object
|
||||
type Client struct {
|
||||
*provider.Client
|
||||
config *model.PrdNomad
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
// New creates new kubernetes provider instance
|
||||
func New(config *model.PrdNomad) *provider.Client {
|
||||
return &provider.Client{
|
||||
Handler: &Client{
|
||||
config: config,
|
||||
logger: log.With().Str("provider", "nomad").Logger(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ListJob returns job list to process
|
||||
func (c *Client) ListJob() []model.Job {
|
||||
if c.config == nil {
|
||||
return []model.Job{}
|
||||
}
|
||||
|
||||
images := c.listTaskImages()
|
||||
if len(images) == 0 {
|
||||
log.Warn().Msg("No image found")
|
||||
return []model.Job{}
|
||||
}
|
||||
|
||||
c.logger.Info().Msgf("Found %d image(s) to analyze", len(images))
|
||||
var list []model.Job
|
||||
for _, image := range images {
|
||||
list = append(list, model.Job{
|
||||
Provider: "nomad",
|
||||
Image: image,
|
||||
})
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
126
internal/provider/nomad/task.go
Normal file
126
internal/provider/nomad/task.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package nomad
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/crazy-max/diun/v4/internal/model"
|
||||
"github.com/crazy-max/diun/v4/internal/provider"
|
||||
nomad "github.com/hashicorp/nomad/api"
|
||||
)
|
||||
|
||||
func parseServiceTags(tags []string) map[string]string {
|
||||
labels := map[string]string{}
|
||||
|
||||
for _, tag := range tags {
|
||||
tagParts := strings.SplitN(tag, "=", 2)
|
||||
if len(tagParts) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
labels[tagParts[0]] = tagParts[1]
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
|
||||
func updateMap(m1, m2 map[string]string) map[string]string {
|
||||
for key, value := range m2 {
|
||||
m1[key] = value
|
||||
}
|
||||
|
||||
return m1
|
||||
}
|
||||
|
||||
func (c *Client) listTaskImages() []model.Image {
|
||||
config := &nomad.Config{
|
||||
Address: c.config.Address,
|
||||
Region: c.config.Region,
|
||||
SecretID: c.config.SecretID,
|
||||
Namespace: c.config.Namespace,
|
||||
}
|
||||
|
||||
if *c.config.TLSInsecure {
|
||||
config.TLSConfig.Insecure = true
|
||||
}
|
||||
|
||||
client, err := nomad.NewClient(config)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Cannot create Nomad client")
|
||||
return []model.Image{}
|
||||
}
|
||||
|
||||
jobs, _, err := client.Jobs().List(nil)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Cannot list Nomad jobs")
|
||||
}
|
||||
|
||||
var list []model.Image
|
||||
|
||||
for _, job := range jobs {
|
||||
jobInfo, _, err := client.Jobs().Info(job.ID, nil)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Cannot get info for job")
|
||||
}
|
||||
|
||||
for _, taskGroup := range jobInfo.TaskGroups {
|
||||
// Get task group service labels
|
||||
groupLabels := map[string]string{}
|
||||
for _, service := range taskGroup.Services {
|
||||
groupLabels = updateMap(groupLabels, parseServiceTags(service.Tags))
|
||||
}
|
||||
|
||||
for _, task := range taskGroup.Tasks {
|
||||
if task.Driver != "docker" {
|
||||
continue
|
||||
}
|
||||
|
||||
if taskImage, ok := task.Config["image"]; ok {
|
||||
imageName := taskImage.(string)
|
||||
if imageName == "${meta.connect.sidecar_image}" {
|
||||
c.logger.Debug().
|
||||
Str("job_id", job.ID).
|
||||
Str("task_group", *taskGroup.Name).
|
||||
Str("task_name", task.Name).
|
||||
Msg("Skipping connect sidecar")
|
||||
continue
|
||||
}
|
||||
|
||||
// Get task service labels
|
||||
labels := map[string]string{}
|
||||
labels = updateMap(labels, groupLabels)
|
||||
for _, service := range task.Services {
|
||||
labels = updateMap(labels, parseServiceTags(service.Tags))
|
||||
}
|
||||
|
||||
// Finally, merge task meta values
|
||||
labels = updateMap(labels, task.Meta)
|
||||
|
||||
image, err := provider.ValidateImage(imageName, labels, *c.config.WatchByDefault)
|
||||
if err != nil {
|
||||
c.logger.Error().
|
||||
Err(err).
|
||||
Str("job_id", job.ID).
|
||||
Str("task_group", *taskGroup.Name).
|
||||
Str("task_name", task.Name).
|
||||
Str("image_name", imageName).
|
||||
Msg("Error validating image")
|
||||
continue
|
||||
} else if reflect.DeepEqual(image, model.Image{}) {
|
||||
c.logger.Debug().
|
||||
Str("job_id", job.ID).
|
||||
Str("task_group", *taskGroup.Name).
|
||||
Str("task_name", task.Name).
|
||||
Str("image_name", imageName).
|
||||
Msg("Watch disabled")
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, image)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
53
internal/provider/nomad/task_test.go
Normal file
53
internal/provider/nomad/task_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package nomad
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseServiceTags(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input []string
|
||||
expected map[string]string
|
||||
}{
|
||||
{
|
||||
input: []string{
|
||||
"noequal",
|
||||
},
|
||||
expected: map[string]string{},
|
||||
},
|
||||
{
|
||||
input: []string{
|
||||
"emptyequal=",
|
||||
},
|
||||
expected: map[string]string{
|
||||
"emptyequal": "",
|
||||
},
|
||||
},
|
||||
{
|
||||
input: []string{
|
||||
"key=value",
|
||||
},
|
||||
expected: map[string]string{
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
{
|
||||
input: []string{
|
||||
"withequal=a=b",
|
||||
},
|
||||
expected: map[string]string{
|
||||
"withequal": "a=b",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
tt := tt
|
||||
t.Run(tt.input[0], func(t *testing.T) {
|
||||
result := parseServiceTags(tt.input)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user