mirror of
https://github.com/containrrr/watchtower.git
synced 2025-12-13 21:56:38 +01:00
Merge branch 'master' into fix/retain-cmd
This commit is contained in:
commit
e1239b2cdb
32 changed files with 966 additions and 481 deletions
|
|
@ -277,11 +277,12 @@
|
|||
"login": "simskij",
|
||||
"name": "Simon Aronsson",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/1596025?v=4",
|
||||
"profile": "http://www.arcticbit.se",
|
||||
"profile": "http://simme.dev",
|
||||
"contributions": [
|
||||
"code",
|
||||
"maintenance",
|
||||
"review"
|
||||
"review",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -309,7 +310,8 @@
|
|||
"avatar_url": "https://avatars0.githubusercontent.com/u/21138205?v=4",
|
||||
"profile": "https://github.com/zoispag",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"review"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -393,6 +395,42 @@
|
|||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jnidzwetzki",
|
||||
"name": "Jan Kristof Nidzwetzki",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/5753622?v=4",
|
||||
"profile": "https://achfrag.net",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mindrunner",
|
||||
"name": "lukas",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/1413542?v=4",
|
||||
"profile": "https://www.lukaselsner.de",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "codingCoffee",
|
||||
"name": "Ameya Shenoy",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/13611153?v=4",
|
||||
"profile": "https://codingcoffee.dev",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "raymondelooff",
|
||||
"name": "Raymon de Looff",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/9716806?v=4",
|
||||
"profile": "https://github.com/raymondelooff",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
|
@ -400,5 +438,6 @@
|
|||
"projectOwner": "containrrr",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"commitConvention": "none"
|
||||
"commitConvention": "none",
|
||||
"skipCi": true
|
||||
}
|
||||
|
|
|
|||
23
.github/workflows/publish-dev-dockerimage.yaml
vendored
Normal file
23
.github/workflows/publish-dev-dockerimage.yaml
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
name: Docker image (latest-dev)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: jerray/publish-docker-action@master
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
file: dockerfiles/Dockerfile.self-contained
|
||||
repository: containrrr/watchtower
|
||||
tags: latest-dev
|
||||
|
|
@ -25,4 +25,14 @@ go build # compiles and packages an executable bin
|
|||
go test ./... -v # runs tests with verbose output
|
||||
./watchtower # runs the application (outside of a container)
|
||||
```
|
||||
|
||||
If you dont have it enabled, you'll either have to prefix each command with `GO111MODULE=on` or run `export GO111MODULE=on` before running the commands. [You can read more about modules here.](https://github.com/golang/go/wiki/Modules)
|
||||
|
||||
To build a Watchtower image of your own, use the self-contained Dockerfiles. As the main Dockerfile, they can be found in `dockerfiles/`:
|
||||
- `dockerfiles/Dockerfile.dev-self-contained` will build an image based on your current local Watchtower files.
|
||||
- `dockerfiles/Dockerfile.self-contained` will build an image based on current Watchtower's repository on GitHub.
|
||||
|
||||
e.g.:
|
||||
```bash
|
||||
sudo docker build . -f dockerfiles/Dockerfile.dev-self-contained -t containrrr/watchtower # to build an image from local files
|
||||
```
|
||||
95
README.md
95
README.md
|
|
@ -62,64 +62,73 @@ The full documentation is available at https://containrrr.github.io/watchtower.
|
|||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="http://codelica.com"><img src="https://avatars3.githubusercontent.com/u/386101?v=4" width="100px;" alt="James"/><br /><sub><b>James</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Codelica" title="Tests">⚠️</a> <a href="#ideas-Codelica" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://kopfkrieg.org"><img src="https://avatars2.githubusercontent.com/u/5047813?v=4" width="100px;" alt="Florian"/><br /><sub><b>Florian</b></sub></a><br /><a href="#review-KopfKrieg" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/containrrr/watchtower/commits?author=KopfKrieg" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/bdehamer"><img src="https://avatars1.githubusercontent.com/u/398027?v=4" width="100px;" alt="Brian DeHamer"/><br /><sub><b>Brian DeHamer</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=bdehamer" title="Code">💻</a> <a href="#maintenance-bdehamer" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/rosscado"><img src="https://avatars1.githubusercontent.com/u/16578183?v=4" width="100px;" alt="Ross Cadogan"/><br /><sub><b>Ross Cadogan</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=rosscado" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/stffabi"><img src="https://avatars0.githubusercontent.com/u/9464631?v=4" width="100px;" alt="stffabi"/><br /><sub><b>stffabi</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=stffabi" title="Code">💻</a> <a href="#maintenance-stffabi" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/ATCUSA"><img src="https://avatars3.githubusercontent.com/u/3581228?v=4" width="100px;" alt="Austin"/><br /><sub><b>Austin</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=ATCUSA" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://labs.ctl.io"><img src="https://avatars2.githubusercontent.com/u/6181487?v=4" width="100px;" alt="David Gardner"/><br /><sub><b>David Gardner</b></sub></a><br /><a href="#review-davidgardner11" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/containrrr/watchtower/commits?author=davidgardner11" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://codelica.com"><img src="https://avatars3.githubusercontent.com/u/386101?v=4" width="100px;" alt=""/><br /><sub><b>James</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Codelica" title="Tests">⚠️</a> <a href="#ideas-Codelica" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://kopfkrieg.org"><img src="https://avatars2.githubusercontent.com/u/5047813?v=4" width="100px;" alt=""/><br /><sub><b>Florian</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/pulls?q=is%3Apr+reviewed-by%3AKopfKrieg" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/containrrr/watchtower/commits?author=KopfKrieg" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/bdehamer"><img src="https://avatars1.githubusercontent.com/u/398027?v=4" width="100px;" alt=""/><br /><sub><b>Brian DeHamer</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=bdehamer" title="Code">💻</a> <a href="#maintenance-bdehamer" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/rosscado"><img src="https://avatars1.githubusercontent.com/u/16578183?v=4" width="100px;" alt=""/><br /><sub><b>Ross Cadogan</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=rosscado" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/stffabi"><img src="https://avatars0.githubusercontent.com/u/9464631?v=4" width="100px;" alt=""/><br /><sub><b>stffabi</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=stffabi" title="Code">💻</a> <a href="#maintenance-stffabi" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/ATCUSA"><img src="https://avatars3.githubusercontent.com/u/3581228?v=4" width="100px;" alt=""/><br /><sub><b>Austin</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=ATCUSA" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://labs.ctl.io"><img src="https://avatars2.githubusercontent.com/u/6181487?v=4" width="100px;" alt=""/><br /><sub><b>David Gardner</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/pulls?q=is%3Apr+reviewed-by%3Adavidgardner11" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/containrrr/watchtower/commits?author=davidgardner11" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/dolanor"><img src="https://avatars3.githubusercontent.com/u/928722?v=4" width="100px;" alt="Tanguy ⧓ Herrmann"/><br /><sub><b>Tanguy ⧓ Herrmann</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=dolanor" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rdamazio"><img src="https://avatars3.githubusercontent.com/u/997641?v=4" width="100px;" alt="Rodrigo Damazio Bovendorp"/><br /><sub><b>Rodrigo Damazio Bovendorp</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=rdamazio" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=rdamazio" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.taisun.io/"><img src="https://avatars3.githubusercontent.com/u/1852688?v=4" width="100px;" alt="Ryan Kuba"/><br /><sub><b>Ryan Kuba</b></sub></a><br /><a href="#infra-thelamer" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/cnrmck"><img src="https://avatars2.githubusercontent.com/u/22061955?v=4" width="100px;" alt="cnrmck"/><br /><sub><b>cnrmck</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=cnrmck" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://harrywalter.co.uk"><img src="https://avatars3.githubusercontent.com/u/338588?v=4" width="100px;" alt="Harry Walter"/><br /><sub><b>Harry Walter</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=haswalt" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://projectsperanza.com"><img src="https://avatars3.githubusercontent.com/u/74515?v=4" width="100px;" alt="Robotex"/><br /><sub><b>Robotex</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Robotex" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://geraldpape.io"><img src="https://avatars0.githubusercontent.com/u/1494211?v=4" width="100px;" alt="Gerald Pape"/><br /><sub><b>Gerald Pape</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=ubergesundheit" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/dolanor"><img src="https://avatars3.githubusercontent.com/u/928722?v=4" width="100px;" alt=""/><br /><sub><b>Tanguy ⧓ Herrmann</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=dolanor" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rdamazio"><img src="https://avatars3.githubusercontent.com/u/997641?v=4" width="100px;" alt=""/><br /><sub><b>Rodrigo Damazio Bovendorp</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=rdamazio" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=rdamazio" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.taisun.io/"><img src="https://avatars3.githubusercontent.com/u/1852688?v=4" width="100px;" alt=""/><br /><sub><b>Ryan Kuba</b></sub></a><br /><a href="#infra-thelamer" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/cnrmck"><img src="https://avatars2.githubusercontent.com/u/22061955?v=4" width="100px;" alt=""/><br /><sub><b>cnrmck</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=cnrmck" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://harrywalter.co.uk"><img src="https://avatars3.githubusercontent.com/u/338588?v=4" width="100px;" alt=""/><br /><sub><b>Harry Walter</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=haswalt" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://projectsperanza.com"><img src="https://avatars3.githubusercontent.com/u/74515?v=4" width="100px;" alt=""/><br /><sub><b>Robotex</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Robotex" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://geraldpape.io"><img src="https://avatars0.githubusercontent.com/u/1494211?v=4" width="100px;" alt=""/><br /><sub><b>Gerald Pape</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=ubergesundheit" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/fomk"><img src="https://avatars0.githubusercontent.com/u/17636183?v=4" width="100px;" alt="fomk"/><br /><sub><b>fomk</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=fomk" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/svengo"><img src="https://avatars3.githubusercontent.com/u/2502366?v=4" width="100px;" alt="Sven Gottwald"/><br /><sub><b>Sven Gottwald</b></sub></a><br /><a href="#infra-svengo" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://liberapay.com/techknowlogick/"><img src="https://avatars1.githubusercontent.com/u/164197?v=4" width="100px;" alt="techknowlogick"/><br /><sub><b>techknowlogick</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=techknowlogick" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://log.c5t.org/about/"><img src="https://avatars1.githubusercontent.com/u/1449568?v=4" width="100px;" alt="waja"/><br /><sub><b>waja</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=waja" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://scottalbertson.com"><img src="https://avatars2.githubusercontent.com/u/154463?v=4" width="100px;" alt="Scott Albertson"/><br /><sub><b>Scott Albertson</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=salbertson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/huddlesj"><img src="https://avatars1.githubusercontent.com/u/11966535?v=4" width="100px;" alt="Jason Huddleston"/><br /><sub><b>Jason Huddleston</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=huddlesj" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://npstr.space/"><img src="https://avatars3.githubusercontent.com/u/6048348?v=4" width="100px;" alt="Napster"/><br /><sub><b>Napster</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=napstr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/fomk"><img src="https://avatars0.githubusercontent.com/u/17636183?v=4" width="100px;" alt=""/><br /><sub><b>fomk</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=fomk" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/svengo"><img src="https://avatars3.githubusercontent.com/u/2502366?v=4" width="100px;" alt=""/><br /><sub><b>Sven Gottwald</b></sub></a><br /><a href="#infra-svengo" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://liberapay.com/techknowlogick/"><img src="https://avatars1.githubusercontent.com/u/164197?v=4" width="100px;" alt=""/><br /><sub><b>techknowlogick</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=techknowlogick" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://log.c5t.org/about/"><img src="https://avatars1.githubusercontent.com/u/1449568?v=4" width="100px;" alt=""/><br /><sub><b>waja</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=waja" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://scottalbertson.com"><img src="https://avatars2.githubusercontent.com/u/154463?v=4" width="100px;" alt=""/><br /><sub><b>Scott Albertson</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=salbertson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/huddlesj"><img src="https://avatars1.githubusercontent.com/u/11966535?v=4" width="100px;" alt=""/><br /><sub><b>Jason Huddleston</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=huddlesj" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://npstr.space/"><img src="https://avatars3.githubusercontent.com/u/6048348?v=4" width="100px;" alt=""/><br /><sub><b>Napster</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=napstr" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/darknode"><img src="https://avatars1.githubusercontent.com/u/809429?v=4" width="100px;" alt="Maxim"/><br /><sub><b>Maxim</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=darknode" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=darknode" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://schmitt.cat"><img src="https://avatars0.githubusercontent.com/u/17984549?v=4" width="100px;" alt="Max Schmitt"/><br /><sub><b>Max Schmitt</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=mxschmitt" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/cron410"><img src="https://avatars1.githubusercontent.com/u/3082899?v=4" width="100px;" alt="cron410"/><br /><sub><b>cron410</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=cron410" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Cardoso222"><img src="https://avatars3.githubusercontent.com/u/7026517?v=4" width="100px;" alt="Paulo Henrique"/><br /><sub><b>Paulo Henrique</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Cardoso222" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://coded.io"><img src="https://avatars0.githubusercontent.com/u/107097?v=4" width="100px;" alt="Kaleb Elwert"/><br /><sub><b>Kaleb Elwert</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=belak" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/wmbutler"><img src="https://avatars1.githubusercontent.com/u/1254810?v=4" width="100px;" alt="Bill Butler"/><br /><sub><b>Bill Butler</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=wmbutler" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.mariotacke.io"><img src="https://avatars2.githubusercontent.com/u/4942019?v=4" width="100px;" alt="Mario Tacke"/><br /><sub><b>Mario Tacke</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=mariotacke" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/darknode"><img src="https://avatars1.githubusercontent.com/u/809429?v=4" width="100px;" alt=""/><br /><sub><b>Maxim</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=darknode" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=darknode" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://schmitt.cat"><img src="https://avatars0.githubusercontent.com/u/17984549?v=4" width="100px;" alt=""/><br /><sub><b>Max Schmitt</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=mxschmitt" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/cron410"><img src="https://avatars1.githubusercontent.com/u/3082899?v=4" width="100px;" alt=""/><br /><sub><b>cron410</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=cron410" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Cardoso222"><img src="https://avatars3.githubusercontent.com/u/7026517?v=4" width="100px;" alt=""/><br /><sub><b>Paulo Henrique</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Cardoso222" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://coded.io"><img src="https://avatars0.githubusercontent.com/u/107097?v=4" width="100px;" alt=""/><br /><sub><b>Kaleb Elwert</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=belak" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/wmbutler"><img src="https://avatars1.githubusercontent.com/u/1254810?v=4" width="100px;" alt=""/><br /><sub><b>Bill Butler</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=wmbutler" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.mariotacke.io"><img src="https://avatars2.githubusercontent.com/u/4942019?v=4" width="100px;" alt=""/><br /><sub><b>Mario Tacke</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=mariotacke" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://markwoodbridge.com"><img src="https://avatars2.githubusercontent.com/u/1101318?v=4" width="100px;" alt="Mark Woodbridge"/><br /><sub><b>Mark Woodbridge</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=mrw34" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.arcticbit.se"><img src="https://avatars0.githubusercontent.com/u/1596025?v=4" width="100px;" alt="Simon Aronsson"/><br /><sub><b>Simon Aronsson</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=simskij" title="Code">💻</a> <a href="#maintenance-simskij" title="Maintenance">🚧</a> <a href="#review-simskij" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/Ansem93"><img src="https://avatars3.githubusercontent.com/u/6626218?v=4" width="100px;" alt="Ansem93"/><br /><sub><b>Ansem93</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Ansem93" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/lukapeschke"><img src="https://avatars1.githubusercontent.com/u/17085536?v=4" width="100px;" alt="Luka Peschke"/><br /><sub><b>Luka Peschke</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=lukapeschke" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=lukapeschke" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/zoispag"><img src="https://avatars0.githubusercontent.com/u/21138205?v=4" width="100px;" alt="Zois Pagoulatos"/><br /><sub><b>Zois Pagoulatos</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=zoispag" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://alexandre.menif.name"><img src="https://avatars0.githubusercontent.com/u/16152103?v=4" width="100px;" alt="Alexandre Menif"/><br /><sub><b>Alexandre Menif</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=alexandremenif" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chugunov"><img src="https://avatars1.githubusercontent.com/u/4140479?v=4" width="100px;" alt="Andrey"/><br /><sub><b>Andrey</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=chugunov" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://markwoodbridge.com"><img src="https://avatars2.githubusercontent.com/u/1101318?v=4" width="100px;" alt=""/><br /><sub><b>Mark Woodbridge</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=mrw34" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://simme.dev"><img src="https://avatars0.githubusercontent.com/u/1596025?v=4" width="100px;" alt=""/><br /><sub><b>Simon Aronsson</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=simskij" title="Code">💻</a> <a href="#maintenance-simskij" title="Maintenance">🚧</a> <a href="https://github.com/containrrr/watchtower/pulls?q=is%3Apr+reviewed-by%3Asimskij" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/containrrr/watchtower/commits?author=simskij" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Ansem93"><img src="https://avatars3.githubusercontent.com/u/6626218?v=4" width="100px;" alt=""/><br /><sub><b>Ansem93</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=Ansem93" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/lukapeschke"><img src="https://avatars1.githubusercontent.com/u/17085536?v=4" width="100px;" alt=""/><br /><sub><b>Luka Peschke</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=lukapeschke" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=lukapeschke" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/zoispag"><img src="https://avatars0.githubusercontent.com/u/21138205?v=4" width="100px;" alt=""/><br /><sub><b>Zois Pagoulatos</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=zoispag" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/pulls?q=is%3Apr+reviewed-by%3Azoispag" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://alexandre.menif.name"><img src="https://avatars0.githubusercontent.com/u/16152103?v=4" width="100px;" alt=""/><br /><sub><b>Alexandre Menif</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=alexandremenif" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chugunov"><img src="https://avatars1.githubusercontent.com/u/4140479?v=4" width="100px;" alt=""/><br /><sub><b>Andrey</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=chugunov" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://noplanman.ch"><img src="https://avatars3.githubusercontent.com/u/9423417?v=4" width="100px;" alt="Armando Lüscher"/><br /><sub><b>Armando Lüscher</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=noplanman" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/rjbudke"><img src="https://avatars2.githubusercontent.com/u/273485?v=4" width="100px;" alt="Ryan Budke"/><br /><sub><b>Ryan Budke</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=rjbudke" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://kaloyan.raev.name"><img src="https://avatars2.githubusercontent.com/u/468091?v=4" width="100px;" alt="Kaloyan Raev"/><br /><sub><b>Kaloyan Raev</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=kaloyan-raev" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=kaloyan-raev" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/sixth"><img src="https://avatars3.githubusercontent.com/u/11591445?v=4" width="100px;" alt="sixth"/><br /><sub><b>sixth</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=sixth" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://foosel.net"><img src="https://avatars0.githubusercontent.com/u/83657?v=4" width="100px;" alt="Gina Häußge"/><br /><sub><b>Gina Häußge</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=foosel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/8ear"><img src="https://avatars0.githubusercontent.com/u/10329648?v=4" width="100px;" alt="Max H."/><br /><sub><b>Max H.</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=8ear" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://pjknkda.github.io"><img src="https://avatars0.githubusercontent.com/u/4986524?v=4" width="100px;" alt="Jungkook Park"/><br /><sub><b>Jungkook Park</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=pjknkda" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://noplanman.ch"><img src="https://avatars3.githubusercontent.com/u/9423417?v=4" width="100px;" alt=""/><br /><sub><b>Armando Lüscher</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=noplanman" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/rjbudke"><img src="https://avatars2.githubusercontent.com/u/273485?v=4" width="100px;" alt=""/><br /><sub><b>Ryan Budke</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=rjbudke" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://kaloyan.raev.name"><img src="https://avatars2.githubusercontent.com/u/468091?v=4" width="100px;" alt=""/><br /><sub><b>Kaloyan Raev</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=kaloyan-raev" title="Code">💻</a> <a href="https://github.com/containrrr/watchtower/commits?author=kaloyan-raev" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/sixth"><img src="https://avatars3.githubusercontent.com/u/11591445?v=4" width="100px;" alt=""/><br /><sub><b>sixth</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=sixth" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://foosel.net"><img src="https://avatars0.githubusercontent.com/u/83657?v=4" width="100px;" alt=""/><br /><sub><b>Gina Häußge</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=foosel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/8ear"><img src="https://avatars0.githubusercontent.com/u/10329648?v=4" width="100px;" alt=""/><br /><sub><b>Max H.</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=8ear" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://pjknkda.github.io"><img src="https://avatars0.githubusercontent.com/u/4986524?v=4" width="100px;" alt=""/><br /><sub><b>Jungkook Park</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=pjknkda" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://achfrag.net"><img src="https://avatars1.githubusercontent.com/u/5753622?v=4" width="100px;" alt=""/><br /><sub><b>Jan Kristof Nidzwetzki</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=jnidzwetzki" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.lukaselsner.de"><img src="https://avatars0.githubusercontent.com/u/1413542?v=4" width="100px;" alt=""/><br /><sub><b>lukas</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=mindrunner" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://codingcoffee.dev"><img src="https://avatars3.githubusercontent.com/u/13611153?v=4" width="100px;" alt=""/><br /><sub><b>Ameya Shenoy</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=codingCoffee" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/raymondelooff"><img src="https://avatars0.githubusercontent.com/u/9716806?v=4" width="100px;" alt=""/><br /><sub><b>Raymon de Looff</b></sub></a><br /><a href="https://github.com/containrrr/watchtower/commits?author=raymondelooff" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/filters"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
|
|
@ -108,7 +109,7 @@ func PreRun(cmd *cobra.Command, args []string) {
|
|||
|
||||
// Run is the main execution flow of the command
|
||||
func Run(c *cobra.Command, names []string) {
|
||||
filter := container.BuildFilter(names, enableLabel)
|
||||
filter := filters.BuildFilter(names, enableLabel)
|
||||
runOnce, _ := c.PersistentFlags().GetBool("run-once")
|
||||
|
||||
if runOnce {
|
||||
|
|
@ -155,7 +156,7 @@ func runUpgradesOnSchedule(filter t.Filter) error {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debug("Starting Watchtower and scheduling first run: " + cron.Entries()[0].Schedule.Next(time.Now()).String())
|
||||
log.Info("Starting Watchtower and scheduling first run: " + cron.Entries()[0].Schedule.Next(time.Now()).String())
|
||||
cron.Start()
|
||||
|
||||
// Graceful shut-down on SIGINT/SIGTERM
|
||||
|
|
@ -172,7 +173,7 @@ func runUpgradesOnSchedule(filter t.Filter) error {
|
|||
|
||||
func runUpdatesWithNotifications(filter t.Filter) {
|
||||
notifier.StartNotification()
|
||||
updateParams := actions.UpdateParams{
|
||||
updateParams := t.UpdateParams{
|
||||
Filter: filter,
|
||||
Cleanup: cleanup,
|
||||
NoRestart: noRestart,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM alpine:3.9 as alpine
|
||||
FROM alpine:3.11 as alpine
|
||||
|
||||
RUN apk add --no-cache \
|
||||
ca-certificates \
|
||||
|
|
@ -15,4 +15,4 @@ COPY --from=alpine \
|
|||
/usr/share/zoneinfo
|
||||
|
||||
COPY watchtower /
|
||||
ENTRYPOINT ["/watchtower"]
|
||||
ENTRYPOINT ["/watchtower"]
|
||||
38
dockerfiles/Dockerfile.dev-self-contained
Normal file
38
dockerfiles/Dockerfile.dev-self-contained
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# Builder
|
||||
#
|
||||
|
||||
FROM golang:alpine as builder
|
||||
|
||||
# use version (for example "v0.3.3") or "master"
|
||||
ARG WATCHTOWER_VERSION=master
|
||||
|
||||
RUN apk add --no-cache \
|
||||
alpine-sdk \
|
||||
ca-certificates \
|
||||
git \
|
||||
tzdata
|
||||
|
||||
COPY . /watchtower
|
||||
|
||||
RUN \
|
||||
cd /watchtower && \
|
||||
\
|
||||
GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' . && \
|
||||
GO111MODULE=on go test ./... -v
|
||||
|
||||
|
||||
#
|
||||
# watchtower
|
||||
#
|
||||
|
||||
FROM scratch
|
||||
|
||||
LABEL "com.centurylinklabs.watchtower"="true"
|
||||
|
||||
# copy files from other container
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
COPY --from=builder /watchtower/watchtower /watchtower
|
||||
|
||||
ENTRYPOINT ["/watchtower"]
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
Some private docker registries (the most prominent probably being AWS ECR) use non-standard ways of authentication.
|
||||
To be able to use this together with watchtower, we need to use a credential helper.
|
||||
|
||||
To keep the image size small we've decided to not include any helpers in the watchtower image, instead we'll put the
|
||||
helper in a separate container and mount it using volumes.
|
||||
|
||||
### Example
|
||||
Example implementation for use with [amazon-ecr-credential-helper](https://github.com/awslabs/amazon-ecr-credential-helper):
|
||||
|
||||
```Dockerfile
|
||||
FROM golang:latest
|
||||
|
||||
ENV CGO_ENABLED 0
|
||||
ENV REPO github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login
|
||||
|
||||
RUN go get -u $REPO
|
||||
|
||||
RUN rm /go/bin/docker-credential-ecr-login
|
||||
|
||||
RUN go build \
|
||||
-o /go/bin/docker-credential-ecr-login \
|
||||
/go/src/$REPO
|
||||
|
||||
WORKDIR /go/bin/
|
||||
```
|
||||
|
||||
and the docker-compose definition:
|
||||
```yaml
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
watchtower:
|
||||
image: index.docker.io/containrrr/watchtower:latest
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- <PATH_TO_HOME_DIR>/.docker/config.json:/config.json
|
||||
- helper:/go/bin
|
||||
environment:
|
||||
- HOME=/
|
||||
- PATH=$PATH:/go/bin
|
||||
- AWS_REGION=<AWS_REGION>
|
||||
- AWS_ACCESS_KEY_ID=<AWS_ACCESS_KEY>
|
||||
- AWS_SECRET_ACCESS_KEY=<AWS_SECRET_ACCESS_KEY>
|
||||
volumes:
|
||||
helper: {}
|
||||
```
|
||||
|
||||
and for `.docker/config.yml`:
|
||||
```yaml
|
||||
{
|
||||
"HttpHeaders" : {
|
||||
"User-Agent" : "Docker-Client/19.03.1 (XXXXXX)"
|
||||
},
|
||||
"credsStore" : "osxkeychain", // ...or your prefered helper
|
||||
"auths" : {
|
||||
"xyzxyzxyz.dkr.ecr.eu-north-1.amazonaws.com" : {},
|
||||
"https://index.docker.io/v1/": {}
|
||||
},
|
||||
"credHelpers": {
|
||||
"xyzxyzxyz.dkr.ecr.eu-north-1.amazonaws.com" : "ecr-login",
|
||||
"index.docker.io": "osxkeychain" // ...or your prefered helper
|
||||
}
|
||||
}
|
||||
```
|
||||
118
docs/private-registries.md
Normal file
118
docs/private-registries.md
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
Watchtower supports private Docker image registries. In many cases, accessing a private registry requires a valid username and password (i.e., _credentials_). In order to operate in such an environment, watchtower needs to know the credentials to access the registry.
|
||||
|
||||
The credentials can be provided to watchtower in a configuration file called `config.json`. There are two ways to generate this configuration file:
|
||||
|
||||
* The configuration file can be created manually.
|
||||
* Call `docker login <REGISTRY_NAME>` and share the resulting configuration file.
|
||||
|
||||
### Create the configuration file manually
|
||||
Create a new configuration file with the following syntax and a base64 encoded username and password `auth` string:
|
||||
```json
|
||||
{
|
||||
"auths": {
|
||||
"<REGISTRY_NAME>": {
|
||||
"auth": "XXXXXXX"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`<REGISTRY_NAME>` needs to be replaced by the name of your private registry (e.g., `my-private-registry.example.org`)
|
||||
|
||||
The required `auth` string can be generated as follows:
|
||||
```bash
|
||||
echo -n 'username:password' | base64
|
||||
```
|
||||
|
||||
When the watchtower Docker container is started, the created configuration file (`<PATH>/config.json` in this example) needs to be passed to the container:
|
||||
```bash
|
||||
docker run [...] -v <PATH>/config.json:/config.json containrrr/watchtower
|
||||
```
|
||||
|
||||
### Share the Docker configuration file
|
||||
To pull an image from a private registry, `docker login` needs to be called first, to get access to the registry. The provided credentials are stored in a configuration file called `<PATH_TO_HOME_DIR>/.docker/config.json`. This configuration file can be directly used by watchtower. In this case, the creation of an additional configuration file is not necessary.
|
||||
|
||||
When the Docker container is started, pass the configuration file to watchtower:
|
||||
```bash
|
||||
docker run [...] -v <PATH_TO_HOME_DIR>/.docker/config.json:/config.json containrrr/watchtower
|
||||
```
|
||||
|
||||
When creating the watchtower container via docker-compose, use the following lines:
|
||||
```yaml
|
||||
version: "3"
|
||||
[...]
|
||||
watchtower:
|
||||
image: index.docker.io/containrrr/watchtower:latest
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- <PATH_TO_HOME_DIR>/.docker/config.json:/config.json
|
||||
[...]
|
||||
```
|
||||
|
||||
## Credential helpers
|
||||
Some private Docker registries (the most prominent probably being AWS ECR) use non-standard ways of authentication.
|
||||
To be able to use this together with watchtower, we need to use a credential helper.
|
||||
|
||||
To keep the image size small we've decided to not include any helpers in the watchtower image, instead we'll put the
|
||||
helper in a separate container and mount it using volumes.
|
||||
|
||||
### Example
|
||||
Example implementation for use with [amazon-ecr-credential-helper](https://github.com/awslabs/amazon-ecr-credential-helper):
|
||||
|
||||
```Dockerfile
|
||||
FROM golang:latest
|
||||
|
||||
ENV CGO_ENABLED 0
|
||||
ENV REPO github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login
|
||||
|
||||
RUN go get -u $REPO
|
||||
|
||||
RUN rm /go/bin/docker-credential-ecr-login
|
||||
|
||||
RUN go build \
|
||||
-o /go/bin/docker-credential-ecr-login \
|
||||
/go/src/$REPO
|
||||
|
||||
WORKDIR /go/bin/
|
||||
```
|
||||
|
||||
and the docker-compose definition:
|
||||
```yaml
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
watchtower:
|
||||
image: index.docker.io/containrrr/watchtower:latest
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- <PATH_TO_HOME_DIR>/.docker/config.json:/config.json
|
||||
- helper:/go/bin
|
||||
environment:
|
||||
- HOME=/
|
||||
- PATH=$PATH:/go/bin
|
||||
- AWS_REGION=<AWS_REGION>
|
||||
- AWS_ACCESS_KEY_ID=<AWS_ACCESS_KEY>
|
||||
- AWS_SECRET_ACCESS_KEY=<AWS_SECRET_ACCESS_KEY>
|
||||
volumes:
|
||||
helper: {}
|
||||
```
|
||||
|
||||
and for `<PATH_TO_HOME_DIR>/.docker/config.json`:
|
||||
```json
|
||||
{
|
||||
"HttpHeaders" : {
|
||||
"User-Agent" : "Docker-Client/19.03.1 (XXXXXX)"
|
||||
},
|
||||
"credsStore" : "osxkeychain",
|
||||
"auths" : {
|
||||
"xyzxyzxyz.dkr.ecr.eu-north-1.amazonaws.com" : {},
|
||||
"https://index.docker.io/v1/": {}
|
||||
},
|
||||
"credHelpers": {
|
||||
"xyzxyzxyz.dkr.ecr.eu-north-1.amazonaws.com" : "ecr-login",
|
||||
"index.docker.io": "osxkeychain"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Note:* `osxkeychain` can be changed to your prefered credentials helper.
|
||||
84
go.mod
84
go.mod
|
|
@ -3,63 +3,57 @@ module github.com/containrrr/watchtower
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78
|
||||
github.com/Microsoft/go-winio v0.4.12
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412
|
||||
github.com/beorn7/perks v1.0.0
|
||||
github.com/brysgo/gomock_ginkgo v0.0.0-20180512161304-be2c1b0e4111
|
||||
github.com/containerd/containerd v1.2.6 // indirect
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.12 // indirect
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 // indirect
|
||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
github.com/bugsnag/bugsnag-go v1.5.3 // indirect
|
||||
github.com/bugsnag/panicwrap v1.2.0 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cloudflare/cfssl v0.0.0-20190911221928-1a911ca1b1d6 // indirect
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect
|
||||
github.com/docker/cli v0.0.0-20190327152802-57b27434ea29
|
||||
github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/docker/docker v0.0.0-20190404075923-dbe4a30928d4
|
||||
github.com/docker/docker-credential-helpers v0.6.1
|
||||
github.com/docker/go v1.5.1-1
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82
|
||||
github.com/docker/go-units v0.3.3
|
||||
github.com/docker/swarmkit v1.12.0 // indirect
|
||||
github.com/gogo/protobuf v1.2.1
|
||||
github.com/golang/mock v1.1.1
|
||||
github.com/golang/protobuf v1.3.1
|
||||
github.com/gorilla/mux v1.7.0
|
||||
github.com/hashicorp/go-memdb v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.1.0
|
||||
github.com/inconshreveable/mousetrap v1.0.0
|
||||
github.com/johntdyer/slack-go v0.0.0-20180213144715-95fac1160b22
|
||||
github.com/docker/docker-credential-helpers v0.6.1 // indirect
|
||||
github.com/docker/go v1.5.1-1 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 // indirect
|
||||
github.com/docker/go-units v0.3.3 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
||||
github.com/google/certificate-transparency-go v1.0.21 // indirect
|
||||
github.com/gorilla/mux v1.7.0 // indirect
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
|
||||
github.com/hashicorp/go-version v1.1.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jinzhu/gorm v1.9.11 // indirect
|
||||
github.com/johntdyer/slack-go v0.0.0-20180213144715-95fac1160b22 // indirect
|
||||
github.com/johntdyer/slackrus v0.0.0-20180518184837-f7aae3243a07
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2
|
||||
github.com/mattn/go-shellwords v1.0.5 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||
github.com/miekg/pkcs11 v0.0.0-20190401114359-553cfdd26aaa
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/lib/pq v1.2.0 // indirect
|
||||
github.com/miekg/pkcs11 v0.0.0-20190401114359-553cfdd26aaa // indirect
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
|
||||
github.com/onsi/ginkgo v1.8.0
|
||||
github.com/onsi/gomega v1.5.0
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1
|
||||
github.com/opencontainers/image-spec v1.0.1
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/opencontainers/runc v0.1.1
|
||||
github.com/opencontainers/runtime-spec v1.0.1 // indirect
|
||||
github.com/opencontainers/selinux v1.2.1 // indirect
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/prometheus/client_golang v0.9.3
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90
|
||||
github.com/prometheus/common v0.4.0
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/spf13/pflag v1.0.3
|
||||
github.com/spf13/viper v1.4.0
|
||||
github.com/stretchr/objx v0.1.1
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/theupdateframework/notary v0.6.1
|
||||
github.com/vbatts/tar-split v0.11.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20190403202508-8e1b8d32e692
|
||||
github.com/theupdateframework/notary v0.6.1 // indirect
|
||||
github.com/zmap/zlint v1.0.2 // indirect
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e
|
||||
google.golang.org/genproto v0.0.0-20190401181712-f467c93bbac2
|
||||
google.golang.org/grpc v1.21.0
|
||||
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
||||
gopkg.in/fatih/pool.v2 v2.0.0 // indirect
|
||||
gopkg.in/gorethink/gorethink.v3 v3.0.5 // indirect
|
||||
gotest.tools v2.2.0+incompatible // indirect
|
||||
)
|
||||
|
|
|
|||
152
go.sum
152
go.sum
|
|
@ -1,25 +1,46 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
|
||||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
|
||||
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/brysgo/gomock_ginkgo v0.0.0-20180512161304-be2c1b0e4111 h1:gRfsoKtF1tba+hVsNgo7OKG7a35hBK30ouOTHPgqFf8=
|
||||
github.com/brysgo/gomock_ginkgo v0.0.0-20180512161304-be2c1b0e4111/go.mod h1:H1ipqq0hhUWJgVeQ5dbUe/C8YptJrE/VGDQp9bI+qTo=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/bugsnag/bugsnag-go v1.5.3 h1:yeRUT3mUE13jL1tGwvoQsKdVbAsQx9AJ+fqahKveP04=
|
||||
github.com/bugsnag/bugsnag-go v1.5.3/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA=
|
||||
github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/containerd v1.2.6 h1:K38ZSAA9oKSrX3iFNY+4SddZ8hH1TCMCerc8NHfcKBQ=
|
||||
github.com/containerd/containerd v1.2.6/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/cloudflare/cfssl v0.0.0-20190911221928-1a911ca1b1d6 h1:A7RURps5t4yDU0zktlgrE3Bdmjfv35nVs+xJdoWgIgY=
|
||||
github.com/cloudflare/cfssl v0.0.0-20190911221928-1a911ca1b1d6/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
|
|
@ -30,6 +51,8 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3 h1:tkum0XDgfR0jcVVXuTsYv/erY2NnEDqwRojbxR1rBYA=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/docker/cli v0.0.0-20190327152802-57b27434ea29 h1:ciaXDHaWQda0nvevWqcjtXX/buQY3e0lga1vq8Batq0=
|
||||
|
|
@ -48,38 +71,56 @@ github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 h1:X0fj836zx99zF
|
|||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/swarmkit v1.12.0 h1:vcbNXevt9xOod0miQxkp9WZ70IsOCe8geXkmFnXP2e0=
|
||||
github.com/docker/swarmkit v1.12.0/go.mod h1:n3Z4lIEl7g261ptkGDBcYi/3qBMDl9csaAhwi2MPejs=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=
|
||||
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
|
||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-memdb v1.0.0 h1:K1O4N2VPndZiTrdH3lmmf5bemr9Xw81KjVwhReIUjTQ=
|
||||
github.com/hashicorp/go-memdb v1.0.0/go.mod h1:I6dKdmYhZqU0RJSheVEWgTNWdVQH5QvTgIUQ0t/t32M=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
|
||||
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
|
|
@ -89,79 +130,97 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
|||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE=
|
||||
github.com/jinzhu/gorm v1.9.11/go.mod h1:bu/pK8szGZ2puuErfU0RwyeNdsf3e6nCX/noXaVxkfw=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/johntdyer/slack-go v0.0.0-20180213144715-95fac1160b22 h1:jKUP9TQ0c7X3w6+IPyMit07RE42MtTWNd77sN2cHngQ=
|
||||
github.com/johntdyer/slack-go v0.0.0-20180213144715-95fac1160b22/go.mod h1:u0Jo4f2dNlTJeeOywkM6bLwxq6gC3pZ9rEFHn3AhTdk=
|
||||
github.com/johntdyer/slackrus v0.0.0-20180518184837-f7aae3243a07 h1:+kBG/8rjCa6vxJZbUjAiE4MQmBEBYc8nLEb51frnvBY=
|
||||
github.com/johntdyer/slackrus v0.0.0-20180518184837-f7aae3243a07/go.mod h1:j1kV/8f3jowErEq4XyeypkCdvg5EeHkf0YCKCcq5Ybo=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/pkcs11 v0.0.0-20190401114359-553cfdd26aaa h1:gOXc1BXmFuxWYmTfoK51YJR7srco3CwbsVHgr+8Y4r0=
|
||||
github.com/miekg/pkcs11 v0.0.0-20190401114359-553cfdd26aaa/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.2.1 h1:Svlc+L67YcjN4K2bqD8Wlw9jtMlmZ+1FEGn6zsm8am0=
|
||||
github.com/opencontainers/selinux v1.2.1/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190403104016-ea9eea638872 h1:0aNv3xC7DmQoy1/x1sMh18g+fihWW68LL13i8ao9kl4=
|
||||
github.com/prometheus/procfs v0.0.0-20190403104016-ea9eea638872/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 h1:x7xEyJDP7Hv3LVgvWhzioQqbC/KtuUhTigKlH/8ehhE=
|
||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
|
|
@ -188,34 +247,45 @@ github.com/theupdateframework/notary v0.6.1 h1:7wshjstgS9x9F5LuB1L5mBI2xNMObWqjz
|
|||
github.com/theupdateframework/notary v0.6.1/go.mod h1:MOfgIfmox8s7/7fduvB2xyPPMJCrjRLRizA8OFwpnKY=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g=
|
||||
github.com/weppos/publicsuffix-go v0.4.0 h1:YSnfg3V65LcCFKtIGKGoBhkyKolEd0hlipcXaOjdnQw=
|
||||
github.com/weppos/publicsuffix-go v0.4.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
|
||||
github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
|
||||
github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e h1:mvOa4+/DXStR4ZXOks/UsjeFdn5O5JpLUtzqk9U8xXw=
|
||||
github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e/go.mod h1:w7kd3qXHh8FNaczNjslXqvFQiv5mMWRXlL9klTUAHc8=
|
||||
github.com/zmap/zlint v1.0.2 h1:07+WuC/prlXVlWa1CJx2lCpuCd8biIeBAVnwTN2CPaA=
|
||||
github.com/zmap/zlint v1.0.2/go.mod h1:29UiAJNsiVdvTBFCJW8e3q6dcDbOoPkhMgttOSCIMMY=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190403202508-8e1b8d32e692 h1:GRhHqDOgeDr6QDTtq9gn2O4iKvm5dsbfqD/TXb0KLX0=
|
||||
golang.org/x/crypto v0.0.0-20190403202508-8e1b8d32e692/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190403144856-b630fd6fe46b h1:/zjbcJPEGAyu6Is/VBOALsgdi4z9+kz/Vtdm6S+beD0=
|
||||
golang.org/x/net v0.0.0-20190403144856-b630fd6fe46b/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -226,32 +296,48 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190401181712-f467c93bbac2 h1:8FyEBtGg6Px24p+H2AkuVWqhj4+R9fo+fZD17mg+lzk=
|
||||
google.golang.org/genproto v0.0.0-20190401181712-f467c93bbac2/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 h1:xtNn7qFlagY2mQNFHMSRPjT2RkOV4OXM7P5TVy9xATo=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/dancannon/gorethink.v3 v3.0.5 h1:/g7PWP7zUS6vSNmHSDbjCHQh1Rqn8Jy6zSMQxAsBSMQ=
|
||||
gopkg.in/dancannon/gorethink.v3 v3.0.5/go.mod h1:GXsi1e3N2OcKhcP6nsYABTiUejbWMFO4GY5a4pEaeEc=
|
||||
gopkg.in/fatih/pool.v2 v2.0.0 h1:xIFeWtxifuQJGk/IEPKsTduEKcKvPmhoiVDGpC40nKg=
|
||||
gopkg.in/fatih/pool.v2 v2.0.0/go.mod h1:8xVGeu1/2jr2wm5V9SPuMht2H5AEmf5aFMGSQixtjTY=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gorethink/gorethink.v3 v3.0.5 h1:e2Uc/Xe+hpcVQFsj6MuHlYog3r0JYpnTzwDj/y2O4MU=
|
||||
gopkg.in/gorethink/gorethink.v3 v3.0.5/go.mod h1:+3yIIHJUGMBK+wyPH+iN5TP+88ikFDfZdqTlK3Y9q8I=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
|
|
@ -261,4 +347,6 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ dockers:
|
|||
goos: linux
|
||||
goarch: amd64
|
||||
goarm: ''
|
||||
dockerfile: Dockerfile
|
||||
dockerfile: dockerfiles/Dockerfile
|
||||
image_templates:
|
||||
- containrrr/watchtower:amd64-{{ .Version }}
|
||||
- containrrr/watchtower:amd64-latest
|
||||
|
|
@ -39,7 +39,7 @@ dockers:
|
|||
goos: linux
|
||||
goarch: 386
|
||||
goarm: ''
|
||||
dockerfile: Dockerfile
|
||||
dockerfile: dockerfiles/Dockerfile
|
||||
image_templates:
|
||||
- containrrr/watchtower:i386-{{ .Version }}
|
||||
- containrrr/watchtower:i386-latest
|
||||
|
|
@ -49,7 +49,7 @@ dockers:
|
|||
goos: linux
|
||||
goarch: arm
|
||||
goarm: 6
|
||||
dockerfile: Dockerfile
|
||||
dockerfile: dockerfiles/Dockerfile
|
||||
image_templates:
|
||||
- containrrr/watchtower:armhf-{{ .Version }}
|
||||
- containrrr/watchtower:armhf-latest
|
||||
|
|
@ -59,7 +59,7 @@ dockers:
|
|||
goos: linux
|
||||
goarch: arm64
|
||||
goarm: ''
|
||||
dockerfile: Dockerfile
|
||||
dockerfile: dockerfiles/Dockerfile
|
||||
image_templates:
|
||||
- containrrr/watchtower:arm64v8-{{ .Version }}
|
||||
- containrrr/watchtower:arm64v8-latest
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
package actions_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/containrrr/watchtower/internal/actions"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"github.com/containrrr/watchtower/pkg/container/mocks"
|
||||
"github.com/docker/docker/api/types"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
cli "github.com/docker/docker/client"
|
||||
|
||||
. "github.com/containrrr/watchtower/internal/actions/mocks"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
|
@ -24,7 +22,7 @@ func TestActions(t *testing.T) {
|
|||
|
||||
var _ = Describe("the actions package", func() {
|
||||
var dockerClient cli.CommonAPIClient
|
||||
var client mockClient
|
||||
var client MockClient
|
||||
BeforeSuite(func() {
|
||||
server := mocks.NewMockAPIServer()
|
||||
dockerClient, _ = cli.NewClientWithOpts(
|
||||
|
|
@ -32,12 +30,15 @@ var _ = Describe("the actions package", func() {
|
|||
cli.WithHTTPClient(server.Client()))
|
||||
})
|
||||
BeforeEach(func() {
|
||||
client = mockClient{
|
||||
api: dockerClient,
|
||||
pullImages: false,
|
||||
removeVolumes: false,
|
||||
TestData: &TestData{},
|
||||
}
|
||||
pullImages := false
|
||||
removeVolumes := false
|
||||
|
||||
client = CreateMockClient(
|
||||
&TestData {},
|
||||
dockerClient,
|
||||
pullImages,
|
||||
removeVolumes,
|
||||
)
|
||||
})
|
||||
|
||||
Describe("the check prerequisites method", func() {
|
||||
|
|
@ -51,7 +52,7 @@ var _ = Describe("the actions package", func() {
|
|||
When("given an array of one", func() {
|
||||
It("should not do anything", func() {
|
||||
client.TestData.Containers = []container.Container{
|
||||
createMockContainer(
|
||||
CreateMockContainer(
|
||||
"test-container",
|
||||
"test-container",
|
||||
"watchtower",
|
||||
|
|
@ -63,27 +64,30 @@ var _ = Describe("the actions package", func() {
|
|||
})
|
||||
When("given multiple containers", func() {
|
||||
BeforeEach(func() {
|
||||
client = mockClient{
|
||||
api: dockerClient,
|
||||
pullImages: false,
|
||||
removeVolumes: false,
|
||||
TestData: &TestData{
|
||||
pullImages := false
|
||||
removeVolumes := false
|
||||
client = CreateMockClient(
|
||||
&TestData{
|
||||
NameOfContainerToKeep: "test-container-02",
|
||||
Containers: []container.Container{
|
||||
createMockContainer(
|
||||
CreateMockContainer(
|
||||
"test-container-01",
|
||||
"test-container-01",
|
||||
"watchtower",
|
||||
time.Now().AddDate(0, 0, -1)),
|
||||
createMockContainer(
|
||||
CreateMockContainer(
|
||||
"test-container-02",
|
||||
"test-container-02",
|
||||
"watchtower",
|
||||
time.Now()),
|
||||
},
|
||||
},
|
||||
}
|
||||
dockerClient,
|
||||
pullImages,
|
||||
removeVolumes,
|
||||
)
|
||||
})
|
||||
|
||||
It("should stop all but the latest one", func() {
|
||||
err := actions.CheckForMultipleWatchtowerInstances(client, false)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
|
@ -91,96 +95,40 @@ var _ = Describe("the actions package", func() {
|
|||
})
|
||||
When("deciding whether to cleanup images", func() {
|
||||
BeforeEach(func() {
|
||||
client = mockClient{
|
||||
api: dockerClient,
|
||||
pullImages: false,
|
||||
removeVolumes: false,
|
||||
TestData: &TestData{
|
||||
pullImages := false
|
||||
removeVolumes := false
|
||||
|
||||
client = CreateMockClient(
|
||||
&TestData{
|
||||
Containers: []container.Container{
|
||||
createMockContainer(
|
||||
CreateMockContainer(
|
||||
"test-container-01",
|
||||
"test-container-01",
|
||||
"watchtower",
|
||||
time.Now().AddDate(0, 0, -1)),
|
||||
createMockContainer(
|
||||
CreateMockContainer(
|
||||
"test-container-02",
|
||||
"test-container-02",
|
||||
"watchtower",
|
||||
time.Now()),
|
||||
},
|
||||
},
|
||||
}
|
||||
dockerClient,
|
||||
pullImages,
|
||||
removeVolumes,
|
||||
)
|
||||
})
|
||||
It("should try to delete the image if the cleanup flag is true", func() {
|
||||
err := actions.CheckForMultipleWatchtowerInstances(client, true)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(client.TestData.TriedToRemoveImage).To(BeTrue())
|
||||
Expect(client.TestData.TriedToRemoveImage()).To(BeTrue())
|
||||
})
|
||||
It("should not try to delete the image if the cleanup flag is false", func() {
|
||||
err := actions.CheckForMultipleWatchtowerInstances(client, false)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(client.TestData.TriedToRemoveImage).To(BeFalse())
|
||||
Expect(client.TestData.TriedToRemoveImage()).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
func createMockContainer(id string, name string, image string, created time.Time) container.Container {
|
||||
content := types.ContainerJSON{
|
||||
ContainerJSONBase: &types.ContainerJSONBase{
|
||||
ID: id,
|
||||
Image: image,
|
||||
Name: name,
|
||||
Created: created.String(),
|
||||
},
|
||||
}
|
||||
return *container.NewContainer(&content, nil)
|
||||
}
|
||||
|
||||
type mockClient struct {
|
||||
TestData *TestData
|
||||
api cli.CommonAPIClient
|
||||
pullImages bool
|
||||
removeVolumes bool
|
||||
}
|
||||
|
||||
type TestData struct {
|
||||
TriedToRemoveImage bool
|
||||
NameOfContainerToKeep string
|
||||
Containers []container.Container
|
||||
}
|
||||
|
||||
func (client mockClient) ListContainers(f t.Filter) ([]container.Container, error) {
|
||||
return client.TestData.Containers, nil
|
||||
}
|
||||
|
||||
func (client mockClient) StopContainer(c container.Container, d time.Duration) error {
|
||||
if c.Name() == client.TestData.NameOfContainerToKeep {
|
||||
return errors.New("tried to stop the instance we want to keep")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (client mockClient) StartContainer(c container.Container) (string, error) {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (client mockClient) RenameContainer(c container.Container, s string) error {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
||||
func (client mockClient) RemoveImage(c container.Container) error {
|
||||
client.TestData.TriedToRemoveImage = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client mockClient) GetContainer(containerID string) (container.Container, error) {
|
||||
return container.Container{}, nil
|
||||
}
|
||||
|
||||
func (client mockClient) ExecuteCommand(containerID string, command string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client mockClient) IsContainerStale(c container.Container) (bool, error) {
|
||||
panic("Not implemented")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package actions
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/containrrr/watchtower/pkg/filters"
|
||||
"github.com/containrrr/watchtower/pkg/sorter"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -19,7 +21,7 @@ import (
|
|||
// will stop and remove all but the most recently started container.
|
||||
func CheckForMultipleWatchtowerInstances(client container.Client, cleanup bool) error {
|
||||
awaitDockerClient()
|
||||
containers, err := client.ListContainers(container.WatchtowerContainersFilter)
|
||||
containers, err := client.ListContainers(filters.WatchtowerContainersFilter)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
@ -39,7 +41,7 @@ func cleanupExcessWatchtowers(containers []container.Container, client container
|
|||
var cleanupErrors int
|
||||
var stopErrors int
|
||||
|
||||
sort.Sort(container.ByCreated(containers))
|
||||
sort.Sort(sorter.ByCreated(containers))
|
||||
allContainersExceptLast := containers[0 : len(containers)-1]
|
||||
|
||||
for _, c := range allContainersExceptLast {
|
||||
|
|
@ -51,7 +53,7 @@ func cleanupExcessWatchtowers(containers []container.Container, client container
|
|||
}
|
||||
|
||||
if cleanup {
|
||||
if err := client.RemoveImage(c); err != nil {
|
||||
if err := client.RemoveImageByID(c.ImageID()); err != nil {
|
||||
// logging the original here as we're just returning a count
|
||||
logrus.Error(err)
|
||||
cleanupErrors++
|
||||
|
|
|
|||
84
internal/actions/mocks/client.go
Normal file
84
internal/actions/mocks/client.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"time"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
cli "github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
// MockClient is a mock that passes as a watchtower Client
|
||||
type MockClient struct {
|
||||
TestData *TestData
|
||||
api cli.CommonAPIClient
|
||||
pullImages bool
|
||||
removeVolumes bool
|
||||
}
|
||||
|
||||
// TestData is the data used to perform the test
|
||||
type TestData struct {
|
||||
TriedToRemoveImageCount int
|
||||
NameOfContainerToKeep string
|
||||
Containers []container.Container
|
||||
}
|
||||
|
||||
// TriedToRemoveImage is a test helper function to check whether RemoveImageByID has been called
|
||||
func (testdata *TestData) TriedToRemoveImage() bool {
|
||||
return testdata.TriedToRemoveImageCount > 0
|
||||
}
|
||||
|
||||
// CreateMockClient creates a mock watchtower Client for usage in tests
|
||||
func CreateMockClient(data *TestData, api cli.CommonAPIClient, pullImages bool, removeVolumes bool) MockClient {
|
||||
return MockClient {
|
||||
data,
|
||||
api,
|
||||
pullImages,
|
||||
removeVolumes,
|
||||
}
|
||||
}
|
||||
|
||||
// ListContainers is a mock method returning the provided container testdata
|
||||
func (client MockClient) ListContainers(f t.Filter) ([]container.Container, error) {
|
||||
return client.TestData.Containers, nil
|
||||
}
|
||||
|
||||
// StopContainer is a mock method
|
||||
func (client MockClient) StopContainer(c container.Container, d time.Duration) error {
|
||||
if c.Name() == client.TestData.NameOfContainerToKeep {
|
||||
return errors.New("tried to stop the instance we want to keep")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartContainer is a mock method
|
||||
func (client MockClient) StartContainer(c container.Container) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
// RenameContainer is a mock method
|
||||
func (client MockClient) RenameContainer(c container.Container, s string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveImageByID increments the TriedToRemoveImageCount on being called
|
||||
func (client MockClient) RemoveImageByID(id string) error {
|
||||
client.TestData.TriedToRemoveImageCount++
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetContainer is a mock method
|
||||
func (client MockClient) GetContainer(containerID string) (container.Container, error) {
|
||||
return container.Container{}, nil
|
||||
}
|
||||
|
||||
// ExecuteCommand is a mock method
|
||||
func (client MockClient) ExecuteCommand(containerID string, command string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsContainerStale is always true for the mock client
|
||||
func (client MockClient) IsContainerStale(c container.Container) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
29
internal/actions/mocks/container.go
Normal file
29
internal/actions/mocks/container.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"github.com/docker/docker/api/types"
|
||||
container2 "github.com/docker/docker/api/types/container"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CreateMockContainer creates a container substitute valid for testing
|
||||
func CreateMockContainer(id string, name string, image string, created time.Time) container.Container {
|
||||
content := types.ContainerJSON{
|
||||
ContainerJSONBase: &types.ContainerJSONBase{
|
||||
ID: id,
|
||||
Image: image,
|
||||
Name: name,
|
||||
Created: created.String(),
|
||||
},
|
||||
Config: &container2.Config{
|
||||
Labels: make(map[string]string),
|
||||
},
|
||||
}
|
||||
return *container.NewContainer(
|
||||
&content,
|
||||
&types.ImageInspect{
|
||||
ID: image,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@ package actions
|
|||
import (
|
||||
"github.com/containrrr/watchtower/internal/util"
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"github.com/containrrr/watchtower/pkg/lifecycle"
|
||||
"github.com/containrrr/watchtower/pkg/sorter"
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
|
@ -10,10 +13,12 @@ import (
|
|||
// used to start those containers have been updated. If a change is detected in
|
||||
// any of the images, the associated containers are stopped and restarted with
|
||||
// the new image.
|
||||
func Update(client container.Client, params UpdateParams) error {
|
||||
func Update(client container.Client, params types.UpdateParams) error {
|
||||
log.Debug("Checking containers for updated images")
|
||||
|
||||
executePreCheck(client, params)
|
||||
if params.LifecycleHooks {
|
||||
lifecycle.ExecutePreChecks(client, params)
|
||||
}
|
||||
|
||||
containers, err := client.ListContainers(params.Filter)
|
||||
if err != nil {
|
||||
|
|
@ -30,7 +35,7 @@ func Update(client container.Client, params UpdateParams) error {
|
|||
containers[i].Stale = stale
|
||||
}
|
||||
|
||||
containers, err = container.SortByDependencies(containers)
|
||||
containers, err = sorter.SortByDependencies(containers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -38,24 +43,28 @@ func Update(client container.Client, params UpdateParams) error {
|
|||
checkDependencies(containers)
|
||||
|
||||
if params.MonitorOnly {
|
||||
executePostCheck(client, params)
|
||||
if params.LifecycleHooks {
|
||||
lifecycle.ExecutePostChecks(client, params)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
stopContainersInReversedOrder(containers, client, params)
|
||||
restartContainersInSortedOrder(containers, client, params)
|
||||
|
||||
executePostCheck(client, params)
|
||||
if params.LifecycleHooks {
|
||||
lifecycle.ExecutePostChecks(client, params)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stopContainersInReversedOrder(containers []container.Container, client container.Client, params UpdateParams) {
|
||||
func stopContainersInReversedOrder(containers []container.Container, client container.Client, params types.UpdateParams) {
|
||||
for i := len(containers) - 1; i >= 0; i-- {
|
||||
stopStaleContainer(containers[i], client, params)
|
||||
}
|
||||
}
|
||||
|
||||
func stopStaleContainer(container container.Container, client container.Client, params UpdateParams) {
|
||||
func stopStaleContainer(container container.Container, client container.Client, params types.UpdateParams) {
|
||||
if container.IsWatchtower() {
|
||||
log.Debugf("This is the watchtower container %s", container.Name())
|
||||
return
|
||||
|
|
@ -64,24 +73,36 @@ func stopStaleContainer(container container.Container, client container.Client,
|
|||
if !container.Stale {
|
||||
return
|
||||
}
|
||||
if params.LifecycleHooks {
|
||||
lifecycle.ExecutePreUpdateCommand(client, container)
|
||||
|
||||
executePreUpdateCommand(client, container)
|
||||
}
|
||||
|
||||
if err := client.StopContainer(container, params.Timeout); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func restartContainersInSortedOrder(containers []container.Container, client container.Client, params UpdateParams) {
|
||||
func restartContainersInSortedOrder(containers []container.Container, client container.Client, params types.UpdateParams) {
|
||||
imageIDs := make(map[string]bool)
|
||||
|
||||
for _, container := range containers {
|
||||
if !container.Stale {
|
||||
continue
|
||||
}
|
||||
restartStaleContainer(container, client, params)
|
||||
imageIDs[container.ImageID()] = true
|
||||
}
|
||||
if params.Cleanup {
|
||||
for imageID := range imageIDs {
|
||||
if err := client.RemoveImageByID(imageID); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func restartStaleContainer(container container.Container, client container.Client, params UpdateParams) {
|
||||
func restartStaleContainer(container container.Container, client container.Client, params types.UpdateParams) {
|
||||
// Since we can't shutdown a watchtower container immediately, we need to
|
||||
// start the new one while the old one is still running. This prevents us
|
||||
// from re-using the same container name so we first rename the current
|
||||
|
|
@ -97,13 +118,7 @@ func restartStaleContainer(container container.Container, client container.Clien
|
|||
if newContainerID, err := client.StartContainer(container); err != nil {
|
||||
log.Error(err)
|
||||
} else if container.Stale && params.LifecycleHooks {
|
||||
executePostUpdateCommand(client, newContainerID)
|
||||
}
|
||||
}
|
||||
|
||||
if params.Cleanup {
|
||||
if err := client.RemoveImage(container); err != nil {
|
||||
log.Error(err)
|
||||
lifecycle.ExecutePostUpdateCommand(client, newContainerID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -126,82 +141,3 @@ func checkDependencies(containers []container.Container) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func executePreCheck(client container.Client, params UpdateParams) {
|
||||
containers, err := client.ListContainers(params.Filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, container := range containers {
|
||||
executePreCheckCommand(client, container)
|
||||
}
|
||||
}
|
||||
|
||||
func executePostCheck(client container.Client, params UpdateParams) {
|
||||
containers, err := client.ListContainers(params.Filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, container := range containers {
|
||||
executePostCheckCommand(client, container)
|
||||
}
|
||||
}
|
||||
|
||||
func executePreCheckCommand(client container.Client, container container.Container) {
|
||||
command := container.GetLifecyclePreCheckCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No pre-check command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing pre-check command.")
|
||||
if err := client.ExecuteCommand(container.ID(), command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func executePostCheckCommand(client container.Client, container container.Container) {
|
||||
command := container.GetLifecyclePostCheckCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No post-check command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing post-check command.")
|
||||
if err := client.ExecuteCommand(container.ID(), command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func executePreUpdateCommand(client container.Client, container container.Container) {
|
||||
|
||||
command := container.GetLifecyclePreUpdateCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No pre-update command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing pre-update command.")
|
||||
if err := client.ExecuteCommand(container.ID(), command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func executePostUpdateCommand(client container.Client, newContainerID string) {
|
||||
newContainer, err := client.GetContainer(newContainerID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
command := newContainer.GetLifecyclePostUpdateCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No post-update command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing post-update command.")
|
||||
if err := client.ExecuteCommand(newContainerID, command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
85
internal/actions/update_test.go
Normal file
85
internal/actions/update_test.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package actions_test
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/internal/actions"
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"github.com/containrrr/watchtower/pkg/container/mocks"
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
cli "github.com/docker/docker/client"
|
||||
"time"
|
||||
|
||||
. "github.com/containrrr/watchtower/internal/actions/mocks"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
|
||||
var _ = Describe("the update action", func() {
|
||||
var dockerClient cli.CommonAPIClient
|
||||
var client MockClient
|
||||
|
||||
BeforeEach(func() {
|
||||
server := mocks.NewMockAPIServer()
|
||||
dockerClient, _ = cli.NewClientWithOpts(
|
||||
cli.WithHost(server.URL),
|
||||
cli.WithHTTPClient(server.Client()))
|
||||
})
|
||||
|
||||
|
||||
When("watchtower has been instructed to clean up", func() {
|
||||
BeforeEach(func() {
|
||||
pullImages := false
|
||||
removeVolumes := false
|
||||
client = CreateMockClient(
|
||||
&TestData{
|
||||
NameOfContainerToKeep: "test-container-02",
|
||||
Containers: []container.Container{
|
||||
CreateMockContainer(
|
||||
"test-container-01",
|
||||
"test-container-01",
|
||||
"fake-image:latest",
|
||||
time.Now().AddDate(0, 0, -1)),
|
||||
CreateMockContainer(
|
||||
"test-container-02",
|
||||
"test-container-02",
|
||||
"fake-image:latest",
|
||||
time.Now()),
|
||||
CreateMockContainer(
|
||||
"test-container-02",
|
||||
"test-container-02",
|
||||
"fake-image:latest",
|
||||
time.Now()),
|
||||
},
|
||||
},
|
||||
dockerClient,
|
||||
pullImages,
|
||||
removeVolumes,
|
||||
)
|
||||
})
|
||||
|
||||
When("there are multiple containers using the same image", func() {
|
||||
It("should only try to remove the image once", func() {
|
||||
|
||||
err := actions.Update(client, types.UpdateParams{ Cleanup: true })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(client.TestData.TriedToRemoveImageCount).To(Equal(1))
|
||||
})
|
||||
})
|
||||
When("there are multiple containers using different images", func() {
|
||||
It("should try to remove each of them", func() {
|
||||
client.TestData.Containers = append(
|
||||
client.TestData.Containers,
|
||||
CreateMockContainer(
|
||||
"unique-test-container",
|
||||
"unique-test-container",
|
||||
"unique-fake-image:latest",
|
||||
time.Now(),
|
||||
),
|
||||
)
|
||||
err := actions.Update(client, types.UpdateParams{ Cleanup: true })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(client.TestData.TriedToRemoveImageCount).To(Equal(2))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -14,7 +14,7 @@ nav:
|
|||
- 'Arguments': 'arguments.md'
|
||||
- 'Notifications': 'notifications.md'
|
||||
- 'Container selection': 'container-selection.md'
|
||||
- 'Credential helpers': 'credential-helpers.md'
|
||||
- 'Private registries': 'private-registries.md'
|
||||
- 'Linked containers': 'linked-containers.md'
|
||||
- 'Remote hosts': 'remote-hosts.md'
|
||||
- 'Secure connections': 'secure-connections.md'
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package container
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/containrrr/watchtower/pkg/registry"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -12,7 +13,7 @@ import (
|
|||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
sdkClient "github.com/docker/docker/client"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
|
@ -29,7 +30,8 @@ type Client interface {
|
|||
RenameContainer(Container, string) error
|
||||
IsContainerStale(Container) (bool, error)
|
||||
ExecuteCommand(containerID string, command string) error
|
||||
RemoveImage(Container) error
|
||||
RemoveImageByID(string) error
|
||||
|
||||
}
|
||||
|
||||
// NewClient returns a new Client instance which can be used to interact with
|
||||
|
|
@ -39,7 +41,7 @@ type Client interface {
|
|||
// * DOCKER_TLS_VERIFY whether to verify tls certificates
|
||||
// * DOCKER_API_VERSION the minimum docker api version to work with
|
||||
func NewClient(pullImages bool, includeStopped bool, reviveStopped bool, removeVolumes bool) Client {
|
||||
cli, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv)
|
||||
cli, err := sdkClient.NewClientWithOpts(sdkClient.FromEnv)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Error instantiating Docker client: %s", err)
|
||||
|
|
@ -55,7 +57,7 @@ func NewClient(pullImages bool, includeStopped bool, reviveStopped bool, removeV
|
|||
}
|
||||
|
||||
type dockerClient struct {
|
||||
api dockerclient.CommonAPIClient
|
||||
api sdkClient.CommonAPIClient
|
||||
pullImages bool
|
||||
removeVolumes bool
|
||||
includeStopped bool
|
||||
|
|
@ -156,7 +158,7 @@ func (client dockerClient) StopContainer(c Container, timeout time.Duration) err
|
|||
|
||||
// Wait for container to be removed. In this case an error is a good thing
|
||||
if err := client.waitForStopOrTimeout(c, timeout); err == nil {
|
||||
return fmt.Errorf("Container %s (%s) could not be removed", c.Name(), c.ID())
|
||||
return fmt.Errorf("container %s (%s) could not be removed", c.Name(), c.ID())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -230,59 +232,72 @@ func (client dockerClient) RenameContainer(c Container, newName string) error {
|
|||
return client.api.ContainerRename(bg, c.ID(), newName)
|
||||
}
|
||||
|
||||
func (client dockerClient) IsContainerStale(c Container) (bool, error) {
|
||||
bg := context.Background()
|
||||
oldImageInfo := c.imageInfo
|
||||
imageName := c.ImageName()
|
||||
func (client dockerClient) IsContainerStale(container Container) (bool, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
if client.pullImages {
|
||||
log.Debugf("Pulling %s for %s", imageName, c.Name())
|
||||
|
||||
var opts types.ImagePullOptions // ImagePullOptions can take a RegistryAuth arg to authenticate against a private registry
|
||||
auth, err := EncodedAuth(imageName)
|
||||
log.Debugf("Got auth value: %s", auth)
|
||||
log.Debugf("Got image name: %s", imageName)
|
||||
if err != nil {
|
||||
log.Debugf("Error loading authentication credentials %s", err)
|
||||
return false, err
|
||||
} else if auth == "" {
|
||||
log.Debugf("No authentication credentials found for %s", imageName)
|
||||
opts = types.ImagePullOptions{} // empty/no auth credentials
|
||||
} else {
|
||||
opts = types.ImagePullOptions{RegistryAuth: auth, PrivilegeFunc: DefaultAuthHandler}
|
||||
}
|
||||
|
||||
response, err := client.api.ImagePull(bg, imageName, opts)
|
||||
if err != nil {
|
||||
log.Debugf("Error pulling image %s, %s", imageName, err)
|
||||
return false, err
|
||||
}
|
||||
defer response.Close()
|
||||
|
||||
// the pull request will be aborted prematurely unless the response is read
|
||||
if _, err = ioutil.ReadAll(response); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
if !client.pullImages {
|
||||
log.Debugf("Skipping image pull.")
|
||||
} else if err := client.PullImage(ctx, container); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
newImageInfo, _, err := client.api.ImageInspectWithRaw(bg, imageName)
|
||||
return client.HasNewImage(ctx, container)
|
||||
}
|
||||
|
||||
func (client dockerClient) HasNewImage(ctx context.Context, container Container) (bool, error) {
|
||||
oldImageID := container.imageInfo.ID
|
||||
imageName := container.ImageName()
|
||||
|
||||
newImageInfo, _, err := client.api.ImageInspectWithRaw(ctx, imageName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if newImageInfo.ID != oldImageInfo.ID {
|
||||
log.Infof("Found new %s image (%s)", imageName, newImageInfo.ID)
|
||||
return true, nil
|
||||
if newImageInfo.ID == oldImageID {
|
||||
log.Debugf("No new images found for %s", container.Name())
|
||||
return false, nil
|
||||
}
|
||||
|
||||
log.Debugf("No new images found for %s", c.Name())
|
||||
return false, nil
|
||||
log.Infof("Found new %s image (%s)", imageName, newImageInfo.ID)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (client dockerClient) RemoveImage(c Container) error {
|
||||
imageID := c.ImageID()
|
||||
log.Infof("Removing image %s", imageID)
|
||||
_, err := client.api.ImageRemove(context.Background(), imageID, types.ImageRemoveOptions{Force: true})
|
||||
func (client dockerClient) PullImage(ctx context.Context, container Container) error {
|
||||
containerName := container.Name()
|
||||
imageName := container.ImageName()
|
||||
log.Debugf("Pulling %s for %s", imageName, containerName)
|
||||
|
||||
opts, err := registry.GetPullOptions(imageName)
|
||||
if err != nil {
|
||||
log.Debugf("Error loading authentication credentials %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
response, err := client.api.ImagePull(ctx, imageName, opts)
|
||||
if err != nil {
|
||||
log.Debugf("Error pulling image %s, %s", imageName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer response.Close()
|
||||
// the pull request will be aborted prematurely unless the response is read
|
||||
if _, err = ioutil.ReadAll(response); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client dockerClient) RemoveImageByID(id string) error {
|
||||
log.Infof("Removing image %s", id)
|
||||
|
||||
_, err := client.api.ImageRemove(
|
||||
context.Background(),
|
||||
id,
|
||||
types.ImageRemoveOptions{
|
||||
Force: true,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ type Container struct {
|
|||
imageInfo *types.ImageInspect
|
||||
}
|
||||
|
||||
// ContainerInfo fetches JSON info for the container
|
||||
func (c Container) ContainerInfo() *types.ContainerJSON {
|
||||
return c.containerInfo
|
||||
}
|
||||
|
||||
// ID returns the Docker container ID.
|
||||
func (c Container) ID() string {
|
||||
return c.containerInfo.ID
|
||||
|
|
@ -133,6 +138,7 @@ func (c Container) StopSignal() string {
|
|||
// the options overridden at runtime.
|
||||
func (c Container) runtimeConfig() *dockercontainer.Config {
|
||||
config := c.containerInfo.Config
|
||||
hostConfig := c.containerInfo.HostConfig
|
||||
imageConfig := c.imageInfo.Config
|
||||
|
||||
if config.WorkingDir == imageConfig.WorkingDir {
|
||||
|
|
@ -143,6 +149,10 @@ func (c Container) runtimeConfig() *dockercontainer.Config {
|
|||
config.User = ""
|
||||
}
|
||||
|
||||
if hostConfig.NetworkMode.IsContainer() {
|
||||
config.Hostname = ""
|
||||
}
|
||||
|
||||
if util.SliceEqual(config.Entrypoint, imageConfig.Entrypoint) {
|
||||
config.Entrypoint = nil
|
||||
if util.SliceEqual(config.Cmd, imageConfig.Cmd) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package container
|
|||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/container/mocks"
|
||||
"github.com/containrrr/watchtower/pkg/filters"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
cli "github.com/docker/docker/client"
|
||||
|
|
@ -34,14 +35,14 @@ var _ = Describe("the container", func() {
|
|||
})
|
||||
When("listing containers without any filter", func() {
|
||||
It("should return all available containers", func() {
|
||||
containers, err := client.ListContainers(noFilter)
|
||||
containers, err := client.ListContainers(filters.NoFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(containers) == 2).To(BeTrue())
|
||||
})
|
||||
})
|
||||
When("listing containers with a filter matching nothing", func() {
|
||||
It("should return an empty array", func() {
|
||||
filter := filterByNames([]string{"lollercoaster"}, noFilter)
|
||||
filter := filters.FilterByNames([]string{"lollercoaster"}, filters.NoFilter)
|
||||
containers, err := client.ListContainers(filter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(containers) == 0).To(BeTrue())
|
||||
|
|
@ -49,7 +50,7 @@ var _ = Describe("the container", func() {
|
|||
})
|
||||
When("listing containers with a watchtower filter", func() {
|
||||
It("should return only the watchtower container", func() {
|
||||
containers, err := client.ListContainers(WatchtowerContainersFilter)
|
||||
containers, err := client.ListContainers(filters.WatchtowerContainersFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(containers) == 1).To(BeTrue())
|
||||
Expect(containers[0].ImageName()).To(Equal("containrrr/watchtower:latest"))
|
||||
|
|
@ -62,7 +63,7 @@ var _ = Describe("the container", func() {
|
|||
pullImages: false,
|
||||
includeStopped: true,
|
||||
}
|
||||
containers, err := client.ListContainers(noFilter)
|
||||
containers, err := client.ListContainers(filters.NoFilter)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(containers) > 0).To(BeTrue())
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
package container
|
||||
package filters
|
||||
|
||||
import t "github.com/containrrr/watchtower/pkg/types"
|
||||
|
||||
// WatchtowerContainersFilter filters only watchtower containers
|
||||
func WatchtowerContainersFilter(c t.FilterableContainer) bool { return c.IsWatchtower() }
|
||||
|
||||
// Filter no containers and returns all
|
||||
func noFilter(t.FilterableContainer) bool { return true }
|
||||
// NoFilter will not filter out any containers
|
||||
func NoFilter(t.FilterableContainer) bool { return true }
|
||||
|
||||
// Filters containers which don't have a specified name
|
||||
func filterByNames(names []string, baseFilter t.Filter) t.Filter {
|
||||
// FilterByNames returns all containers that match the specified name
|
||||
func FilterByNames(names []string, baseFilter t.Filter) t.Filter {
|
||||
if len(names) == 0 {
|
||||
return baseFilter
|
||||
}
|
||||
|
|
@ -24,8 +24,8 @@ func filterByNames(names []string, baseFilter t.Filter) t.Filter {
|
|||
}
|
||||
}
|
||||
|
||||
// Filters out containers that don't have the 'enableLabel'
|
||||
func filterByEnableLabel(baseFilter t.Filter) t.Filter {
|
||||
// FilterByEnableLabel returns all containers that have the enabled label set
|
||||
func FilterByEnableLabel(baseFilter t.Filter) t.Filter {
|
||||
return func(c t.FilterableContainer) bool {
|
||||
// If label filtering is enabled, containers should only be considered
|
||||
// if the label is specifically set.
|
||||
|
|
@ -38,8 +38,8 @@ func filterByEnableLabel(baseFilter t.Filter) t.Filter {
|
|||
}
|
||||
}
|
||||
|
||||
// Filters out containers that have a 'enableLabel' and is set to disable.
|
||||
func filterByDisabledLabel(baseFilter t.Filter) t.Filter {
|
||||
// FilterByDisabledLabel returns all containers that have the enabled label set to disable
|
||||
func FilterByDisabledLabel(baseFilter t.Filter) t.Filter {
|
||||
return func(c t.FilterableContainer) bool {
|
||||
enabledLabel, ok := c.Enabled()
|
||||
if ok && !enabledLabel {
|
||||
|
|
@ -53,13 +53,13 @@ func filterByDisabledLabel(baseFilter t.Filter) t.Filter {
|
|||
|
||||
// BuildFilter creates the needed filter of containers
|
||||
func BuildFilter(names []string, enableLabel bool) t.Filter {
|
||||
filter := noFilter
|
||||
filter = filterByNames(names, filter)
|
||||
filter := NoFilter
|
||||
filter = FilterByNames(names, filter)
|
||||
if enableLabel {
|
||||
// If label filtering is enabled, containers should only be considered
|
||||
// if the label is specifically set.
|
||||
filter = filterByEnableLabel(filter)
|
||||
filter = FilterByEnableLabel(filter)
|
||||
}
|
||||
filter = filterByDisabledLabel(filter)
|
||||
filter = FilterByDisabledLabel(filter)
|
||||
return filter
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package container
|
||||
package filters
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
|
@ -20,7 +20,7 @@ func TestWatchtowerContainersFilter(t *testing.T) {
|
|||
func TestNoFilter(t *testing.T) {
|
||||
container := new(mocks.FilterableContainer)
|
||||
|
||||
assert.True(t, noFilter(container))
|
||||
assert.True(t, NoFilter(container))
|
||||
|
||||
container.AssertExpectations(t)
|
||||
}
|
||||
|
|
@ -28,12 +28,12 @@ func TestNoFilter(t *testing.T) {
|
|||
func TestFilterByNames(t *testing.T) {
|
||||
var names []string
|
||||
|
||||
filter := filterByNames(names, nil)
|
||||
filter := FilterByNames(names, nil)
|
||||
assert.Nil(t, filter)
|
||||
|
||||
names = append(names, "test")
|
||||
|
||||
filter = filterByNames(names, noFilter)
|
||||
filter = FilterByNames(names, NoFilter)
|
||||
assert.NotNil(t, filter)
|
||||
|
||||
container := new(mocks.FilterableContainer)
|
||||
|
|
@ -48,7 +48,7 @@ func TestFilterByNames(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFilterByEnableLabel(t *testing.T) {
|
||||
filter := filterByEnableLabel(noFilter)
|
||||
filter := FilterByEnableLabel(NoFilter)
|
||||
assert.NotNil(t, filter)
|
||||
|
||||
container := new(mocks.FilterableContainer)
|
||||
|
|
@ -68,7 +68,7 @@ func TestFilterByEnableLabel(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFilterByDisabledLabel(t *testing.T) {
|
||||
filter := filterByDisabledLabel(noFilter)
|
||||
filter := FilterByDisabledLabel(NoFilter)
|
||||
assert.NotNil(t, filter)
|
||||
|
||||
container := new(mocks.FilterableContainer)
|
||||
93
pkg/lifecycle/lifecycle.go
Normal file
93
pkg/lifecycle/lifecycle.go
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package lifecycle
|
||||
|
||||
import (
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"github.com/containrrr/watchtower/pkg/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ExecutePreChecks tries to run the pre-check lifecycle hook for all containers included by the current filter.
|
||||
func ExecutePreChecks(client container.Client, params types.UpdateParams) {
|
||||
containers, err := client.ListContainers(params.Filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, container := range containers {
|
||||
ExecutePreCheckCommand(client, container)
|
||||
}
|
||||
}
|
||||
|
||||
// ExecutePostChecks tries to run the post-check lifecycle hook for all containers included by the current filter.
|
||||
func ExecutePostChecks(client container.Client, params types.UpdateParams) {
|
||||
containers, err := client.ListContainers(params.Filter)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, container := range containers {
|
||||
ExecutePostCheckCommand(client, container)
|
||||
}
|
||||
}
|
||||
|
||||
// ExecutePreCheckCommand tries to run the pre-check lifecycle hook for a single container.
|
||||
func ExecutePreCheckCommand(client container.Client, container container.Container) {
|
||||
command := container.GetLifecyclePreCheckCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No pre-check command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing pre-check command.")
|
||||
if err := client.ExecuteCommand(container.ID(), command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ExecutePostCheckCommand tries to run the post-check lifecycle hook for a single container.
|
||||
func ExecutePostCheckCommand(client container.Client, container container.Container) {
|
||||
command := container.GetLifecyclePostCheckCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No post-check command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing post-check command.")
|
||||
if err := client.ExecuteCommand(container.ID(), command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ExecutePreUpdateCommand tries to run the pre-update lifecycle hook for a single container.
|
||||
func ExecutePreUpdateCommand(client container.Client, container container.Container) {
|
||||
|
||||
command := container.GetLifecyclePreUpdateCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No pre-update command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing pre-update command.")
|
||||
if err := client.ExecuteCommand(container.ID(), command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ExecutePostUpdateCommand tries to run the post-update lifecycle hook for a single container.
|
||||
func ExecutePostUpdateCommand(client container.Client, newContainerID string) {
|
||||
newContainer, err := client.GetContainer(newContainerID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
command := newContainer.GetLifecyclePostUpdateCommand()
|
||||
if len(command) == 0 {
|
||||
log.Debug("No post-update command supplied. Skipping")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Executing post-update command.")
|
||||
if err := client.ExecuteCommand(newContainerID, command); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"net/smtp"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
|
|
@ -113,7 +114,7 @@ func (e *emailTypeNotifier) sendEntries(entries []*log.Entry) {
|
|||
if e.User != "" {
|
||||
auth = smtp.PlainAuth("", e.User, e.Password, e.Server)
|
||||
}
|
||||
err := SendMail(e.Server+":"+strconv.Itoa(e.Port), e.tlsSkipVerify, auth, e.From, []string{e.To}, msg)
|
||||
err := SendMail(e.Server+":"+strconv.Itoa(e.Port), e.tlsSkipVerify, auth, e.From, strings.Split(e.To, ","), msg)
|
||||
if err != nil {
|
||||
// Use fmt so it doesn't trigger another email.
|
||||
fmt.Println("Failed to send notification email: ", err)
|
||||
|
|
|
|||
33
pkg/registry/registry.go
Normal file
33
pkg/registry/registry.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// GetPullOptions creates a struct with all options needed for pulling images from a registry
|
||||
func GetPullOptions(imageName string) (types.ImagePullOptions, error) {
|
||||
auth, err := EncodedAuth(imageName)
|
||||
log.Debugf("Got image name: %s", imageName)
|
||||
if err != nil {
|
||||
return types.ImagePullOptions{}, err
|
||||
}
|
||||
|
||||
log.Debugf("Got auth value: %s", auth)
|
||||
if auth == "" {
|
||||
return types.ImagePullOptions{}, nil
|
||||
}
|
||||
|
||||
return types.ImagePullOptions{
|
||||
RegistryAuth: auth,
|
||||
PrivilegeFunc: DefaultAuthHandler,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DefaultAuthHandler will be invoked if an AuthConfig is rejected
|
||||
// It could be used to return a new value for the "X-Registry-Auth" authentication header,
|
||||
// but there's no point trying again with the same value as used in AuthConfig
|
||||
func DefaultAuthHandler() (string, error) {
|
||||
log.Debug("Authentication request was rejected. Trying again without authentication")
|
||||
return "", nil
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package container
|
||||
package registry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
|
@ -97,11 +97,3 @@ func CredentialsStore(configFile configfile.ConfigFile) credentials.Store {
|
|||
func EncodeAuth(auth types.AuthConfig) (string, error) {
|
||||
return command.EncodeAuthToBase64(auth)
|
||||
}
|
||||
|
||||
// DefaultAuthHandler will be invoked if an AuthConfig is rejected
|
||||
// It could be used to return a new value for the "X-Registry-Auth" authentication header,
|
||||
// but there's no point trying again with the same value as used in AuthConfig
|
||||
func DefaultAuthHandler() (string, error) {
|
||||
log.Debug("Authentication request was rejected. Trying again without authentication")
|
||||
return "", nil
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package container
|
||||
package registry
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
package container
|
||||
package sorter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containrrr/watchtower/pkg/container"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ByCreated allows a list of Container structs to be sorted by the container's
|
||||
// created date.
|
||||
type ByCreated []Container
|
||||
type ByCreated []container.Container
|
||||
|
||||
func (c ByCreated) Len() int { return len(c) }
|
||||
func (c ByCreated) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||
|
|
@ -15,12 +16,12 @@ func (c ByCreated) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
|||
// Less will compare two elements (identified by index) in the Container
|
||||
// list by created-date.
|
||||
func (c ByCreated) Less(i, j int) bool {
|
||||
t1, err := time.Parse(time.RFC3339Nano, c[i].containerInfo.Created)
|
||||
t1, err := time.Parse(time.RFC3339Nano, c[i].ContainerInfo().Created)
|
||||
if err != nil {
|
||||
t1 = time.Now()
|
||||
}
|
||||
|
||||
t2, _ := time.Parse(time.RFC3339Nano, c[j].containerInfo.Created)
|
||||
t2, _ := time.Parse(time.RFC3339Nano, c[j].ContainerInfo().Created)
|
||||
if err != nil {
|
||||
t1 = time.Now()
|
||||
}
|
||||
|
|
@ -33,18 +34,18 @@ func (c ByCreated) Less(i, j int) bool {
|
|||
// the front of the list while containers with links will be sorted after all
|
||||
// of their dependencies. This sort order ensures that linked containers can
|
||||
// be started in the correct order.
|
||||
func SortByDependencies(containers []Container) ([]Container, error) {
|
||||
func SortByDependencies(containers []container.Container) ([]container.Container, error) {
|
||||
sorter := dependencySorter{}
|
||||
return sorter.Sort(containers)
|
||||
}
|
||||
|
||||
type dependencySorter struct {
|
||||
unvisited []Container
|
||||
unvisited []container.Container
|
||||
marked map[string]bool
|
||||
sorted []Container
|
||||
sorted []container.Container
|
||||
}
|
||||
|
||||
func (ds *dependencySorter) Sort(containers []Container) ([]Container, error) {
|
||||
func (ds *dependencySorter) Sort(containers []container.Container) ([]container.Container, error) {
|
||||
ds.unvisited = containers
|
||||
ds.marked = map[string]bool{}
|
||||
|
||||
|
|
@ -57,10 +58,10 @@ func (ds *dependencySorter) Sort(containers []Container) ([]Container, error) {
|
|||
return ds.sorted, nil
|
||||
}
|
||||
|
||||
func (ds *dependencySorter) visit(c Container) error {
|
||||
func (ds *dependencySorter) visit(c container.Container) error {
|
||||
|
||||
if _, ok := ds.marked[c.Name()]; ok {
|
||||
return fmt.Errorf("Circular reference to %s", c.Name())
|
||||
return fmt.Errorf("circular reference to %s", c.Name())
|
||||
}
|
||||
|
||||
// Mark any visited node so that circular references can be detected
|
||||
|
|
@ -83,7 +84,7 @@ func (ds *dependencySorter) visit(c Container) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (ds *dependencySorter) findUnvisited(name string) *Container {
|
||||
func (ds *dependencySorter) findUnvisited(name string) *container.Container {
|
||||
for _, c := range ds.unvisited {
|
||||
if c.Name() == name {
|
||||
return &c
|
||||
|
|
@ -93,7 +94,7 @@ func (ds *dependencySorter) findUnvisited(name string) *Container {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (ds *dependencySorter) removeUnvisited(c Container) {
|
||||
func (ds *dependencySorter) removeUnvisited(c container.Container) {
|
||||
var idx int
|
||||
for i := range ds.unvisited {
|
||||
if ds.unvisited[i].Name() == c.Name() {
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
package actions
|
||||
package types
|
||||
|
||||
import (
|
||||
t "github.com/containrrr/watchtower/pkg/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
// UpdateParams contains all different options available to alter the behavior of the Update func
|
||||
type UpdateParams struct {
|
||||
Filter t.Filter
|
||||
Filter Filter
|
||||
Cleanup bool
|
||||
NoRestart bool
|
||||
Timeout time.Duration
|
||||
Loading…
Add table
Add a link
Reference in a new issue