Compare commits

...

224 Commits

Author SHA1 Message Date
stakater-user
732d35e45f Bump Version to v0.0.62 2020-07-17 09:17:35 +00:00
Ahmed Waleed Malik
dcedaa2cfe Merge pull request #147 from alexconlin/patch-1
Remove empty fields from kustomize deployment
2020-07-17 14:07:01 +05:00
Alex Conlin-Oakley
8d77121c3b only include env and args in container when needed 2020-07-15 17:42:08 +01:00
Alex Conlin
013cd92219 Merge branch 'master' into patch-1 2020-07-10 17:24:33 +01:00
stakater-user
39b5be37af Bump Version to v0.0.61 2020-07-10 15:54:41 +00:00
kahootali
86c2ed265d Add non-root security context 2020-07-10 20:40:48 +05:00
LucasBoisserie
87130f06bc Run as Non Root (#149) 2020-07-10 17:34:49 +02:00
Ali Kahoot
17f702f510 Merge pull request #148 from TBBle/patch-1
Typo fix "resatart"
2020-07-10 20:27:40 +05:00
Paul "TBBle" Hampson
16f3055e10 Typo fix "resatart" 2020-07-10 11:34:47 +10:00
Alex Conlin
4800af8e28 Remove empty fields from deployment manifest 2020-07-08 11:22:43 +01:00
Alex Conlin
db79c65334 Remove empty fields from kustomize deployment
Fixes #115
2020-07-07 22:52:53 +01:00
stakater-user
d2223f313f Bump Version to v0.0.60 2020-06-23 07:15:27 +00:00
Ahmed Waleed Malik
c9dabc3a14 Merge pull request #142 from vladlosev/feat-track-secrets-configmaps-by-annotation
Adds support for auto-reloading secrets and configmaps by annotation.
2020-06-23 12:05:22 +05:00
Vlad Losev
e61f9a6bdb Adds note on incompatibility with 'reloader.stakater.com/auto'. 2020-06-21 14:15:58 -07:00
Vlad Losev
6bcec06052 Fixes missing import. 2020-06-09 19:45:12 -07:00
Vlad Losev
0988e8947f Removes unused import. 2020-06-09 19:18:12 -07:00
Vlad Losev
ff27cc0f51 Simplifies test. 2020-06-09 19:17:19 -07:00
Vlad Losev
be7d454504 Fixes test using auto annotations. 2020-06-09 19:16:04 -07:00
Vlad Losev
3131116ed6 Re-adds sleep statements. 2020-06-09 19:16:04 -07:00
Vlad Losev
965cacf1ba Updates documentation. 2020-06-09 19:16:04 -07:00
Vlad Losev
e81b49d81b Renames search annotation. 2020-06-09 19:16:03 -07:00
Vlad Losev
17f8b81110 Simplifies annotations for searching secrets for reload. 2020-06-09 19:16:03 -07:00
Vlad Losev
5980c91560 Abstracts out configmap and deployment creation. 2020-06-09 19:16:01 -07:00
Vlad Losev
fda733ea5a Adds support for auto-reloading secrets and configmaps by annotation. 2020-06-09 19:14:14 -07:00
stakater-user
732cd5b53a Bump Version to v0.0.59 2020-06-09 16:50:55 +00:00
stakater-user
aae0c5c443 Merge pull request #141 from cucxabong/support-projected-volume
Support projected volume
2020-06-09 20:16:24 +05:00
Quan Hoang
d4223311de Support projected volume 2020-06-02 23:36:08 +07:00
stakater-user
29173c7364 Bump Version to v0.0.58 2020-03-30 15:12:34 +00:00
inductor
7767809a38 Refactor Dockerfile (#133)
* refactor dockerfile

* update go version on Dockerfile
2020-03-30 16:52:33 +02:00
stakater-user
f0d6a9e646 Bump Version to v0.0.57 2020-03-18 09:26:04 +00:00
Usama Ahmad
d1538dbeec Merge pull request #131 from stakater/fix-pipeline
Update pipeline library and pipeline tools version
2020-03-18 14:15:55 +05:00
Waleed Malik
8470962383 Update pipeline library and pipeline tools version 2020-03-18 14:02:05 +05:00
Ali Kahoot
139bc1ca38 Merge pull request #128 from katainaka0503/add-prometheus-endpoint
Implement prometheus endpoint
2020-03-17 20:43:03 +05:00
kahootali
6d9f89a452 add service manifest 2020-03-17 15:27:47 +05:00
Ali Kahoot
5ba914d6bb Fix documentation 2020-03-17 15:10:42 +05:00
katainaka0503
9a5094a4ed Add document of prometheus endpoint 2020-03-01 21:56:05 +09:00
katainaka0503
3fe7ad04e9 Implement prometheus endpoint 2020-03-01 21:56:02 +09:00
stakater-user
bf6a247f54 Bump Version to v0.0.56 2020-03-01 12:47:59 +00:00
stakater-user
8203cc3c11 Bump Version to v0.0.55 2020-03-01 12:37:09 +00:00
stakater-user
f287d84b6a Bump Version to v0.0.54 2020-03-01 12:26:27 +00:00
katainaka
205d36512c Remove redundant namePrefix from kustomization.yaml sample (#126) 2020-03-01 13:16:35 +01:00
stakater-user
0b39353c12 Bump Version to v0.0.53 2020-02-28 12:53:28 +00:00
Ali Kahoot
97a5616e60 Merge pull request #125 from stakater/update-library-version
update library version and toolsImage
2020-02-28 17:43:19 +05:00
usamaahmadkhan
b274ac0947 update library version and toolsImage 2020-02-28 17:28:26 +05:00
stakater-user
ed29d1d18c Bump Version to v0.0.52 2020-02-14 06:45:57 +00:00
aure-olli
2384d65953 feat: allow annotations in the pod template too (#123)
Several public charts only allow to edit the annotations of the pod template, not the deployment. Annotations will also be checked in the pod template if not present in the deployment.

fix: #122

Signed-off-by: Aurélien Lambert <aure@olli-ai.com>
2020-02-14 07:32:31 +01:00
stakater-user
7b19601423 Bump Version to v0.0.51 2020-01-13 13:33:00 +00:00
Usama Ahmad
76bf43cb13 Merge pull request #121 from elblivion/json-logging
JSON logging
2020-01-13 18:22:46 +05:00
kahootali
1b7bb3bead add support for logFormat argument in deployment 2020-01-13 17:10:08 +05:00
kahootali
c844f12f73 add logFormat default value 2020-01-13 17:09:53 +05:00
kahootali
5ac2164a1c add logFormat parameter in Readme 2020-01-13 17:09:25 +05:00
Anthony Stanton
c9b89c37c1 Update README 2020-01-03 13:44:01 +01:00
Anthony Stanton
55bc4c3e22 JSON logging 2020-01-02 22:10:41 +01:00
stakater-user
77c7d63296 Bump Version to v0.0.50 2019-12-31 05:49:32 +00:00
Irtiza Ali
2ae4753efb Merge pull request #119 from rjshrjndrn/patch-1
Include annotations in templating.
2019-12-31 10:39:13 +05:00
Rajesh Rajendran
68d0349793 Include annotations in templating.
for example, If I have istio enabled in a namespace, and I want to deploy reloader in that, It doesn't make sense to include envoy there. So there should be an option to add `sidecar.istio.io/inject: "false"` annotation.
2019-12-31 10:52:19 +05:30
stakater-user
ded923b12a Bump Version to v0.0.49 2019-10-22 12:21:42 +00:00
Waseem Hassan Shahid
0726999bf9 Merge pull request #109 from alexandrsemak/patch-1
fix value for helm template
2019-10-22 14:11:26 +02:00
Alexandr Semak
f89c321a50 fix value for helm template 2019-10-22 06:43:19 -04:00
stakater-user
225427cec1 Bump Version to v0.0.48 2019-10-21 07:12:07 +00:00
Waseem Hassan Shahid
be86e8417f Update .goreleaser.yml 2019-10-21 09:01:55 +02:00
stakater-user
bf961c0456 Bump Version to v0.0.47 2019-10-21 07:01:11 +00:00
Waseem Hassan Shahid
3248ca9578 Change name template of archives 2019-10-21 08:50:39 +02:00
stakater-user
d517626033 Bump Version to v0.0.46 2019-10-21 06:39:52 +00:00
Waseem Hassan Shahid
28c9696bdf Update Jenkinsfile 2019-10-21 08:29:14 +02:00
stakater-user
d0baf7a5cc Bump Version to v0.0.45 2019-10-18 11:59:28 +00:00
Waseem Hassan
492fae7b52 Merge pull request #108 from stakater/add-github-token
Add github token to goreleaser
2019-10-18 13:30:31 +02:00
waseem
4999bdbd96 Add github token to goreleaser 2019-10-18 13:29:01 +02:00
stakater-user
fd7d0f9f99 Bump Version to v0.0.44 2019-10-18 11:26:06 +00:00
Waseem Hassan
0359c3040a Merge pull request #107 from stakater/use-goreleaser
Use goreleaser for releasing binaries
2019-10-18 13:11:34 +02:00
waseem
d710c16774 Use stk compatible version file 2019-10-18 12:38:47 +02:00
waseem
e57db0dc56 Remove version file 2019-10-18 12:38:13 +02:00
waseem
e1a6a1ed87 Change library function to use 2019-10-18 12:35:44 +02:00
waseem
f8b3b21bbd Use goreleaser for releasing binaries 2019-10-18 12:34:26 +02:00
stakater-user
b6a333ea73 Bump Version to v0.0.43 2019-10-16 08:08:06 +00:00
Waseem Hassan
efa30662ae Merge pull request #106 from stakater/compatibility-1.16
Make reloader compatible with kubernetes 1.16
2019-10-16 09:57:50 +02:00
waseem
5fff0c9bb7 Add compatibility note 2019-10-16 08:05:03 +02:00
waseem
ec35f653b1 Fix labels 2019-10-16 07:25:02 +02:00
waseem
9229775f11 Make reloader compatible with kubernetes 1.16 2019-10-16 07:03:43 +02:00
stakater-user
e14b0c81b0 Bump Version to v0.0.42 2019-10-15 06:39:28 +00:00
Waseem Hassan
6aa016f6dd Merge pull request #104 from stakater/go-modules
Use Go modules
2019-10-15 08:29:12 +02:00
waseem
02cab487c4 Add missing global field in values template 2019-10-15 08:10:33 +02:00
waseem
4ecdc0acaa Update toolsImage 2019-10-15 08:07:44 +02:00
waseem
4b02478210 Use go mod to download dependencies 2019-10-15 08:03:09 +02:00
waseem
6ec1f9add8 Use go modules 2019-10-15 07:58:12 +02:00
Waseem Hassan
fe3499ee26 Merge pull request #102 from stakater/ignore-namespace-flag
Add support for ignoring namespaces
2019-10-15 07:49:13 +02:00
waseem
aee5d84f45 Add to update method 2019-10-14 14:20:17 +02:00
waseem
a10b2fa747 Add support for ignoring namespaces 2019-10-14 14:14:40 +02:00
Irtiza Ali
6d8a81fa26 Merge pull request #101 from marcostvz/reloader-sc-ips
Sync with upstream helm/charts/stable/reloader
2019-10-14 10:13:26 +05:00
Marcos Estevez
734b33ba55 Sync with upstream helm/charts/stable/reloader
Signed-off-by: Marcos Estevez <marcos.stvz@gmail.com>
2019-10-10 14:29:51 +02:00
Irtiza Ali
5265c14760 Merge pull request #100 from stakater/fix-vanilla-manifest-usage-guideline
fix-vanilla-manifest-usage-guideline
2019-10-09 13:01:13 +05:00
irti
5fb1a8b5ef [fix-vanilla-manifest-usage-guideline] update the vanilla manifest usage guidelines 2019-10-09 12:17:32 +05:00
stakater-user
29f4c66274 Bump Version to v0.0.41 2019-10-09 06:55:17 +00:00
Ali Kahoot
82b94d8b57 Merge pull request #98 from stakater/fix-direct-installation-issue
[fix-direct-installation-issue] update Jenkinsfile
2019-10-09 11:44:37 +05:00
irti
984794850b [fix-direct-installation-issue] remove the chartRepositoryURL arg from the goBuildAndRelease method 2019-10-09 11:27:32 +05:00
Ali Kahoot
de0d588406 Merge pull request #99 from stakater/remove-chartmuseum-from-pipeline
remove chartmuseum from pipeline
2019-10-07 12:35:08 +05:00
Usama Ahmad
5665a5c424 remove chartmuseum from pipeline 2019-10-07 12:17:43 +05:00
irti
4598bf0f7d [fix-direct-installation-issue] update Jenkinsfile 2019-10-01 20:14:16 +05:00
irti
c8ab70f80d [fix-direct-installation-issue] update Jenkinsfile 2019-10-01 15:37:35 +05:00
irti
2d720809d9 [fix-direct-installation-issue] change the pipeline library version 2019-09-23 12:15:39 +05:00
irti
2c2beb91c7 [fix-direct-installation-issue] update Jenkinsfile 2019-09-20 11:27:30 +05:00
Ali Kahoot
d3f2eb794f Merge pull request #93 from stakater/add-info-for-manifest-issue
add-info-for-manifest-issue
2019-08-28 19:08:54 +05:00
irti
02ddd80280 [add-info-for-manifest-issue] update the README.md by adding the info to replace the RELEASE-NAME with a proper value 2019-08-28 18:57:25 +05:00
stakater-user
503776c2a5 Bump Version to v0.0.40 2019-08-27 07:51:00 +00:00
Ali Kahoot
4c7afbcb71 Merge pull request #90 from stakater/update-manifests
[update-manifests] update values manifest
2019-08-27 12:40:17 +05:00
irti
b11514ec13 [update-manifests] update values.yaml.tmlp manifest 2019-08-27 12:39:03 +05:00
irti
ef7d98f5e3 [update-manifests] update values manifest 2019-08-27 11:36:59 +05:00
Ali Kahoot
a336304fb3 Merge pull request #85 from stakater/fix-issue-81
[fix-issue-81] remove reloader binary file
2019-08-21 12:08:19 +05:00
irti
65365e5fef [fix-issue-81] remove reloader binary file 2019-08-21 11:39:21 +05:00
stakater-user
7c2121b7c9 Bump Version to v0.0.39 2019-08-20 09:59:32 +00:00
Ali Kahoot
008f4b0fd2 Merge pull request #80 from stakater/fix-issue-79
fix-issue-79
2019-08-20 14:47:41 +05:00
irti
0bf2fc66cc [fix-issue-79] add reloader-name template in _helpers.tpl 2019-08-20 14:20:40 +05:00
irti
d599340549 [fix-issue-79] remove reloader-name template and replace it with reloader-fullname 2019-08-20 10:28:35 +05:00
irti
83a711885c [fix-issue-79] add nodeSelector, affinity and tolerations in deployment manifest 2019-08-13 18:14:51 +05:00
irti
0ddfe8406d [fix-issue-79] fix for default value issue for service account 2019-08-13 17:58:53 +05:00
stakater-user
036882b588 Bump Version to v0.0.38 2019-08-05 08:09:38 +00:00
Irtiza Ali
63619e360c Merge pull request #78 from stakater/fix-openshift-rbac
Add openshift flag to explicitly add rbac for openshift if desired
2019-08-05 12:58:55 +05:00
waseem
6d54f9faca Added brackets to isOpenshift 2019-08-05 09:45:04 +02:00
waseem
18254666a6 Add openshift flag to explicitly add rbac for openshift 2019-08-05 09:20:37 +02:00
Ali Kahoot
b0dcb4c5e2 Merge pull request #76 from stakater/update-readme
update-readme-by-adding-guideline-to-ignore-resource
2019-07-11 11:19:25 +05:00
irti
cd4a4fb324 [update-readme] update README.md file by fixing issue in table template 2019-07-10 11:16:09 +05:00
irti
7ae3a4259e [update-readme] update README.md file by adding not about ignore parameters 2019-07-10 11:14:30 +05:00
irti
e82926a9f6 [update-readme] update README.md file by adding the guideline on how ignore some resource configMaps and secrets 2019-07-10 10:35:20 +05:00
stakater-user
e462f7ab26 Bump Version to v0.0.37 2019-07-08 10:21:39 +00:00
Waseem Hassan
da4ffc9432 Merge pull request #74 from stakater/deploymentconfigs
Add support for DeploymentConfigs for openshift
2019-07-08 12:10:45 +02:00
waseem
cc65a1c039 Fix conflicts 2019-07-08 10:38:46 +02:00
waseem
8c1a9317ee Fix conflicts 2019-07-08 10:38:19 +02:00
Waseem Hassan
33d1918d71 Merge branch 'master' into deploymentconfigs 2019-07-08 10:35:23 +02:00
stakater-user
5fc34e885e Bump Version to v0.0.36 2019-07-08 08:28:55 +00:00
Ali Kahoot
acc61d504f Merge pull request #75 from stakater/fix-deployment-template
fix-deployment-template
2019-07-08 13:05:40 +05:00
irti
cf9c0fc685 [fix-deployment-template] fix deployment template. Custom annotations check causing the ignore-resources field addition to fail 2019-07-08 12:32:19 +05:00
waseem
4822dbae86 Remove GetClient from testutil 2019-07-05 12:30:11 +02:00
waseem
16d75d1d47 Fix merge conflicts 2019-07-05 12:24:46 +02:00
waseem
878bc5c442 Refactor Openshift detection 2019-07-05 12:23:14 +02:00
stakater-user
e7ccc40035 Bump Version to v0.0.35 2019-07-05 05:38:24 +00:00
Irtiza Ali
0197dec568 Merge pull request #72 from henryaj/master
Optionally disable secret checking
2019-07-04 22:40:36 +05:00
hstanley
795de2399b Fail if user tries to ignore all resource types 2019-07-04 10:21:19 +01:00
hstanley
a69674ba4c Remove errant 'resources-to-watch' flags 2019-07-04 10:03:14 +01:00
waseem
ff5f28ba00 Add comments where needed 2019-07-04 11:00:52 +02:00
waseem
df777332a9 Lint go 2019-07-04 10:56:17 +02:00
waseem
daca09e65e Add deploymentconfigs to clusterrole 2019-07-04 10:53:19 +02:00
waseem
50a908a59f Update minor version 2019-07-04 10:42:30 +02:00
waseem
121a550da5 Update readme 2019-07-04 10:42:06 +02:00
waseem
9f3c8379a6 Add IsOpenshift flag 2019-07-04 10:32:17 +02:00
waseem
9b48d320be Add check for openshift 2019-07-04 10:25:22 +02:00
waseem
a8edefcdde Fix install command 2019-07-04 10:21:35 +02:00
waseem
1689a9560b Add deploymentconfigs in rbac if platform is openshift 2019-07-04 10:16:48 +02:00
waseem
4f8377de15 Fix glide command in docker build 2019-07-04 10:10:26 +02:00
waseem
765ddbdf43 Update go version 2019-07-04 09:59:35 +02:00
waseem
181477de05 Update glide with openshift packages 2019-07-04 09:59:20 +02:00
waseem
6d8c0cf6cb Add controller tests and fixes 2019-07-04 09:58:58 +02:00
waseem
2dc7d20a37 Fix upgrade test cases 2019-07-04 09:58:49 +02:00
waseem
9cd5b87dab Add openshift apps client 2019-07-04 09:58:39 +02:00
waseem
20d88e0668 Fix test cases 2019-07-04 09:58:33 +02:00
waseem
de77785d4f Add support for DeploymentConfigs 2019-07-04 09:58:26 +02:00
waseem
bf6cb73fd7 Merge branch 'master' of github.com:stakater/Reloader into deploymentconfigs 2019-07-04 08:32:20 +02:00
stakater-user
b3d3c3704a Bump Version to v0.0.34 2019-07-04 06:29:52 +00:00
Ali Kahoot
58514e8610 Merge pull request #73 from stakater/fix-dnsPolicy-issue
fix-dnsPolicy-issue
2019-07-04 11:06:41 +05:00
irti
a26f7fc4ad [fix-dnsPolicy-issue] bump package version in glide.yaml file. k8s.io/api version 1.8.0 to 1.10.0 and client go version 5.0.0 to 6.0.0 2019-07-04 10:12:55 +05:00
waseem
e06394c940 Reduce wait times and fix indentations 2019-07-03 22:17:36 +02:00
waseem
362ea70e26 Fix test cases 2019-07-03 22:14:36 +02:00
hstanley
3e6c4a3f60 Switch from list of resources to monitor to list of resources to ignore 2019-07-03 16:01:15 +01:00
hstanley
8cf105726f Update helm charts (deployments and RBAC) 2019-07-03 10:56:09 +01:00
hstanley
361bea4373 move List to util.go 2019-07-03 10:32:33 +01:00
hstanley
59fd71d15f Add 'resources-to-watch' flag 2019-07-02 14:09:27 +01:00
hstanley
6c6776f2b4 Optionally disable checking k8s Secrets 2019-07-02 11:51:14 +01:00
stakater-user
8b824ef26a Bump Version to v0.0.33 2019-07-01 12:09:23 +00:00
Irtiza Ali
5fd170a7ca Merge pull request #69 from chrisns/kustomize
add Kustomize deployment code docs
2019-07-01 16:44:50 +05:00
Chris Nesbitt-Smith
69487f6caf update readme for kustomize 2019-06-27 14:34:07 +01:00
Chris Nesbitt-Smith
401a94bd36 add kustomization.yaml 2019-06-27 10:59:02 +01:00
stakater-user
bf12cbec15 Bump Version to v0.0.32 2019-06-27 08:30:31 +00:00
Irtiza Ali
fdc223a4a6 Merge pull request #68 from DevotedHealth/affinity_tolerations
Permit passing resources, tolerations, affinity to Helm chart
2019-06-27 13:07:34 +05:00
Steve Huff
dcbc0e0de0 Permit passing resources, tolerations, affinity to Helm chart
These values are all empty by default.
2019-06-26 18:44:39 +00:00
stakater-user
aff377718c Bump Version to v0.0.31 2019-06-25 09:27:27 +00:00
Ali Kahoot
112e8ba89d Merge pull request #67 from stakater/add-node-selector-support
add-node-selector-support
2019-06-25 14:04:40 +05:00
irti
c2e6231a46 [add-node-selector-support] revert README.md doc change 2019-06-20 12:21:35 +05:00
irti
51b42dc098 [add-node-selector-support] add char in README.md 2019-06-20 12:18:31 +05:00
irti
43200e127a [add-node-selector-support] add nodeSelector param in values.yaml file 2019-06-20 12:03:37 +05:00
irti
6db5106f85 [add-node-selector-support] fix issue 2019-06-20 11:55:21 +05:00
irti
703c0ea56e [add-node-selector-support] add nodeSelector support 2019-06-20 11:36:12 +05:00
stakater-user
21563abc07 Bump Version to v0.0.30 2019-06-11 07:36:19 +00:00
Ali Kahoot
ce96eb3810 Merge pull request #65 from blurpy/filesys_and_role
Fix issue with readOnlyRootFilesystem and statefulsets permissions
2019-06-11 12:13:13 +05:00
Christian Ihle
b5c8ee2ab9 Add optional support for readOnlyRootFilesystem 2019-06-06 11:59:42 +02:00
Christian Ihle
c27bb3929b Split permissions for apps and extensions apigroups since statefulsets does not have extensions 2019-06-06 11:54:14 +02:00
stakater-user
67913c9985 Bump Version to v0.0.29 2019-05-23 10:04:32 +00:00
Ali Kahoot
9dac1a30b6 Merge pull request #64 from cko/alpine_update
Update alpine container base image to 3.9
2019-05-23 14:41:30 +05:00
Christine Koppelt
ac7f9d09cc update alpine container base image to 3.9 2019-05-23 10:55:06 +02:00
stakater-user
d8ae3c76da Bump Version to v0.0.28 2019-05-08 10:22:39 +00:00
Ali Kahoot
3f115618cc Merge pull request #62 from stakater/issue-61
Initial implementation of fix for issue 61
2019-05-08 14:59:43 +05:00
faizanahmad055
06aa382910 Initial implementation of fix for issue 61
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-05-07 10:51:58 +02:00
stakater-user
3b69599c77 Bump Version to v0.0.27 2019-04-25 10:18:02 +00:00
Ali Kahoot
125e7536af Merge pull request #60 from stakater/fix-config-change-logs-issue
fix-config-change-logs-issue
2019-04-25 14:55:07 +05:00
irti
66f9b07817 [fix-config-change-logs-issue] fixed log statement placement 2019-04-25 14:19:52 +05:00
irti
40aa9955cd [fix-config-change-logs-issue] fixed the issue in create.go file 2019-04-25 14:16:42 +05:00
irti
bfff7104aa [fix-config-change-logs-issue] logs issue fixed 2019-04-25 14:11:31 +05:00
Ali Kahoot
c0acfd0503 Merge pull request #58 from stakater/sealed-secret-doc
Sealed secret doc
2019-03-18 20:18:11 +05:00
faizanahmad055
379b6c0131 Add doc for how to use sealed secrets with reloader
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-03-18 16:14:47 +01:00
faizanahmad055
3bf427e985 Add doc for how to use sealed secrets with reloader
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-03-18 16:13:55 +01:00
stakater-user
2b6e5455dc Bump Version to v0.0.26 2019-02-20 10:57:07 +00:00
Ali Kahoot
9bc8d6b67d Merge pull request #56 from stakater/add-initContainer-support
Initial implementation for init container support
2019-02-20 15:32:44 +05:00
faizanahmad055
0c340fcb48 Fix same name configmap and secret conflict
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-02-18 12:09:53 +01:00
faizanahmad055
889b16718a Add test cases
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-02-18 10:20:52 +01:00
faizanahmad055
512cbd8c85 Fix incorrect container update
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-02-16 16:52:12 +01:00
faizanahmad055
39944497f3 Implement golang-ci comment
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-02-16 15:50:47 +01:00
faizanahmad055
6fb1266637 Initial implementation for init container support
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-02-16 15:43:56 +01:00
stakater-user
724cda887e Bump Version to v0.0.25 2019-02-12 08:28:39 +00:00
Muhammad Ahsan
d29f3716b2 Merge pull request #53 from stakater/fix-helper-func
append reloader- to serviceAccountName
2019-02-12 13:03:43 +05:00
kahootali
2131f0ebf3 append reloader- to serviceAccountName 2019-02-12 12:20:28 +05:00
stakater-user
0f052162a2 Bump Version to v0.0.24 2019-02-08 10:55:07 +00:00
Faizan Ahmad
02c6de97c8 Merge pull request #50 from ParticleDecay/feat/annotation-flag
Parameterize all annotations
2019-02-08 11:31:38 +01:00
kahootali
16bce16f81 add custom annotation 2019-02-08 15:05:18 +05:00
Joey Espinosa
33443ccb29 feat: add cli flags to helm chart 2019-02-06 12:46:17 -05:00
Joey Espinosa
75b00733bf feat: parameterize all annotations 2019-02-04 12:33:53 -05:00
stakater-user
d2335f8ffd Bump Version to v0.0.23 2019-02-01 12:21:59 +00:00
Ali Kahoot
87f3a32f68 Merge pull request #49 from stakater/fix-48
Add support for envFrom for autoUpdate
2019-02-01 16:57:46 +05:00
faizanahmad055
95bd5e497f Use single container loop for envs
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-02-01 12:06:18 +01:00
faizanahmad055
333957d82a Implemented golang CI comment
Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-01-31 16:32:47 +01:00
faizanahmad055
75f67ffa6e Add support for envFrom for autoUpdate
Signed-off-by: faizanahmad055 <faizanahmad@217-212-164-26.customer.telia.com>
2019-01-31 16:03:53 +01:00
Ziming Miao
0558fc3723 fix typo (#47) 2019-01-30 10:38:23 +05:00
stakater-user
b637e33d9d Bump Version to v0.0.22 2019-01-25 13:24:41 +00:00
Faizan Ahmad
130741480e Auto update referenced resource (#45)
* Add implementation for create event

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Add sleep in testcase

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Fix test case data

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Remove unnecessary dashes from chart

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Fix new env var creation issue

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Optimize upgrade code

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Update logs

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Initial implementation to perform rolling upgrades by auto referencing the resources

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Fix nil pointer exception

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Fix test cases

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Add test cases

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Update test case verify method

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Add missing name for envs

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Update annotation name

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Update readme

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Update readme

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Implement Golang CI comment

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>

* Implement Golang CI comment

Signed-off-by: faizanahmad055 <faizan.ahmad55@outlook.com>
2019-01-25 14:00:21 +01:00
stakater-user
cd19d739ab Bump Version to v0.0.21 2019-01-21 08:54:49 +00:00
Ali Kahoot
f15ec9b4d4 Merge pull request #44 from stakater/update-jenkins-file
updates pipeline library version
2019-01-21 13:34:39 +05:00
ahsan-storm
013fcdc052 updates pipeline library version 2019-01-21 13:10:31 +05:00
59 changed files with 4178 additions and 1510 deletions

1
.VERSION Normal file
View File

@@ -0,0 +1 @@
version: v0.0.62

1
.dockerignore Normal file
View File

@@ -0,0 +1 @@
vendor

3
.gitignore vendored
View File

@@ -7,4 +7,5 @@ out/
_gopath/
.DS_Store
.vscode
vendor
vendor
dist

26
.goreleaser.yml Normal file
View File

@@ -0,0 +1,26 @@
builds:
- env:
- CGO_ENABLED=0
goos:
- windows
- darwin
- linux
goarch:
- 386
- amd64
- arm
- arm64
archives:
- name_template: "{{ .ProjectName }}_v{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
snapshot:
name_template: "{{ .Tag }}-next"
checksum:
name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
env_files:
github_token: /home/jenkins/.apitoken/hub

View File

@@ -1 +0,0 @@
0.0.20

8
Jenkinsfile vendored
View File

@@ -1,10 +1,8 @@
#!/usr/bin/groovy
@Library('github.com/stakater/fabric8-pipeline-library@v2.10.4')
@Library('github.com/stakater/stakater-pipeline-library@v2.16.24') _
def dummy
goBuildAndRelease {
chartRepositoryURL = 'https://chartmuseum.release.stakater.com'
goBuildViaGoReleaser {
publicChartRepositoryURL = 'https://stakater.github.io/stakater-charts'
publicChartGitURL = 'git@github.com:stakater/stakater-charts.git'
toolsImage = 'stakater/pipeline-tools:v2.0.18'
}

View File

@@ -13,14 +13,13 @@ VERSION=$(shell cat .version)
BUILD=
GOCMD = go
GLIDECMD = glide
GOFLAGS ?= $(GOFLAGS:)
LDFLAGS =
default: build test
install:
"$(GLIDECMD)" install
"$(GOCMD)" mod download
build:
"$(GOCMD)" build ${GOFLAGS} ${LDFLAGS} -o "${BINARY}"

157
README.md
View File

@@ -13,16 +13,73 @@
## Problem
We would like to watch if some change happens in `ConfigMap` and/or `Secret`; then perform a rolling upgrade on relevant `Deployment`, `Deamonset` and `Statefulset`
We would like to watch if some change happens in `ConfigMap` and/or `Secret`; then perform a rolling upgrade on relevant `DeploymentConfig`, `Deployment`, `Daemonset` and `Statefulset`
## Solution
Reloader can watch changes in `ConfigMap` and `Secret` and do rolling upgrades on Pods with their associated `Deployments`, `Deamonsets` and `Statefulsets`.
Reloader can watch changes in `ConfigMap` and `Secret` and do rolling upgrades on Pods with their associated `DeploymentConfigs`, `Deployments`, `Daemonsets` and `Statefulsets`.
## Compatibility
Reloader is compatible with kubernetes >= 1.9
## How to use Reloader
For a `Deployment` called `foo` have a `ConfigMap` called `foo-configmap` or `Secret` called `foo-secret` or both. Then add your annotation (by default `reloader.stakater.com/auto`) to main metadata of your `Deployment`
```yaml
kind: Deployment
metadata:
annotations:
reloader.stakater.com/auto: "true"
spec:
template: metadata:
```
This will discover deployments/daemonsets/statefulset automatically where `foo-configmap` or `foo-secret` is being used either via environment variable or from volume mount. And it will perform rolling upgrade on related pods when `foo-configmap` or `foo-secret`are updated.
You can restrict this discovery to only `ConfigMap` or `Secret` objects that
are tagged with a special annotation. To take advantage of that, annotate
your deployment/daemonset/statefulset like this:
```yaml
kind: Deployment
metadata:
annotations:
reloader.stakater.com/search: "true"
spec:
template:
```
and Reloader will trigger the rolling upgrade upon modification of any
`ConfigMap` or `Secret` annotated like this:
```yaml
kind: ConfigMap
metadata:
annotations:
reloader.stakater.com/match: "true"
data:
key: value
```
provided the secret/configmap is being used in an environment variable or a
volume mount.
Please note that `reloader.stakater.com/search` and
`reloader.stakater.com/auto` do not work together. If you have the
`reloader.stakater.com/auto: "true"` annotation on your deployment, then it
will always restart upon a change in configmaps or secrets it uses, regardless
of whether they have the `reloader.stakater.com/match: "true"` annotation or
not.
We can also specify a specific configmap or secret which would trigger rolling upgrade only upon change in our specified configmap or secret, this way, it will not trigger rolling upgrade upon changes in all configmaps or secrets used in a deployment, daemonset or statefulset.
To do this either set the auto annotation to `"false"` (`reloader.stakater.com/auto: "false"`) or remove it altogether, and use annotations mentioned [here](#Configmap) or [here](#Secret)
### Configmap
To perform rolling upgrade when change happens only on specific configmaps use below annotation.
For a `Deployment` called `foo` have a `ConfigMap` called `foo-configmap`. Then add this annotation to main metadata of your `Deployment`
```yaml
@@ -31,8 +88,7 @@ metadata:
annotations:
configmap.reloader.stakater.com/reload: "foo-configmap"
spec:
template:
metadata:
template: metadata:
```
Use comma separated list to define multiple configmaps.
@@ -43,13 +99,14 @@ metadata:
annotations:
configmap.reloader.stakater.com/reload: "foo-configmap,bar-configmap,baz-configmap"
spec:
template:
metadata:
template: metadata:
```
### Secret
For a `Deployment` called `foo` have a `Secret` called `foo-secret`. Then add this annotation to main metadata of your `Deployment`
To perform rolling upgrade when change happens only on specific secrets use below annotation.
For a `Deployment` called `foo` have a `Secret` called `foo-secret`. Then add this annotation to main metadata of your `Deployment`
```yaml
kind: Deployment
@@ -57,8 +114,7 @@ metadata:
annotations:
secret.reloader.stakater.com/reload: "foo-secret"
spec:
template:
metadata:
template: metadata:
```
Use comma separated list to define multiple secrets.
@@ -69,17 +125,30 @@ metadata:
annotations:
secret.reloader.stakater.com/reload: "foo-secret,bar-secret,baz-secret"
spec:
template:
metadata:
template: metadata:
```
### NOTES
- Reloader also supports [sealed-secrets](https://github.com/bitnami-labs/sealed-secrets). [Here](docs/Reloader-with-Sealed-Secrets.md) are the steps to use sealed-secrets with reloader.
- `reloader.stakater.com/auto: "true"` will only reload the pod, if the configmap or secret is used (as a volume mount or as an env) in `DeploymentConfigs/Deployment/Daemonsets/Statefulsets`
- `secret.reloader.stakater.com/reload` or `configmap.reloader.stakater.com/reload` annotation will reload the pod upon changes in specified configmap or secret, irrespective of the usage of configmap or secret.
- you may override the auto annotation with the `--auto-annotation` flag
- you may override the search annotation with the `--auto-search-annotation` flag
and the match annotation with the `--search-match-annotation` flag
- you may override the configmap annotation with the `--configmap-annotation` flag
- you may override the secret annotation with the `--secret-annotation` flag
- you may want to prevent watching certain namespaces with the `--namespaces-to-ignore` flag
- you may want to prevent watching certain resources with the `--resources-to-ignore` flag
- you can configure logging in JSON format with the `--log-format=json` option
## Deploying to Kubernetes
You can deploy Reloader by following methods:
### Vanilla Manifests
You can apply vanilla manifests by running the following command
You can apply vanilla manifests by changing `RELEASE-NAME` placeholder provided in manifest with a proper value and apply it by running the command given below:
```bash
kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
@@ -87,11 +156,44 @@ kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/depl
By default Reloader gets deployed in `default` namespace and watches changes `secrets` and `configmaps` in all namespaces.
Reloader can be configured to ignore the resources `secrets` and `configmaps` by passing the following args (`spec.template.spec.containers.args`) to its container :
| Args | Description |
| -------------------------------- | -------------------- |
| --resources-to-ignore=configMaps | To ignore configMaps |
| --resources-to-ignore=secrets | To ignore secrets |
`Note`: At one time only one of these resource can be ignored, trying to do it will cause error in Reloader. Workaround for ignoring both resources is by scaling down the reloader pods to `0`.
### Vanilla kustomize
You can also apply the vanilla manifests by running the following command
```bash
kubectl apply -k https://github.com/stakater/Reloader/deployments/kubernetes
```
Similarly to vanilla manifests get deployed in `default` namespace and watches changes `secrets` and `configmaps` in all namespaces.
### Kustomize
You can write your own `kustomization.yaml` using ours as a 'base' and write patches to tweak the configuration.
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- https://github.com/stakater/Reloader/deployments/kubernetes
namespace: reloader
```
### Helm Charts
Alternatively if you have configured helm on your cluster, you can add reloader to helm from our public chart repository and deploy it via helm using below mentioned commands
```bash
```bash
helm repo add stakater https://stakater.github.io/stakater-charts
helm repo update
@@ -99,18 +201,31 @@ helm repo update
helm install stakater/reloader
```
**Note:** By default reloader watches in all namespaces. To watch in single namespace, please run following command. It will install reloader in `test` namespace which will only watch `Deployments`, `Deamonsets` and `Statefulsets` in `test` namespace.
**Note:** By default reloader watches in all namespaces. To watch in single namespace, please run following command. It will install reloader in `test` namespace which will only watch `Deployments`, `Daemonsets` and `Statefulsets` in `test` namespace.
```bash
helm install stakater/reloader --set reloader.watchGlobally=false --namespace test
```
Reloader can be configured to ignore the resources `secrets` and `configmaps` by using the following parameters of `values.yaml` file:
| Parameter | Description | Type |
| ---------------- | -------------------------------------------------------------- | ------- |
| ignoreSecrets | To ignore secrets. Valid value are either `true` or `false` | boolean |
| ignoreConfigMaps | To ignore configMaps. Valid value are either `true` or `false` | boolean |
`Note`: At one time only one of these resource can be ignored, trying to do it will cause error in helm template compilation.
You can also set the log format of Reloader to json by setting `logFormat` to `json` in values.yaml and apply the chart
## Help
### Documentation
You can find more documentation [here](docs/)
### Have a question?
File a GitHub [issue](https://github.com/stakater/Reloader/issues), or send us an [email](mailto:stakater@gmail.com).
### Talk to us on Slack
@@ -130,11 +245,11 @@ Please use the [issue tracker](https://github.com/stakater/Reloader/issues) to r
PRs are welcome. In general, we follow the "fork-and-pull" Git workflow.
1. **Fork** the repo on GitHub
2. **Clone** the project to your own machine
3. **Commit** changes to your own branch
4. **Push** your work back up to your fork
5. Submit a **Pull request** so that we can review your changes
1. **Fork** the repo on GitHub
2. **Clone** the project to your own machine
3. **Commit** changes to your own branch
4. **Push** your work back up to your fork
5. Submit a **Pull request** so that we can review your changes
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
@@ -153,8 +268,8 @@ Apache2 © [Stakater](http://stakater.com)
See [our other projects][community]
or contact us in case of professional services and queries on <hello@stakater.com>
[website]: http://stakater.com/
[community]: https://github.com/stakater/
[website]: http://stakater.com/
[community]: https://github.com/stakater/
## Acknowledgements

View File

@@ -1,18 +1,21 @@
FROM stakater/go-glide:1.9.3
MAINTAINER "Stakater Team"
RUN apk update
FROM golang:1.13.9-alpine
LABEL maintainer "Stakater Team"
RUN apk -v --update \
add git build-base && \
rm -rf /var/cache/apk/* && \
mkdir -p "$GOPATH/src/github.com/stakater/Reloader"
--no-cache \
add git build-base
ADD . "$GOPATH/src/github.com/stakater/Reloader"
WORKDIR "$GOPATH/src/github.com/stakater/Reloader"
RUN cd "$GOPATH/src/github.com/stakater/Reloader" && \
glide update && \
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a --installsuffix cgo --ldflags="-s" -o /Reloader
COPY go.mod go.sum ./
RUN go mod download
COPY . .
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go build -a --installsuffix cgo --ldflags="-s" -o /Reloader
COPY build/package/Dockerfile.run /

View File

@@ -1,8 +1,11 @@
FROM alpine:3.4
MAINTAINER "Stakater Team"
FROM alpine:3.11
LABEL maintainer "Stakater Team"
RUN apk add --update ca-certificates
RUN apk add --update --no-cache ca-certificates
COPY Reloader /bin/Reloader
# On alpine 'nobody' has uid 65534
USER 65534
ENTRYPOINT ["/bin/Reloader"]

Binary file not shown.

View File

@@ -3,8 +3,8 @@
apiVersion: v1
name: reloader
description: Reloader chart that runs on kubernetes
version: 0.0.20
appVersion: 0.0.20
version: v0.0.62
appVersion: v0.0.62
keywords:
- Reloader
- kubernetes

View File

@@ -2,6 +2,7 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "reloader-name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" | lower -}}
{{- end -}}
@@ -16,7 +17,7 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
{{- end -}}
{{- define "reloader-labels.chart" -}}
app: {{ template "reloader-name" . }}
app: {{ template "reloader-fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: {{ .Release.Name | quote }}
heritage: {{ .Release.Service | quote }}
@@ -25,7 +26,7 @@ heritage: {{ .Release.Service | quote }}
{{/*
Create the name of the service account to use
*/}}
{{- define "serviceAccountName" -}}
{{- define "reloader-serviceAccountName" -}}
{{- if .Values.reloader.serviceAccount.create -}}
{{ default (include "reloader-fullname" .) .Values.reloader.serviceAccount.name }}
{{- else -}}

View File

@@ -1,4 +1,3 @@
---
{{- if and .Values.reloader.watchGlobally (.Values.reloader.rbac.enabled) }}
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
@@ -11,20 +10,35 @@ metadata:
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
{{- end }}
name: {{ template "reloader-name" . }}-role
name: {{ template "reloader-fullname" . }}-role
namespace: {{ .Release.Namespace }}
rules:
- apiGroups:
- ""
resources:
resources:
{{- if .Values.reloader.ignoreSecrets }}{{- else }}
- secrets
{{- end }}
{{- if .Values.reloader.ignoreConfigMaps }}{{- else }}
- configmaps
{{- end }}
verbs:
- list
- get
- watch
{{- if or (.Capabilities.APIVersions.Has "apps.openshift.io/v1") (.Values.isOpenshift) }}
- apiGroups:
- "apps.openshift.io"
- ""
resources:
- deploymentconfigs
verbs:
- list
- get
- update
- patch
{{- end }}
- apiGroups:
- "extensions"
- "apps"
resources:
- deployments
@@ -35,4 +49,14 @@ rules:
- get
- update
- patch
- apiGroups:
- "extensions"
resources:
- deployments
- daemonsets
verbs:
- list
- get
- update
- patch
{{- end }}

View File

@@ -1,5 +1,4 @@
{{- if and .Values.reloader.watchGlobally (.Values.reloader.rbac.enabled) }}
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
@@ -11,14 +10,14 @@ metadata:
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
{{- end }}
name: {{ template "reloader-name" . }}-role-binding
name: {{ template "reloader-fullname" . }}-role-binding
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ template "reloader-name" . }}-role
name: {{ template "reloader-fullname" . }}-role
subjects:
- kind: ServiceAccount
name: {{ template "serviceAccountName" . }}
name: {{ template "reloader-serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -1,4 +1,4 @@
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
{{- if .Values.reloader.deployment.annotations }}
@@ -13,19 +13,23 @@ metadata:
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
{{- end }}
name: {{ template "reloader-name" . }}
name: {{ template "reloader-fullname" . }}
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: {{ template "reloader-name" . }}
app: {{ template "reloader-fullname" . }}
release: {{ .Release.Name | quote }}
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 6 }}
{{- end }}
template:
metadata:
{{- if .Values.reloader.deployment.pod.annotations }}
annotations:
{{ toYaml .Values.reloader.deployment.pod.annotations | indent 8 }}
{{- end }}
labels:
{{ include "reloader-labels.chart" . | indent 8 }}
{{- if .Values.reloader.deployment.labels }}
@@ -35,8 +39,24 @@ spec:
{{ toYaml .Values.reloader.matchLabels | indent 8 }}
{{- end }}
spec:
{{- if .Values.reloader.deployment.nodeSelector }}
nodeSelector:
{{ toYaml .Values.reloader.deployment.nodeSelector | indent 8 }}
{{- end }}
{{- if .Values.reloader.deployment.affinity }}
affinity:
{{ toYaml .Values.reloader.deployment.affinity | indent 8 }}
{{- end }}
{{- if .Values.reloader.deployment.tolerations }}
tolerations:
{{ toYaml .Values.reloader.deployment.tolerations | indent 8 }}
{{- end }}
containers:
- env:
- image: "{{ .Values.reloader.deployment.image.name }}:{{ .Values.reloader.deployment.image.tag }}"
imagePullPolicy: {{ .Values.reloader.deployment.image.pullPolicy }}
name: {{ template "reloader-fullname" . }}
{{- if or (.Values.reloader.deployment.env.open) (.Values.reloader.deployment.env.secret) (.Values.reloader.deployment.env.field) }}
env:
{{- range $name, $value := .Values.reloader.deployment.env.open }}
{{- if not (empty $value) }}
- name: {{ $name | quote }}
@@ -67,7 +87,49 @@ spec:
fieldRef:
fieldPath: metadata.namespace
{{- end }}
image: "{{ .Values.reloader.deployment.image.name }}:{{ .Values.reloader.deployment.image.tag }}"
imagePullPolicy: {{ .Values.reloader.deployment.image.pullPolicy }}
name: {{ template "reloader-name" . }}
serviceAccountName: {{ template "serviceAccountName" . }}
{{- end }}
{{- if eq .Values.reloader.readOnlyRootFileSystem true }}
volumeMounts:
- mountPath: /tmp/
name: tmp-volume
{{- end }}
{{- if or (.Values.reloader.logFormat) (.Values.reloader.ignoreSecrets) (eq .Values.reloader.ignoreConfigMaps true) (.Values.reloader.custom_annotations) }}
args:
{{- if .Values.reloader.logFormat }}
- "--log-format={{ .Values.reloader.logFormat }}"
{{- end }}
{{- if .Values.reloader.ignoreSecrets }}
- "--resources-to-ignore=secrets"
{{- end }}
{{- if eq .Values.reloader.ignoreConfigMaps true }}
- "--resources-to-ignore=configMaps"
{{- end }}
{{- if .Values.reloader.custom_annotations }}
{{- if .Values.reloader.custom_annotations.configmap }}
- "--configmap-annotation"
- "{{ .Values.reloader.custom_annotations.configmap }}"
{{- end }}
{{- if .Values.reloader.custom_annotations.secret }}
- "--secret-annotation"
- "{{ .Values.reloader.custom_annotations.secret }}"
{{- end }}
{{- if .Values.reloader.custom_annotations.auto }}
- "--auto-annotation"
- "{{ .Values.reloader.custom_annotations.auto }}"
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.reloader.deployment.resources }}
resources:
{{ toYaml .Values.reloader.deployment.resources | indent 10 }}
{{- end }}
{{- if .Values.reloader.deployment.securityContext }}
securityContext: {{ toYaml .Values.reloader.deployment.securityContext | nindent 8 }}
{{- end }}
serviceAccountName: {{ template "reloader-serviceAccountName" . }}
{{- if eq .Values.reloader.readOnlyRootFileSystem true }}
volumes:
- emptyDir: {}
name: tmp-volume
{{- end }}

View File

@@ -10,20 +10,35 @@ metadata:
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
{{- end }}
name: {{ template "reloader-name" . }}-role
name: {{ template "reloader-fullname" . }}-role
namespace: {{ .Release.Namespace }}
rules:
- apiGroups:
- ""
resources:
resources:
{{- if .Values.reloader.ignoreSecrets }}{{- else }}
- secrets
{{- end }}
{{- if .Values.reloader.ignoreConfigMaps }}{{- else }}
- configmaps
{{- end }}
verbs:
- list
- get
- watch
{{- if or (.Capabilities.APIVersions.Has "apps.openshift.io/v1") (.Values.reloader.isOpenshift) }}
- apiGroups:
- "apps.openshift.io"
- ""
resources:
- deploymentconfigs
verbs:
- list
- get
- update
- patch
{{- end }}
- apiGroups:
- "extensions"
- "apps"
resources:
- deployments
@@ -34,4 +49,14 @@ rules:
- get
- update
- patch
- apiGroups:
- "extensions"
resources:
- deployments
- daemonsets
verbs:
- list
- get
- update
- patch
{{- end }}

View File

@@ -1,5 +1,4 @@
{{- if and (not (.Values.reloader.watchGlobally)) (.Values.reloader.rbac.enabled) }}
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
@@ -11,14 +10,14 @@ metadata:
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
{{- end }}
name: {{ template "reloader-name" . }}-role-binding
name: {{ template "reloader-fullname" . }}-role-binding
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ template "reloader-name" . }}-role
name: {{ template "reloader-fullname" . }}-role
subjects:
- kind: ServiceAccount
name: {{ template "serviceAccountName" . }}
name: {{ template "reloader-serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -0,0 +1,25 @@
{{- if .Values.reloader.service }}
apiVersion: v1
kind: Service
metadata:
{{- if .Values.reloader.service.annotations }}
annotations:
{{ toYaml .Values.reloader.service.annotations | indent 4 }}
{{- end }}
labels:
{{ include "reloader-labels.chart" . | indent 4 }}
{{- if .Values.reloader.service.labels }}
{{ toYaml .Values.reloader.service.labels | indent 4 }}
{{- end }}
name: {{ template "reloader-fullname" . }}
spec:
selector:
{{- if .Values.reloader.deployment.labels }}
{{ toYaml .Values.reloader.deployment.labels | indent 4 }}
{{- end }}
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
{{- end }}
ports:
{{ toYaml .Values.reloader.service.ports | indent 4 }}
{{- end }}

View File

@@ -1,6 +1,9 @@
{{- if .Values.reloader.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
{{- if .Values.global.imagePullSecrets }}
imagePullSecrets: {{ toYaml .Values.global.imagePullSecrets | nindent 2 }}
{{- end }}
metadata:
labels:
{{ include "reloader-labels.chart" . | indent 4 }}
@@ -10,5 +13,5 @@ metadata:
{{- if .Values.reloader.matchLabels }}
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
{{- end }}
name: {{ template "serviceAccountName" . }}
name: {{ template "reloader-serviceAccountName" . }}
{{- end }}

View File

@@ -1,20 +1,57 @@
# Generated from deployments/kubernetes/templates/chart/values.yaml.tmpl
global:
## Reference to one or more secrets to be used when pulling images
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
imagePullSecrets: []
kubernetes:
host: https://kubernetes.default
reloader:
isOpenshift: false
ignoreSecrets: false
ignoreConfigMaps: false
logFormat: "" #json
watchGlobally: true
# Set to true if you have a pod security policy that enforces readOnlyRootFilesystem
readOnlyRootFileSystem: false
matchLabels: {}
deployment:
nodeSelector:
# cloud.google.com/gke-nodepool: default-pool
# An affinity stanza to be applied to the Deployment.
# Example:
# affinity:
# nodeAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# nodeSelectorTerms:
# - matchExpressions:
# - key: "node-role.kubernetes.io/infra-worker"
# operator: "Exists"
affinity: {}
securityContext:
runAsNonRoot: true
runAsUser: 65534
# A list of tolerations to be applied to the Deployment.
# Example:
# tolerations:
# - key: "node-role.kubernetes.io/infra-worker"
# operator: "Exists"
# effect: "NoSchedule"
tolerations: []
annotations: {}
labels:
provider: stakater
group: com.stakater.platform
version: 0.0.20
version: v0.0.62
image:
name: stakater/reloader
tag: "0.0.20"
tag: "v0.0.62"
pullPolicy: IfNotPresent
# Support for extra environment variables.
env:
@@ -24,6 +61,29 @@ reloader:
secret:
# field supports Key value pair as environment variables. It gets the values from other fields of pod.
field:
# Specify resource requests/limits for the deployment.
# Example:
# resources:
# limits:
# cpu: "100m"
# memory: "512Mi"
# requests:
# cpu: "10m"
# memory: "128Mi"
resources: {}
pod:
annotations: {}
service: {}
# labels: {}
# annotations: {}
# ports:
# - port: 9090
# name: http
# protocol: TCP
# targetPort: 9090
rbac:
enabled: true
labels: {}
@@ -34,4 +94,10 @@ reloader:
labels: {}
# The name of the ServiceAccount to use.
# If not set and create is true, a name is generated using the fullname template
name: reloader
name:
# Optional flags to pass to the Reloader entrypoint
# Example:
# custom_annotations:
# configmap: "my.company.com/configmap"
# secret: "my.company.com/secret"
custom_annotations: {}

View File

@@ -0,0 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- manifests/clusterrole.yaml
- manifests/clusterrolebinding.yaml
- manifests/role.yaml
- manifests/rolebinding.yaml
- manifests/serviceaccount.yaml
- manifests/deployment.yaml

View File

@@ -1,20 +1,20 @@
---
# Source: reloader/templates/clusterrole.yaml
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
name: reloader-role
name: reloader-reloader-role
namespace: default
rules:
- apiGroups:
- ""
resources:
resources:
- secrets
- configmaps
verbs:
@@ -22,7 +22,6 @@ rules:
- get
- watch
- apiGroups:
- "extensions"
- "apps"
resources:
- deployments
@@ -33,4 +32,14 @@ rules:
- get
- update
- patch
- apiGroups:
- "extensions"
resources:
- deployments
- daemonsets
verbs:
- list
- get
- update
- patch

View File

@@ -1,23 +1,22 @@
---
# Source: reloader/templates/clusterrolebinding.yaml
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
name: reloader-role-binding
name: reloader-reloader-role-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reloader-role
name: reloader-reloader-role
subjects:
- kind: ServiceAccount
name: reloader
name: reloader-reloader
namespace: default

View File

@@ -1,41 +1,44 @@
---
# Source: reloader/templates/deployment.yaml
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
group: com.stakater.platform
provider: stakater
version: 0.0.20
version: v0.0.62
name: reloader
name: reloader-reloader
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: reloader
release: "RELEASE-NAME"
app: reloader-reloader
release: "reloader"
template:
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
group: com.stakater.platform
provider: stakater
version: 0.0.20
version: v0.0.62
spec:
containers:
- env:
image: "stakater/reloader:0.0.20"
- image: "stakater/reloader:v0.0.62"
imagePullPolicy: IfNotPresent
name: reloader
serviceAccountName: reloader
name: reloader-reloader
securityContext:
runAsNonRoot: true
runAsUser: 65534
serviceAccountName: reloader-reloader

View File

@@ -1,73 +0,0 @@
---
# Source: reloader/templates/rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: reloader
group: com.stakater.platform
provider: stakater
version: 0.0.18
chart: "reloader-0.0.18"
release: "RELEASE-NAME"
heritage: "Tiller"
name: reloader
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
labels:
app: reloader
group: com.stakater.platform
provider: stakater
version: 0.0.18
chart: "reloader-0.0.18"
release: "RELEASE-NAME"
heritage: "Tiller"
name: reloader-role
namespace: default
rules:
- apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- list
- get
- watch
- apiGroups:
- ""
- "extensions"
- "apps"
resources:
- deployments
- daemonsets
- statefulsets
verbs:
- list
- get
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
app: reloader
group: com.stakater.platform
provider: stakater
version: 0.0.18
chart: "reloader-0.0.18"
release: "RELEASE-NAME"
heritage: "Tiller"
name: reloader-role-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reloader-role
subjects:
- kind: ServiceAccount
name: reloader
namespace: default

View File

@@ -0,0 +1,3 @@
---
# Source: reloader/templates/service.yaml

View File

@@ -5,9 +5,9 @@ apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
name: reloader
name: reloader-reloader

View File

@@ -1,65 +1,20 @@
---
# Source: reloader/templates/role.yaml
---
# Source: reloader/templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
heritage: "Tiller"
group: com.stakater.platform
provider: stakater
version: 0.0.20
name: reloader
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: reloader
release: "RELEASE-NAME"
template:
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
heritage: "Tiller"
group: com.stakater.platform
provider: stakater
version: 0.0.20
spec:
containers:
- env:
image: "stakater/reloader:0.0.20"
imagePullPolicy: IfNotPresent
name: reloader
serviceAccountName: reloader
---
# Source: reloader/templates/clusterrole.yaml
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
name: reloader-role
name: reloader-reloader-role
namespace: default
rules:
- apiGroups:
- ""
resources:
resources:
- secrets
- configmaps
verbs:
@@ -67,7 +22,6 @@ rules:
- get
- watch
- apiGroups:
- "extensions"
- "apps"
resources:
- deployments
@@ -78,106 +32,93 @@ rules:
- get
- update
- patch
- apiGroups:
- "extensions"
resources:
- deployments
- daemonsets
verbs:
- list
- get
- update
- patch
---
# Source: reloader/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
name: reloader-reloader-role-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reloader-reloader-role
subjects:
- kind: ServiceAccount
name: reloader-reloader
namespace: default
---
# Source: reloader/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
group: com.stakater.platform
provider: stakater
version: v0.0.62
name: reloader-reloader
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app: reloader-reloader
release: "reloader"
template:
metadata:
labels:
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
group: com.stakater.platform
provider: stakater
version: v0.0.62
spec:
containers:
- image: "stakater/reloader:v0.0.62"
imagePullPolicy: IfNotPresent
name: reloader-reloader
securityContext:
runAsNonRoot: true
runAsUser: 65534
serviceAccountName: reloader-reloader
---
# Source: reloader/templates/role.yaml
---
# Source: reloader/templates/rolebinding.yaml
---
# Source: reloader/templates/rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: reloader
group: com.stakater.platform
provider: stakater
version: 0.0.18
chart: "reloader-0.0.18"
release: "RELEASE-NAME"
heritage: "Tiller"
name: reloader
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
labels:
app: reloader
group: com.stakater.platform
provider: stakater
version: 0.0.18
chart: "reloader-0.0.18"
release: "RELEASE-NAME"
heritage: "Tiller"
name: reloader-role
namespace: default
rules:
- apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- list
- get
- watch
- apiGroups:
- ""
- "extensions"
- "apps"
resources:
- deployments
- daemonsets
- statefulsets
verbs:
- list
- get
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
app: reloader
group: com.stakater.platform
provider: stakater
version: 0.0.18
chart: "reloader-0.0.18"
release: "RELEASE-NAME"
heritage: "Tiller"
name: reloader-role-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reloader-role
subjects:
- kind: ServiceAccount
name: reloader
namespace: default
---
# Source: reloader/templates/clusterrolebinding.yaml
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
heritage: "Tiller"
name: reloader-role-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reloader-role
subjects:
- kind: ServiceAccount
name: reloader
namespace: default
# Source: reloader/templates/service.yaml
---
# Source: reloader/templates/serviceaccount.yaml
@@ -186,9 +127,9 @@ apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: reloader
chart: "reloader-0.0.20"
release: "RELEASE-NAME"
app: reloader-reloader
chart: "reloader-v0.0.62"
release: "reloader"
heritage: "Tiller"
name: reloader
name: reloader-reloader

View File

@@ -1,12 +1,49 @@
# Generated from deployments/kubernetes/templates/chart/values.yaml.tmpl
global:
## Reference to one or more secrets to be used when pulling images
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
imagePullSecrets: []
kubernetes:
host: https://kubernetes.default
reloader:
isOpenshift: false
ignoreSecrets: false
ignoreConfigMaps: false
logFormat: "" #json
watchGlobally: true
# Set to true if you have a pod security policy that enforces readOnlyRootFilesystem
readOnlyRootFileSystem: false
matchLabels: {}
deployment:
nodeSelector:
# cloud.google.com/gke-nodepool: default-pool
# An affinity stanza to be applied to the Deployment.
# Example:
# affinity:
# nodeAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# nodeSelectorTerms:
# - matchExpressions:
# - key: "node-role.kubernetes.io/infra-worker"
# operator: "Exists"
affinity: {}
securityContext:
runAsNonRoot: true
runAsUser: 65534
# A list of tolerations to be applied to the Deployment.
# Example:
# tolerations:
# - key: "node-role.kubernetes.io/infra-worker"
# operator: "Exists"
# effect: "NoSchedule"
tolerations: []
annotations: {}
labels:
provider: stakater
@@ -24,6 +61,29 @@ reloader:
secret:
# field supports Key value pair as environment variables. It gets the values from other fields of pod.
field:
# Specify resource requests/limits for the deployment.
# Example:
# resources:
# limits:
# cpu: "100m"
# memory: "512Mi"
# requests:
# cpu: "10m"
# memory: "128Mi"
resources: {}
pod:
annotations: {}
service: {}
# labels: {}
# annotations: {}
# ports:
# - port: 9090
# name: http
# protocol: TCP
# targetPort: 9090
rbac:
enabled: true
labels: {}
@@ -34,4 +94,10 @@ reloader:
labels: {}
# The name of the ServiceAccount to use.
# If not set and create is true, a name is generated using the fullname template
name: reloader
name:
# Optional flags to pass to the Reloader entrypoint
# Example:
# custom_annotations:
# configmap: "my.company.com/configmap"
# secret: "my.company.com/secret"
custom_annotations: {}

View File

@@ -1,6 +1,6 @@
# How it works?
Reloader watches for `ConfigMap` and `Secret` and detects if there are changes in data of these objects. After change detection reloader performs rolling upgrade on relevant Pods via associated `Deployment`, `Deamonset` and `Statefulset`.
Reloader watches for `ConfigMap` and `Secret` and detects if there are changes in data of these objects. After change detection reloader performs rolling upgrade on relevant Pods via associated `Deployment`, `Daemonset` and `Statefulset`.
## How change detection works
@@ -17,23 +17,25 @@ The annotation value is comma separated list of `configmaps` or `secrets`. If a
### Annotation for Configmap
For a `Deployment` called `foo` have a `ConfigMap` called `foo`. Then add this annotation to your `Deployment`
For a `Deployment` called `foo` have a `ConfigMap` called `foo`. Then add this annotation* to your `Deployment`
```yaml
metadata:
annotations:
configmap.reloader.stakater.com/reload: "foo"
```
<small>*the default annotation can be changed with the `--configmap-annotation` flag</small>
### Annotation for Secret
For a `Deployment` called `foo` have a `Secret` called `foo`. Then add this annotation to your `Deployment`
For a `Deployment` called `foo` have a `Secret` called `foo`. Then add this annotation* to your `Deployment`
```yaml
metadata:
annotations:
secret.reloader.stakater.com/reload: "foo"
```
<small>*the default annotation can be changed with the `--secret-annotation` flag</small>
Above mentioned annotation are also work for `Daemonsets` and `Statefulsets`

View File

@@ -8,4 +8,5 @@ Reloader is inspired from [Configmapcontroller](https://github.com/fabric8io/con
| Reloader can watch both `secrets` and `configmaps`. | ConfigmapController can only watch changes in `configmaps`. It cannot detect changes in other resources like `secrets`. |
| Reloader can perform rolling upgrades on `deployments` as well as on `statefulsets` and `daemonsets` | ConfigmapController can only perform rolling upgrades on `deployments`. It currently does not support rolling upgrades on `statefulsets` and `daemonsets` |
| Reloader provides both unit test cases and end to end integration test cases for future updates. So one can make sure that new changes do not break any old functionality. | Currently there are not any unit test cases or end to end integration test cases in configmap controller. It add difficulties for any additional updates in configmap controller and one can not know for sure whether new changes breaks any old functionality or not. |
| Reloader uses SHA1 to encode the change in configmap or secret. It then saves the SHA1 value in `STAKATER_FOO_CONFIGMAP` or `STAKATER_FOO_SECRET` environment variable depending upon where the change has happened. The use of SHA1 provides a concise 40 characters encoded value that is very less pron to collision. | Configmap controller uses `FABRICB_FOO_REVISION` environment variable to store any change in configmap controller. It does not encode it or convert it in suitable hash value to avoid data pollution in deployment. |
| Reloader uses SHA1 to encode the change in configmap or secret. It then saves the SHA1 value in `STAKATER_FOO_CONFIGMAP` or `STAKATER_FOO_SECRET` environment variable depending upon where the change has happened. The use of SHA1 provides a concise 40 characters encoded value that is very less pron to collision. | Configmap controller uses `FABRICB_FOO_REVISION` environment variable to store any change in configmap controller. It does not encode it or convert it in suitable hash value to avoid data pollution in deployment. |
| Reloader allows you to customize your own annotation (for both Secrets and Configmaps) using command line flags | Configmap controller restricts you to only their provided annotation |

View File

@@ -25,4 +25,16 @@ Reloader supports deployment rollout as well as daemonsets and statefulsets roll
k8s-trigger-controller stores the hash value in an annotation `trigger.k8s.io/[secret|configMap]-NAME-last-hash`
#### Reloader:
Reloader stores the hash value in an environment variable `STAKATER_NAME_[SECRET|CONFIGMAP]`
Reloader stores the hash value in an environment variable `STAKATER_NAME_[SECRET|CONFIGMAP]`
### Customization
#### k8s-trigger-controller:
k8s-trigger-controller restricts you to using the `trigger.k8s.io/[secret-configMap]-NAME-last-hash` annotation
#### Reloader:
Reloader allows you to customize the annotation to fit your needs with command line flags:
- `--auto-annotation <annotation>`
- `--configmap-annotation <annotation>`
- `--secret-annotation <annotation>`

View File

@@ -0,0 +1,11 @@
Below are the steps to use reloader with Sealed Secrets.
1. Download and install the kubeseal client from [here](https://github.com/bitnami-labs/sealed-secrets).
2. Install the controller for sealed secrets
3. Fetch the encryption certificate
4. Encrypt the secret.
5. Apply the secret.
7. Install the tool which uses that sealed secret.
8. Install Reloader.
9. Once everything is setup, update the original secret at client and encrypt it with kubeseal to see reloader working.
10. Apply the updated sealed secret.
11. Reloader will restart the pod to use that updated secret.

View File

@@ -1,6 +1,6 @@
# Verify Reloader's Working
Reloader's working can be verified by two ways.
Reloader's working can be verified by three ways.
## Verify from logs
@@ -49,3 +49,13 @@ After a change in `secret` or `configmap`. Run the below mentioned command and v
```bash
kubectl get pods <pod name> -n <namespace name>
```
## Verify from metrics
Some metrics are exported to prometheus endpoint `/metrics` on port `9090`.
When reloader is unable to reload, `reloader_reload_executed_total{success="false"}` metric gets incremented and when it reloads successfully, `reloader_reload_executed_total{success="true"}` gets incremented. You will be able to see the following metrics, with some other metrics, at `/metrics` endpoint.
```
reloader_reload_executed_total{success="false"} 15
reloader_reload_executed_total{success="true"} 12
```

269
glide.lock generated
View File

@@ -1,269 +0,0 @@
hash: b6fe060028bdb1249ba2413746476c2550b267eeab3c166c36a86e000a8dd354
updated: 2018-07-24T21:12:43.027181463+05:00
imports:
- name: github.com/davecgh/go-spew
version: 782f4967f2dc4564575ca782fe2d04090b5faca8
subpackages:
- spew
- name: github.com/emicklei/go-restful
version: ff4f55a206334ef123e4f79bbf348980da81ca46
subpackages:
- log
- name: github.com/emicklei/go-restful-swagger12
version: dcef7f55730566d41eae5db10e7d6981829720f6
- name: github.com/ghodss/yaml
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
- name: github.com/go-openapi/jsonpointer
version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
- name: github.com/go-openapi/jsonreference
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
- name: github.com/go-openapi/spec
version: 6aced65f8501fe1217321abf0749d354824ba2ff
- name: github.com/go-openapi/swag
version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72
- name: github.com/gogo/protobuf
version: c0656edd0d9eab7c66d1eb0c568f9039345796f7
subpackages:
- proto
- sortkeys
- name: github.com/golang/glog
version: 44145f04b68cf362d9c4df2182967c2275eaefed
- name: github.com/golang/protobuf
version: 4bd1920723d7b7c925de087aa32e2187708897f7
subpackages:
- proto
- ptypes
- ptypes/any
- ptypes/duration
- ptypes/timestamp
- name: github.com/google/btree
version: 7d79101e329e5a3adf994758c578dab82b90c017
- name: github.com/google/gofuzz
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
- name: github.com/googleapis/gnostic
version: 0c5108395e2debce0d731cf0287ddf7242066aba
subpackages:
- OpenAPIv2
- compiler
- extensions
- name: github.com/gregjones/httpcache
version: 787624de3eb7bd915c329cba748687a3b22666a6
subpackages:
- diskcache
- name: github.com/hashicorp/golang-lru
version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
subpackages:
- simplelru
- name: github.com/howeyc/gopass
version: bf9dde6d0d2c004a008c27aaee91170c786f6db8
- name: github.com/imdario/mergo
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
- name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/json-iterator/go
version: 36b14963da70d11297d313183d7e6388c8510e1e
- name: github.com/juju/ratelimit
version: 5b9ff866471762aa2ab2dced63c9fb6f53921342
- name: github.com/mailru/easyjson
version: d5b7844b561a7bc640052f1b935f7b800330d7e0
subpackages:
- buffer
- jlexer
- jwriter
- name: github.com/peterbourgon/diskv
version: 5f041e8faa004a95c88a202771f4cc3e991971e6
- name: github.com/PuerkitoBio/purell
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
- name: github.com/PuerkitoBio/urlesc
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
- name: github.com/sirupsen/logrus
version: c155da19408a8799da419ed3eeb0cb5db0ad5dbc
- name: github.com/spf13/cobra
version: ef82de70bb3f60c65fb8eebacbb2d122ef517385
- name: github.com/spf13/pflag
version: 583c0c0531f06d5278b7d917446061adc344b5cd
- name: golang.org/x/crypto
version: 81e90905daefcd6fd217b62423c0908922eadb30
subpackages:
- ssh/terminal
- name: golang.org/x/net
version: 1c05540f6879653db88113bc4a2b70aec4bd491f
subpackages:
- context
- http2
- http2/hpack
- idna
- lex/httplex
- name: golang.org/x/sys
version: 7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce
subpackages:
- unix
- windows
- name: golang.org/x/text
version: b19bf474d317b857955b12035d2c5acb57ce8b01
subpackages:
- cases
- internal
- internal/tag
- language
- runes
- secure/bidirule
- secure/precis
- transform
- unicode/bidi
- unicode/norm
- width
- name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/yaml.v2
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
- name: k8s.io/api
version: fe29995db37613b9c5b2a647544cf627bfa8d299
subpackages:
- admissionregistration/v1alpha1
- apps/v1beta1
- apps/v1beta2
- authentication/v1
- authentication/v1beta1
- authorization/v1
- authorization/v1beta1
- autoscaling/v1
- autoscaling/v2beta1
- batch/v1
- batch/v1beta1
- batch/v2alpha1
- certificates/v1beta1
- core/v1
- extensions/v1beta1
- networking/v1
- policy/v1beta1
- rbac/v1
- rbac/v1alpha1
- rbac/v1beta1
- scheduling/v1alpha1
- settings/v1alpha1
- storage/v1
- storage/v1beta1
- name: k8s.io/apimachinery
version: 019ae5ada31de202164b118aee88ee2d14075c31
subpackages:
- pkg/api/equality
- pkg/api/errors
- pkg/api/meta
- pkg/api/resource
- pkg/apis/meta/internalversion
- pkg/apis/meta/v1
- pkg/apis/meta/v1/unstructured
- pkg/apis/meta/v1alpha1
- pkg/conversion
- pkg/conversion/queryparams
- pkg/conversion/unstructured
- pkg/fields
- pkg/labels
- pkg/runtime
- pkg/runtime/schema
- pkg/runtime/serializer
- pkg/runtime/serializer/json
- pkg/runtime/serializer/protobuf
- pkg/runtime/serializer/recognizer
- pkg/runtime/serializer/streaming
- pkg/runtime/serializer/versioning
- pkg/selection
- pkg/types
- pkg/util/cache
- pkg/util/clock
- pkg/util/diff
- pkg/util/errors
- pkg/util/framer
- pkg/util/intstr
- pkg/util/json
- pkg/util/net
- pkg/util/runtime
- pkg/util/sets
- pkg/util/validation
- pkg/util/validation/field
- pkg/util/wait
- pkg/util/yaml
- pkg/version
- pkg/watch
- third_party/forked/golang/reflect
- name: k8s.io/client-go
version: 35874c597fed17ca62cd197e516d7d5ff9a2958c
subpackages:
- discovery
- discovery/fake
- kubernetes
- kubernetes/fake
- kubernetes/scheme
- kubernetes/typed/admissionregistration/v1alpha1
- kubernetes/typed/admissionregistration/v1alpha1/fake
- kubernetes/typed/apps/v1beta1
- kubernetes/typed/apps/v1beta1/fake
- kubernetes/typed/apps/v1beta2
- kubernetes/typed/apps/v1beta2/fake
- kubernetes/typed/authentication/v1
- kubernetes/typed/authentication/v1/fake
- kubernetes/typed/authentication/v1beta1
- kubernetes/typed/authentication/v1beta1/fake
- kubernetes/typed/authorization/v1
- kubernetes/typed/authorization/v1/fake
- kubernetes/typed/authorization/v1beta1
- kubernetes/typed/authorization/v1beta1/fake
- kubernetes/typed/autoscaling/v1
- kubernetes/typed/autoscaling/v1/fake
- kubernetes/typed/autoscaling/v2beta1
- kubernetes/typed/autoscaling/v2beta1/fake
- kubernetes/typed/batch/v1
- kubernetes/typed/batch/v1/fake
- kubernetes/typed/batch/v1beta1
- kubernetes/typed/batch/v1beta1/fake
- kubernetes/typed/batch/v2alpha1
- kubernetes/typed/batch/v2alpha1/fake
- kubernetes/typed/certificates/v1beta1
- kubernetes/typed/certificates/v1beta1/fake
- kubernetes/typed/core/v1
- kubernetes/typed/core/v1/fake
- kubernetes/typed/extensions/v1beta1
- kubernetes/typed/extensions/v1beta1/fake
- kubernetes/typed/networking/v1
- kubernetes/typed/networking/v1/fake
- kubernetes/typed/policy/v1beta1
- kubernetes/typed/policy/v1beta1/fake
- kubernetes/typed/rbac/v1
- kubernetes/typed/rbac/v1/fake
- kubernetes/typed/rbac/v1alpha1
- kubernetes/typed/rbac/v1alpha1/fake
- kubernetes/typed/rbac/v1beta1
- kubernetes/typed/rbac/v1beta1/fake
- kubernetes/typed/scheduling/v1alpha1
- kubernetes/typed/scheduling/v1alpha1/fake
- kubernetes/typed/settings/v1alpha1
- kubernetes/typed/settings/v1alpha1/fake
- kubernetes/typed/storage/v1
- kubernetes/typed/storage/v1/fake
- kubernetes/typed/storage/v1beta1
- kubernetes/typed/storage/v1beta1/fake
- pkg/version
- rest
- rest/watch
- testing
- tools/auth
- tools/cache
- tools/clientcmd
- tools/clientcmd/api
- tools/clientcmd/api/latest
- tools/clientcmd/api/v1
- tools/metrics
- tools/pager
- tools/reference
- transport
- util/cert
- util/flowcontrol
- util/homedir
- util/integer
- util/workqueue
- name: k8s.io/kube-openapi
version: 868f2f29720b192240e18284659231b440f9cda5
subpackages:
- pkg/common
testImports: []

View File

@@ -1,14 +0,0 @@
package: github.com/stakater/Reloader
import:
- package: k8s.io/api
version: kubernetes-1.8.0
- package: k8s.io/apimachinery
version: kubernetes-1.8.0
- package: k8s.io/client-go
version: 5.0.0
- package: github.com/spf13/cobra
version: 0.0.3
- package: github.com/spf13/pflag
version: 1.0.1
- package: github.com/sirupsen/logrus
version: 1.0.5

28
go.mod Normal file
View File

@@ -0,0 +1,28 @@
module github.com/stakater/Reloader
go 1.13
require (
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/onsi/ginkgo v1.10.2 // indirect
github.com/onsi/gomega v1.7.0 // indirect
github.com/openshift/api v3.9.1-0.20190923092516-169848dd8137+incompatible
github.com/openshift/client-go v0.0.0-20190923092832-6afefc9bb372
github.com/prometheus/client_golang v1.4.1
github.com/sirupsen/logrus v1.4.2
github.com/spf13/cobra v0.0.0-20160722081547-f62e98d28ab7
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
k8s.io/api v0.0.0-20190918155943-95b840bb6a1f
k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90
)
replace (
github.com/openshift/api => github.com/openshift/api v3.9.1-0.20190923092516-169848dd8137+incompatible // prebase-1.16
github.com/openshift/client-go => github.com/openshift/client-go v0.0.0-20190923092832-6afefc9bb372 // prebase-1.16
k8s.io/api => k8s.io/api v0.0.0-20191004120104-195af9ec3521 // release-1.16
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8 // kubernetes-1.16.0
k8s.io/client-go => k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90 // kubernetes-1.16.0
)

293
go.sum Normal file
View File

@@ -0,0 +1,293 @@
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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
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 v0.0.0-20150909031657-73d445a93680 h1:ZktWZesgun21uEDrwW7iEV1zPCGQldM2atlJZ3TdvVM=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc h1:55rEp52jU6bkyslZ1+C/7NGfpQsEc6pxGLAGDOctqbw=
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
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 v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
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/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367 h1:ScAXWS+TR6MZKex+7Z8rneuSJH+FSDqd6ocQyl+ZHo4=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3 h1:/UewZcckqhvnnS0C6r3Sher2hSEbVmM6Ogpcjen08+Y=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/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/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da h1:ZQGIPjr1iTtUPXZFk8WShqb5G+Qg65VHFLtSvmHh+Mw=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94=
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openshift/api v3.9.1-0.20190923092516-169848dd8137+incompatible h1:vfxB7vqajc9CkO9e68Aj4kt7qzuKsOBcLJcEnSzNrM0=
github.com/openshift/api v3.9.1-0.20190923092516-169848dd8137+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
github.com/openshift/client-go v0.0.0-20190923092832-6afefc9bb372 h1:iOFI/ua5QKKEHTy8ohWdY1kgWpEmik8nw5ZCESx0Crg=
github.com/openshift/client-go v0.0.0-20190923092832-6afefc9bb372/go.mod h1:6rzn+JTr7+WYS2E1TExP4gByoABxMznR6y2SnUIkmxk=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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 v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8=
github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cobra v0.0.0-20160722081547-f62e98d28ab7 h1:vX79RLf8hJqzYiv0FVgbIqSD76lK4dTIoIN29Kc4MXo=
github.com/spf13/cobra v0.0.0-20160722081547-f62e98d28ab7/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/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/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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 h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
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-20190108225652-1e06a53dbb7e/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/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=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190209173611-3b5209105503/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.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-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
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=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
k8s.io/api v0.0.0-20191004120104-195af9ec3521 h1:StP5An9aFEWfPckudvHEJc4q/WUDCUVGoZJrE/efGME=
k8s.io/api v0.0.0-20191004120104-195af9ec3521/go.mod h1:/L5qH+AD540e7Cetbui1tuJeXdmNhO8jM6VkXeDdDhQ=
k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8 h1:Iieh/ZEgT3BWwbLD5qEKcY06jKuPEl6zC7gPSehoLw4=
k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90 h1:mLmhKUm1X+pXu0zXMEzNsOF5E2kKFGe5o6BZBIIqA6A=
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.4.0 h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ=
k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf h1:EYm5AW/UUDbnmnI+gK0TJDVK9qPLhM+sRHYanNKw0EQ=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1 h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

View File

@@ -3,89 +3,207 @@ package callbacks
import (
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/util"
apps_v1beta1 "k8s.io/api/apps/v1beta1"
"k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
"github.com/stakater/Reloader/pkg/kube"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
openshiftv1 "github.com/openshift/api/apps/v1"
)
//ItemsFunc is a generic function to return a specific resource array in given namespace
type ItemsFunc func(kubernetes.Interface, string) []interface{}
type ItemsFunc func(kube.Clients, string) []interface{}
//ContainersFunc is a generic func to return containers
type ContainersFunc func(interface{}) []v1.Container
//InitContainersFunc is a generic func to return containers
type InitContainersFunc func(interface{}) []v1.Container
//VolumesFunc is a generic func to return volumes
type VolumesFunc func(interface{}) []v1.Volume
//UpdateFunc performs the resource update
type UpdateFunc func(kubernetes.Interface, string, interface{}) error
type UpdateFunc func(kube.Clients, string, interface{}) error
//AnnotationsFunc is a generic func to return annotations
type AnnotationsFunc func(interface{}) map[string]string
//PodAnnotationsFunc is a generic func to return annotations
type PodAnnotationsFunc func(interface{}) map[string]string
//RollingUpgradeFuncs contains generic functions to perform rolling upgrade
type RollingUpgradeFuncs struct {
ItemsFunc ItemsFunc
ContainersFunc ContainersFunc
UpdateFunc UpdateFunc
ResourceType string
ItemsFunc ItemsFunc
AnnotationsFunc AnnotationsFunc
PodAnnotationsFunc PodAnnotationsFunc
ContainersFunc ContainersFunc
InitContainersFunc InitContainersFunc
UpdateFunc UpdateFunc
VolumesFunc VolumesFunc
ResourceType string
}
// GetDeploymentItems returns the deployments in given namespace
func GetDeploymentItems(client kubernetes.Interface, namespace string) []interface{} {
deployments, err := client.ExtensionsV1beta1().Deployments(namespace).List(meta_v1.ListOptions{})
func GetDeploymentItems(clients kube.Clients, namespace string) []interface{} {
deployments, err := clients.KubernetesClient.AppsV1().Deployments(namespace).List(meta_v1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to list deployments %v", err)
}
return util.InterfaceSlice(deployments.Items)
}
// GetDaemonSetItems returns the daemonSet in given namespace
func GetDaemonSetItems(client kubernetes.Interface, namespace string) []interface{} {
daemonSets, err := client.ExtensionsV1beta1().DaemonSets(namespace).List(meta_v1.ListOptions{})
// GetDaemonSetItems returns the daemonSets in given namespace
func GetDaemonSetItems(clients kube.Clients, namespace string) []interface{} {
daemonSets, err := clients.KubernetesClient.AppsV1().DaemonSets(namespace).List(meta_v1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to list daemonSets %v", err)
}
return util.InterfaceSlice(daemonSets.Items)
}
// GetStatefulSetItems returns the statefulSet in given namespace
func GetStatefulSetItems(client kubernetes.Interface, namespace string) []interface{} {
statefulSets, err := client.AppsV1beta1().StatefulSets(namespace).List(meta_v1.ListOptions{})
// GetStatefulSetItems returns the statefulSets in given namespace
func GetStatefulSetItems(clients kube.Clients, namespace string) []interface{} {
statefulSets, err := clients.KubernetesClient.AppsV1().StatefulSets(namespace).List(meta_v1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to list statefulSets %v", err)
}
return util.InterfaceSlice(statefulSets.Items)
}
// GetDeploymentConfigItems returns the deploymentConfigs in given namespace
func GetDeploymentConfigItems(clients kube.Clients, namespace string) []interface{} {
deploymentConfigs, err := clients.OpenshiftAppsClient.AppsV1().DeploymentConfigs(namespace).List(meta_v1.ListOptions{})
if err != nil {
logrus.Errorf("Failed to list deploymentConfigs %v", err)
}
return util.InterfaceSlice(deploymentConfigs.Items)
}
// GetDeploymentAnnotations returns the annotations of given deployment
func GetDeploymentAnnotations(item interface{}) map[string]string {
return item.(appsv1.Deployment).ObjectMeta.Annotations
}
// GetDaemonSetAnnotations returns the annotations of given daemonSet
func GetDaemonSetAnnotations(item interface{}) map[string]string {
return item.(appsv1.DaemonSet).ObjectMeta.Annotations
}
// GetStatefulSetAnnotations returns the annotations of given statefulSet
func GetStatefulSetAnnotations(item interface{}) map[string]string {
return item.(appsv1.StatefulSet).ObjectMeta.Annotations
}
// GetDeploymentConfigAnnotations returns the annotations of given deploymentConfig
func GetDeploymentConfigAnnotations(item interface{}) map[string]string {
return item.(openshiftv1.DeploymentConfig).ObjectMeta.Annotations
}
// GetDeploymentPodAnnotations returns the pod's annotations of given deployment
func GetDeploymentPodAnnotations(item interface{}) map[string]string {
return item.(appsv1.Deployment).Spec.Template.ObjectMeta.Annotations
}
// GetDaemonSetPodAnnotations returns the pod's annotations of given daemonSet
func GetDaemonSetPodAnnotations(item interface{}) map[string]string {
return item.(appsv1.DaemonSet).Spec.Template.ObjectMeta.Annotations
}
// GetStatefulSetPodAnnotations returns the pod's annotations of given statefulSet
func GetStatefulSetPodAnnotations(item interface{}) map[string]string {
return item.(appsv1.StatefulSet).Spec.Template.ObjectMeta.Annotations
}
// GetDeploymentConfigPodAnnotations returns the pod's annotations of given deploymentConfig
func GetDeploymentConfigPodAnnotations(item interface{}) map[string]string {
return item.(openshiftv1.DeploymentConfig).Spec.Template.ObjectMeta.Annotations
}
// GetDeploymentContainers returns the containers of given deployment
func GetDeploymentContainers(item interface{}) []v1.Container {
return item.(v1beta1.Deployment).Spec.Template.Spec.Containers
return item.(appsv1.Deployment).Spec.Template.Spec.Containers
}
// GetDaemonSetContainers returns the containers of given daemonset
// GetDaemonSetContainers returns the containers of given daemonSet
func GetDaemonSetContainers(item interface{}) []v1.Container {
return item.(v1beta1.DaemonSet).Spec.Template.Spec.Containers
return item.(appsv1.DaemonSet).Spec.Template.Spec.Containers
}
// GetStatefulsetContainers returns the containers of given statefulSet
func GetStatefulsetContainers(item interface{}) []v1.Container {
return item.(apps_v1beta1.StatefulSet).Spec.Template.Spec.Containers
// GetStatefulSetContainers returns the containers of given statefulSet
func GetStatefulSetContainers(item interface{}) []v1.Container {
return item.(appsv1.StatefulSet).Spec.Template.Spec.Containers
}
// GetDeploymentConfigContainers returns the containers of given deploymentConfig
func GetDeploymentConfigContainers(item interface{}) []v1.Container {
return item.(openshiftv1.DeploymentConfig).Spec.Template.Spec.Containers
}
// GetDeploymentInitContainers returns the containers of given deployment
func GetDeploymentInitContainers(item interface{}) []v1.Container {
return item.(appsv1.Deployment).Spec.Template.Spec.InitContainers
}
// GetDaemonSetInitContainers returns the containers of given daemonSet
func GetDaemonSetInitContainers(item interface{}) []v1.Container {
return item.(appsv1.DaemonSet).Spec.Template.Spec.InitContainers
}
// GetStatefulSetInitContainers returns the containers of given statefulSet
func GetStatefulSetInitContainers(item interface{}) []v1.Container {
return item.(appsv1.StatefulSet).Spec.Template.Spec.InitContainers
}
// GetDeploymentConfigInitContainers returns the containers of given deploymentConfig
func GetDeploymentConfigInitContainers(item interface{}) []v1.Container {
return item.(openshiftv1.DeploymentConfig).Spec.Template.Spec.InitContainers
}
// UpdateDeployment performs rolling upgrade on deployment
func UpdateDeployment(client kubernetes.Interface, namespace string, resource interface{}) error {
deployment := resource.(v1beta1.Deployment)
_, err := client.ExtensionsV1beta1().Deployments(namespace).Update(&deployment)
func UpdateDeployment(clients kube.Clients, namespace string, resource interface{}) error {
deployment := resource.(appsv1.Deployment)
_, err := clients.KubernetesClient.AppsV1().Deployments(namespace).Update(&deployment)
return err
}
// UpdateDaemonSet performs rolling upgrade on daemonSet
func UpdateDaemonSet(client kubernetes.Interface, namespace string, resource interface{}) error {
daemonSet := resource.(v1beta1.DaemonSet)
_, err := client.ExtensionsV1beta1().DaemonSets(namespace).Update(&daemonSet)
func UpdateDaemonSet(clients kube.Clients, namespace string, resource interface{}) error {
daemonSet := resource.(appsv1.DaemonSet)
_, err := clients.KubernetesClient.AppsV1().DaemonSets(namespace).Update(&daemonSet)
return err
}
// UpdateStatefulset performs rolling upgrade on statefulSet
func UpdateStatefulset(client kubernetes.Interface, namespace string, resource interface{}) error {
statefulSet := resource.(apps_v1beta1.StatefulSet)
_, err := client.AppsV1beta1().StatefulSets(namespace).Update(&statefulSet)
// UpdateStatefulSet performs rolling upgrade on statefulSet
func UpdateStatefulSet(clients kube.Clients, namespace string, resource interface{}) error {
statefulSet := resource.(appsv1.StatefulSet)
_, err := clients.KubernetesClient.AppsV1().StatefulSets(namespace).Update(&statefulSet)
return err
}
// UpdateDeploymentConfig performs rolling upgrade on deploymentConfig
func UpdateDeploymentConfig(clients kube.Clients, namespace string, resource interface{}) error {
deploymentConfig := resource.(openshiftv1.DeploymentConfig)
_, err := clients.OpenshiftAppsClient.AppsV1().DeploymentConfigs(namespace).Update(&deploymentConfig)
return err
}
// GetDeploymentVolumes returns the Volumes of given deployment
func GetDeploymentVolumes(item interface{}) []v1.Volume {
return item.(appsv1.Deployment).Spec.Template.Spec.Volumes
}
// GetDaemonSetVolumes returns the Volumes of given daemonSet
func GetDaemonSetVolumes(item interface{}) []v1.Volume {
return item.(appsv1.DaemonSet).Spec.Template.Spec.Volumes
}
// GetStatefulSetVolumes returns the Volumes of given statefulSet
func GetStatefulSetVolumes(item interface{}) []v1.Volume {
return item.(appsv1.StatefulSet).Spec.Template.Spec.Volumes
}
// GetDeploymentConfigVolumes returns the Volumes of given deploymentConfig
func GetDeploymentConfigVolumes(item interface{}) []v1.Volume {
return item.(openshiftv1.DeploymentConfig).Spec.Template.Spec.Volumes
}

View File

@@ -1,13 +1,18 @@
package cmd
import (
"errors"
"fmt"
"os"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/stakater/Reloader/internal/pkg/controller"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
"k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// NewReloaderCommand starts the reloader controller
@@ -17,10 +22,38 @@ func NewReloaderCommand() *cobra.Command {
Short: "A watcher for your Kubernetes cluster",
Run: startReloader,
}
// options
cmd.PersistentFlags().StringVar(&options.ConfigmapUpdateOnChangeAnnotation, "configmap-annotation", "configmap.reloader.stakater.com/reload", "annotation to detect changes in configmaps, specified by name")
cmd.PersistentFlags().StringVar(&options.SecretUpdateOnChangeAnnotation, "secret-annotation", "secret.reloader.stakater.com/reload", "annotation to detect changes in secrets, specified by name")
cmd.PersistentFlags().StringVar(&options.ReloaderAutoAnnotation, "auto-annotation", "reloader.stakater.com/auto", "annotation to detect changes in secrets")
cmd.PersistentFlags().StringVar(&options.AutoSearchAnnotation, "auto-search-annotation", "reloader.stakater.com/search", "annotation to detect changes in configmaps or secrets tagged with special match annotation")
cmd.PersistentFlags().StringVar(&options.SearchMatchAnnotation, "search-match-annotation", "reloader.stakater.com/match", "annotation to mark secrets or configmapts to match the search")
cmd.PersistentFlags().StringVar(&options.LogFormat, "log-format", "", "Log format to use (empty string for text, or JSON")
cmd.PersistentFlags().StringSlice("resources-to-ignore", []string{}, "list of resources to ignore (valid options 'configMaps' or 'secrets')")
cmd.PersistentFlags().StringSlice("namespaces-to-ignore", []string{}, "list of namespaces to ignore")
return cmd
}
func configureLogging(logFormat string) error {
switch logFormat {
case "json":
logrus.SetFormatter(&logrus.JSONFormatter{})
default:
// just let the library use default on empty string.
if logFormat != "" {
return fmt.Errorf("unsupported logging formatter: %q", logFormat)
}
}
return nil
}
func startReloader(cmd *cobra.Command, args []string) {
err := configureLogging(options.LogFormat)
if err != nil {
logrus.Warn(err)
}
logrus.Info("Starting Reloader")
currentNamespace := os.Getenv("KUBERNETES_NAMESPACE")
if len(currentNamespace) == 0 {
@@ -29,13 +62,29 @@ func startReloader(cmd *cobra.Command, args []string) {
}
// create the clientset
clientset, err := kube.GetClient()
clientset, err := kube.GetKubernetesClient()
if err != nil {
logrus.Fatal(err)
}
ignoredResourcesList, err := getIgnoredResourcesList(cmd)
if err != nil {
logrus.Fatal(err)
}
ignoredNamespacesList, err := getIgnoredNamespacesList(cmd)
if err != nil {
logrus.Fatal(err)
}
collectors := metrics.SetupPrometheusEndpoint()
for k := range kube.ResourceMap {
c, err := controller.NewController(clientset, k, currentNamespace)
if ignoredResourcesList.Contains(k) {
continue
}
c, err := controller.NewController(clientset, k, currentNamespace, ignoredNamespacesList, collectors)
if err != nil {
logrus.Fatalf("%s", err)
}
@@ -50,3 +99,36 @@ func startReloader(cmd *cobra.Command, args []string) {
// Wait forever
select {}
}
func getIgnoredNamespacesList(cmd *cobra.Command) (util.List, error) {
return getStringSliceFromFlags(cmd, "namespaces-to-ignore")
}
func getStringSliceFromFlags(cmd *cobra.Command, flag string) ([]string, error) {
slice, err := cmd.Flags().GetStringSlice(flag)
if err != nil {
return nil, err
}
return slice, nil
}
func getIgnoredResourcesList(cmd *cobra.Command) (util.List, error) {
ignoredResourcesList, err := getStringSliceFromFlags(cmd, "resources-to-ignore")
if err != nil {
return nil, err
}
for _, v := range ignoredResourcesList {
if v != "configMaps" && v != "secrets" {
return nil, fmt.Errorf("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not '%s'", v)
}
}
if len(ignoredResourcesList) > 1 {
return nil, errors.New("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not both")
}
return ignoredResourcesList, nil
}

View File

@@ -1,8 +0,0 @@
package constants
const (
// ConfigmapUpdateOnChangeAnnotation is an annotation to detect changes in configmaps
ConfigmapUpdateOnChangeAnnotation = "configmap.reloader.stakater.com/reload"
// SecretUpdateOnChangeAnnotation is an annotation to detect changes in secrets
SecretUpdateOnChangeAnnotation = "secret.reloader.stakater.com/reload"
)

View File

@@ -0,0 +1,15 @@
package constants
// Result is a status for deployment update
type Result int
const (
// Updated is returned when environment variable is created/updated
Updated Result = 1 + iota
// NotUpdated is returned when environment variable is found but had value equals to the new value
NotUpdated
// NoEnvVarFound is returned when no environment variable is found
NoEnvVarFound
// NoContainerFound is returned when no environment variable is found
NoContainerFound
)

View File

@@ -6,6 +6,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/handler"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/runtime"
@@ -13,24 +15,29 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
v1 "k8s.io/api/core/v1"
)
// Controller for checking events
type Controller struct {
client kubernetes.Interface
indexer cache.Indexer
queue workqueue.RateLimitingInterface
informer cache.Controller
namespace string
client kubernetes.Interface
indexer cache.Indexer
queue workqueue.RateLimitingInterface
informer cache.Controller
namespace string
ignoredNamespaces util.List
collectors metrics.Collectors
}
// NewController for initializing a Controller
func NewController(
client kubernetes.Interface, resource string, namespace string) (*Controller, error) {
client kubernetes.Interface, resource string, namespace string, ignoredNamespaces []string, collectors metrics.Collectors) (*Controller, error) {
c := Controller{
client: client,
namespace: namespace,
client: client,
namespace: namespace,
ignoredNamespaces: ignoredNamespaces,
}
queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
@@ -44,27 +51,44 @@ func NewController(
c.indexer = indexer
c.informer = informer
c.queue = queue
c.collectors = collectors
return &c, nil
}
// Add function to add a new object to the queue in case of creating a resource
func (c *Controller) Add(obj interface{}) {
c.queue.Add(handler.ResourceCreatedHandler{
Resource: obj,
})
if !c.resourceInIgnoredNamespace(obj) {
c.queue.Add(handler.ResourceCreatedHandler{
Resource: obj,
Collectors: c.collectors,
})
}
}
func (c *Controller) resourceInIgnoredNamespace(raw interface{}) bool {
switch object := raw.(type) {
case *v1.ConfigMap:
return c.ignoredNamespaces.Contains(object.ObjectMeta.Namespace)
case *v1.Secret:
return c.ignoredNamespaces.Contains(object.ObjectMeta.Namespace)
}
return false
}
// Update function to add an old object and a new object to the queue in case of updating a resource
func (c *Controller) Update(old interface{}, new interface{}) {
c.queue.Add(handler.ResourceUpdatedHandler{
Resource: new,
OldResource: old,
})
if !c.resourceInIgnoredNamespace(new) {
c.queue.Add(handler.ResourceUpdatedHandler{
Resource: new,
OldResource: old,
Collectors: c.collectors,
})
}
}
// Delete function to add an object to the queue in case of deleting a resource
func (c *Controller) Delete(old interface{}) {
logrus.Infof("Resource deletion has been detected but no further implementation found to take action")
// Todo: Any future delete event can be handled here
}
//Run function for controller which handles the queue

File diff suppressed because it is too large Load Diff

View File

@@ -2,17 +2,39 @@ package handler
import (
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/util"
v1 "k8s.io/api/core/v1"
)
// ResourceCreatedHandler contains new objects
type ResourceCreatedHandler struct {
Resource interface{}
Resource interface{}
Collectors metrics.Collectors
}
// Handle processes the newly created resource
func (r ResourceCreatedHandler) Handle() error {
if r.Resource == nil {
logrus.Errorf("Resource creation handler received nil resource")
} else {
config, _ := r.GetConfig()
// process resource based on its type
doRollingUpgrade(config, r.Collectors)
}
return nil
}
// GetConfig gets configurations containing SHA, annotations, namespace and resource name
func (r ResourceCreatedHandler) GetConfig() (util.Config, string) {
var oldSHAData string
var config util.Config
if _, ok := r.Resource.(*v1.ConfigMap); ok {
config = util.GetConfigmapConfig(r.Resource.(*v1.ConfigMap))
} else if _, ok := r.Resource.(*v1.Secret); ok {
config = util.GetSecretConfig(r.Resource.(*v1.Secret))
} else {
logrus.Warnf("Invalid resource: Resource should be 'Secret' or 'Configmap' but found, %v", r.Resource)
}
return config, oldSHAData
}

View File

@@ -1,6 +1,11 @@
package handler
import (
"github.com/stakater/Reloader/internal/pkg/util"
)
// ResourceHandler handles the creation and update of resources
type ResourceHandler interface {
Handle() error
GetConfig() (util.Config, string)
}

View File

@@ -1,23 +1,17 @@
package handler
import (
"sort"
"strings"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/crypto"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
"k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
v1 "k8s.io/api/core/v1"
)
// ResourceUpdatedHandler contains updated objects
type ResourceUpdatedHandler struct {
Resource interface{}
OldResource interface{}
Collectors metrics.Collectors
}
// Handle processes the updated resource
@@ -25,162 +19,27 @@ func (r ResourceUpdatedHandler) Handle() error {
if r.Resource == nil || r.OldResource == nil {
logrus.Errorf("Resource update handler received nil resource")
} else {
config, envVarPostfix, oldSHAData := getConfig(r)
config, oldSHAData := r.GetConfig()
if config.SHAValue != oldSHAData {
logrus.Infof("Changes detected in %s of type '%s' in namespace: %s", config.ResourceName, envVarPostfix, config.Namespace)
// process resource based on its type
rollingUpgrade(r, config, envVarPostfix, callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDeploymentItems,
ContainersFunc: callbacks.GetDeploymentContainers,
UpdateFunc: callbacks.UpdateDeployment,
ResourceType: "Deployment",
})
rollingUpgrade(r, config, envVarPostfix, callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDaemonSetItems,
ContainersFunc: callbacks.GetDaemonSetContainers,
UpdateFunc: callbacks.UpdateDaemonSet,
ResourceType: "DaemonSet",
})
rollingUpgrade(r, config, envVarPostfix, callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetStatefulSetItems,
ContainersFunc: callbacks.GetStatefulsetContainers,
UpdateFunc: callbacks.UpdateStatefulset,
ResourceType: "StatefulSet",
})
doRollingUpgrade(config, r.Collectors)
}
}
return nil
}
func rollingUpgrade(r ResourceUpdatedHandler, config util.Config, envarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) {
client, err := kube.GetClient()
if err != nil {
logrus.Fatalf("Unable to create Kubernetes client error = %v", err)
}
err = PerformRollingUpgrade(client, config, envarPostfix, upgradeFuncs)
if err != nil {
logrus.Errorf("Rolling upgrade for %s failed with error = %v", config.ResourceName, err)
}
}
func getConfig(r ResourceUpdatedHandler) (util.Config, string, string) {
var oldSHAData, envVarPostfix string
// GetConfig gets configurations containing SHA, annotations, namespace and resource name
func (r ResourceUpdatedHandler) GetConfig() (util.Config, string) {
var oldSHAData string
var config util.Config
if _, ok := r.Resource.(*v1.ConfigMap); ok {
oldSHAData = getSHAfromConfigmap(r.OldResource.(*v1.ConfigMap).Data)
config = getConfigmapConfig(r)
envVarPostfix = constants.ConfigmapEnvVarPostfix
oldSHAData = util.GetSHAfromConfigmap(r.OldResource.(*v1.ConfigMap).Data)
config = util.GetConfigmapConfig(r.Resource.(*v1.ConfigMap))
} else if _, ok := r.Resource.(*v1.Secret); ok {
oldSHAData = getSHAfromSecret(r.OldResource.(*v1.Secret).Data)
config = getSecretConfig(r)
envVarPostfix = constants.SecretEnvVarPostfix
oldSHAData = util.GetSHAfromSecret(r.OldResource.(*v1.Secret).Data)
config = util.GetSecretConfig(r.Resource.(*v1.Secret))
} else {
logrus.Warnf("Invalid resource: Resource should be 'Secret' or 'Configmap' but found, %v", r.Resource)
}
return config, envVarPostfix, oldSHAData
}
func getConfigmapConfig(r ResourceUpdatedHandler) util.Config {
configmap := r.Resource.(*v1.ConfigMap)
return util.Config{
Namespace: configmap.Namespace,
ResourceName: configmap.Name,
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
SHAValue: getSHAfromConfigmap(configmap.Data),
}
}
func getSecretConfig(r ResourceUpdatedHandler) util.Config {
secret := r.Resource.(*v1.Secret)
return util.Config{
Namespace: secret.Namespace,
ResourceName: secret.Name,
Annotation: constants.SecretUpdateOnChangeAnnotation,
SHAValue: getSHAfromSecret(secret.Data),
}
}
// PerformRollingUpgrade upgrades the deployment if there is any change in configmap or secret data
func PerformRollingUpgrade(client kubernetes.Interface, config util.Config, envarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) error {
items := upgradeFuncs.ItemsFunc(client, config.Namespace)
var err error
for _, i := range items {
containers := upgradeFuncs.ContainersFunc(i)
resourceName := util.ToObjectMeta(i).Name
// find correct annotation and update the resource
annotationValue := util.ToObjectMeta(i).Annotations[config.Annotation]
if annotationValue != "" {
values := strings.Split(annotationValue, ",")
for _, value := range values {
if value == config.ResourceName {
updated := updateContainers(containers, value, config.SHAValue, envarPostfix)
if !updated {
logrus.Warnf("Rolling upgrade failed because no container found to add environment variable in %s of type %s in namespace: %s", resourceName, upgradeFuncs.ResourceType, config.Namespace)
} else {
err = upgradeFuncs.UpdateFunc(client, config.Namespace, i)
if err != nil {
logrus.Errorf("Update for %s of type %s in namespace %s failed with error %v", resourceName, upgradeFuncs.ResourceType, config.Namespace, err)
} else {
logrus.Infof("Updated %s of type %s in namespace: %s ", resourceName, upgradeFuncs.ResourceType, config.Namespace)
}
break
}
}
}
}
}
return err
}
func updateContainers(containers []v1.Container, annotationValue string, shaData string, envarPostfix string) bool {
updated := false
envar := constants.EnvVarPrefix + util.ConvertToEnvVarName(annotationValue)+ "_" + envarPostfix
for i := range containers {
envs := containers[i].Env
//update if env var exists
updated = updateEnvVar(envs, envar, shaData)
// if no existing env var exists lets create one
if !updated {
e := v1.EnvVar{
Name: envar,
Value: shaData,
}
containers[i].Env = append(containers[i].Env, e)
updated = true
}
}
return updated
}
func updateEnvVar(envs []v1.EnvVar, envar string, shaData string) bool {
for j := range envs {
if envs[j].Name == envar {
if envs[j].Value != shaData {
envs[j].Value = shaData
return true
}
}
}
return false
}
func getSHAfromConfigmap(data map[string]string) string {
values := []string{}
for k, v := range data {
values = append(values, k+"="+v)
}
sort.Strings(values)
return crypto.GenerateSHA(strings.Join(values, ";"))
}
func getSHAfromSecret(data map[string][]byte) string {
values := []string{}
for k, v := range data {
values = append(values, k+"="+string(v[:]))
}
sort.Strings(values)
return crypto.GenerateSHA(strings.Join(values, ";"))
return config, oldSHAData
}

View File

@@ -1,315 +0,0 @@
package handler
import (
"os"
"testing"
"time"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/testutil"
"github.com/stakater/Reloader/internal/pkg/util"
testclient "k8s.io/client-go/kubernetes/fake"
)
var (
client = testclient.NewSimpleClientset()
namespace = "test-handler-" + testutil.RandSeq(5)
configmapName = "testconfigmap-handler-" + testutil.RandSeq(5)
secretName = "testsecret-handler-" + testutil.RandSeq(5)
)
func TestMain(m *testing.M) {
// Creating namespace
testutil.CreateNamespace(namespace, client)
logrus.Infof("Setting up the test resources")
setup()
logrus.Infof("Running Testcases")
retCode := m.Run()
logrus.Infof("tearing down the test resources")
teardown()
os.Exit(retCode)
}
func setup() {
// Creating configmap
_, err := testutil.CreateConfigMap(client, namespace, configmapName, "www.google.com")
if err != nil {
logrus.Errorf("Error in configmap creation: %v", err)
}
// Creating secret
data := "dGVzdFNlY3JldEVuY29kaW5nRm9yUmVsb2FkZXI="
_, err = testutil.CreateSecret(client, namespace, secretName, data)
if err != nil {
logrus.Errorf("Error in secret creation: %v", err)
}
// Creating Deployment with configmap
_, err = testutil.CreateDeployment(client, configmapName, namespace)
if err != nil {
logrus.Errorf("Error in Deployment with configmap creation: %v", err)
}
// Creating Deployment with secret
_, err = testutil.CreateDeployment(client, secretName, namespace)
if err != nil {
logrus.Errorf("Error in Deployment with secret creation: %v", err)
}
// Creating DaemonSet with configmap
_, err = testutil.CreateDaemonSet(client, configmapName, namespace)
if err != nil {
logrus.Errorf("Error in DaemonSet with configmap creation: %v", err)
}
// Creating DaemonSet with secret
_, err = testutil.CreateDaemonSet(client, secretName, namespace)
if err != nil {
logrus.Errorf("Error in DaemonSet with secret creation: %v", err)
}
// Creating StatefulSet with configmap
_, err = testutil.CreateStatefulSet(client, configmapName, namespace)
if err != nil {
logrus.Errorf("Error in StatefulSet with configmap creation: %v", err)
}
// Creating StatefulSet with secret
_, err = testutil.CreateStatefulSet(client, secretName, namespace)
if err != nil {
logrus.Errorf("Error in StatefulSet with secret creation: %v", err)
}
}
func teardown() {
// Deleting Deployment with configmap
deploymentError := testutil.DeleteDeployment(client, namespace, configmapName)
if deploymentError != nil {
logrus.Errorf("Error while deleting deployment with configmap %v", deploymentError)
}
// Deleting Deployment with secret
deploymentError = testutil.DeleteDeployment(client, namespace, secretName)
if deploymentError != nil {
logrus.Errorf("Error while deleting deployment with secret %v", deploymentError)
}
// Deleting DaemonSet with configmap
daemonSetError := testutil.DeleteDaemonSet(client, namespace, configmapName)
if daemonSetError != nil {
logrus.Errorf("Error while deleting daemonSet with configmap %v", daemonSetError)
}
// Deleting Deployment with secret
daemonSetError = testutil.DeleteDaemonSet(client, namespace, secretName)
if daemonSetError != nil {
logrus.Errorf("Error while deleting daemonSet with secret %v", daemonSetError)
}
// Deleting StatefulSet with configmap
statefulSetError := testutil.DeleteStatefulSet(client, namespace, configmapName)
if statefulSetError != nil {
logrus.Errorf("Error while deleting statefulSet with configmap %v", statefulSetError)
}
// Deleting Deployment with secret
statefulSetError = testutil.DeleteStatefulSet(client, namespace, secretName)
if statefulSetError != nil {
logrus.Errorf("Error while deleting statefulSet with secret %v", statefulSetError)
}
// Deleting Configmap
err := testutil.DeleteConfigMap(client, namespace, configmapName)
if err != nil {
logrus.Errorf("Error while deleting the configmap %v", err)
}
// Deleting Secret
err = testutil.DeleteSecret(client, namespace, secretName)
if err != nil {
logrus.Errorf("Error while deleting the secret %v", err)
}
// Deleting namespace
testutil.DeleteNamespace(namespace, client)
}
func TestRollingUpgradeForDeploymentWithConfigmap(t *testing.T) {
shaData := testutil.ConvertResourceToSHA(testutil.SecretResourceType, namespace, configmapName, "www.stakater.com")
config := util.Config{
Namespace: namespace,
ResourceName: configmapName,
SHAValue: shaData,
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
}
deploymentFuncs := callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDeploymentItems,
ContainersFunc: callbacks.GetDeploymentContainers,
UpdateFunc: callbacks.UpdateDeployment,
ResourceType: "Deployment",
}
err := PerformRollingUpgrade(client, config, constants.ConfigmapEnvVarPostfix, deploymentFuncs)
time.Sleep(5 * time.Second)
if err != nil {
t.Errorf("Rolling upgrade failed for Deployment with Configmap")
}
logrus.Infof("Verifying deployment update")
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, deploymentFuncs)
if !updated {
t.Errorf("Deployment was not updated")
}
}
func TestRollingUpgradeForDeploymentWithSecret(t *testing.T) {
shaData := testutil.ConvertResourceToSHA(testutil.SecretResourceType, namespace, secretName, "dGVzdFVwZGF0ZWRTZWNyZXRFbmNvZGluZ0ZvclJlbG9hZGVy")
config := util.Config{
Namespace: namespace,
ResourceName: secretName,
SHAValue: shaData,
Annotation: constants.SecretUpdateOnChangeAnnotation,
}
deploymentFuncs := callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDeploymentItems,
ContainersFunc: callbacks.GetDeploymentContainers,
UpdateFunc: callbacks.UpdateDeployment,
ResourceType: "Deployment",
}
err := PerformRollingUpgrade(client, config, constants.SecretEnvVarPostfix, deploymentFuncs)
time.Sleep(5 * time.Second)
if err != nil {
t.Errorf("Rolling upgrade failed for Deployment with Secret")
}
logrus.Infof("Verifying deployment update")
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, deploymentFuncs)
if !updated {
t.Errorf("Deployment was not updated")
}
}
func TestRollingUpgradeForDaemonSetWithConfigmap(t *testing.T) {
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapName, "www.facebook.com")
config := util.Config{
Namespace: namespace,
ResourceName: configmapName,
SHAValue: shaData,
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
}
daemonSetFuncs := callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDaemonSetItems,
ContainersFunc: callbacks.GetDaemonSetContainers,
UpdateFunc: callbacks.UpdateDaemonSet,
ResourceType: "DaemonSet",
}
err := PerformRollingUpgrade(client, config, constants.ConfigmapEnvVarPostfix, daemonSetFuncs)
time.Sleep(5 * time.Second)
if err != nil {
t.Errorf("Rolling upgrade failed for DaemonSet with configmap")
}
logrus.Infof("Verifying daemonSet update")
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, daemonSetFuncs)
if !updated {
t.Errorf("DaemonSet was not updated")
}
}
func TestRollingUpgradeForDaemonSetWithSecret(t *testing.T) {
shaData := testutil.ConvertResourceToSHA(testutil.SecretResourceType, namespace, secretName, "d3d3LmZhY2Vib29rLmNvbQ==")
config := util.Config{
Namespace: namespace,
ResourceName: secretName,
SHAValue: shaData,
Annotation: constants.SecretUpdateOnChangeAnnotation,
}
daemonSetFuncs := callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDaemonSetItems,
ContainersFunc: callbacks.GetDaemonSetContainers,
UpdateFunc: callbacks.UpdateDaemonSet,
ResourceType: "DaemonSet",
}
err := PerformRollingUpgrade(client, config, constants.SecretEnvVarPostfix, daemonSetFuncs)
time.Sleep(5 * time.Second)
if err != nil {
t.Errorf("Rolling upgrade failed for DaemonSet with secret")
}
logrus.Infof("Verifying daemonSet update")
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, daemonSetFuncs)
if !updated {
t.Errorf("DaemonSet was not updated")
}
}
func TestRollingUpgradeForStatefulSetWithConfigmap(t *testing.T) {
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapName, "www.twitter.com")
config := util.Config{
Namespace: namespace,
ResourceName: configmapName,
SHAValue: shaData,
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
}
statefulSetFuncs := callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetStatefulSetItems,
ContainersFunc: callbacks.GetStatefulsetContainers,
UpdateFunc: callbacks.UpdateStatefulset,
ResourceType: "StatefulSet",
}
err := PerformRollingUpgrade(client, config, constants.ConfigmapEnvVarPostfix, statefulSetFuncs)
time.Sleep(5 * time.Second)
if err != nil {
t.Errorf("Rolling upgrade failed for StatefulSet with configmap")
}
logrus.Infof("Verifying statefulSet update")
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, statefulSetFuncs)
if !updated {
t.Errorf("StatefulSet was not updated")
}
}
func TestRollingUpgradeForStatefulSetWithSecret(t *testing.T) {
shaData := testutil.ConvertResourceToSHA(testutil.SecretResourceType, namespace, secretName, "d3d3LnR3aXR0ZXIuY29t")
config := util.Config{
Namespace: namespace,
ResourceName: secretName,
SHAValue: shaData,
Annotation: constants.SecretUpdateOnChangeAnnotation,
}
statefulSetFuncs := callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetStatefulSetItems,
ContainersFunc: callbacks.GetStatefulsetContainers,
UpdateFunc: callbacks.UpdateStatefulset,
ResourceType: "StatefulSet",
}
err := PerformRollingUpgrade(client, config, constants.SecretEnvVarPostfix, statefulSetFuncs)
time.Sleep(5 * time.Second)
if err != nil {
t.Errorf("Rolling upgrade failed for StatefulSet with secret")
}
logrus.Infof("Verifying statefulSet update")
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, statefulSetFuncs)
if !updated {
t.Errorf("StatefulSet was not updated")
}
}

View File

@@ -0,0 +1,299 @@
package handler
import (
"strconv"
"strings"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
v1 "k8s.io/api/core/v1"
)
// GetDeploymentRollingUpgradeFuncs returns all callback funcs for a deployment
func GetDeploymentRollingUpgradeFuncs() callbacks.RollingUpgradeFuncs {
return callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDeploymentItems,
AnnotationsFunc: callbacks.GetDeploymentAnnotations,
PodAnnotationsFunc: callbacks.GetDeploymentPodAnnotations,
ContainersFunc: callbacks.GetDeploymentContainers,
InitContainersFunc: callbacks.GetDeploymentInitContainers,
UpdateFunc: callbacks.UpdateDeployment,
VolumesFunc: callbacks.GetDeploymentVolumes,
ResourceType: "Deployment",
}
}
// GetDaemonSetRollingUpgradeFuncs returns all callback funcs for a daemonset
func GetDaemonSetRollingUpgradeFuncs() callbacks.RollingUpgradeFuncs {
return callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDaemonSetItems,
AnnotationsFunc: callbacks.GetDaemonSetAnnotations,
PodAnnotationsFunc: callbacks.GetDaemonSetPodAnnotations,
ContainersFunc: callbacks.GetDaemonSetContainers,
InitContainersFunc: callbacks.GetDaemonSetInitContainers,
UpdateFunc: callbacks.UpdateDaemonSet,
VolumesFunc: callbacks.GetDaemonSetVolumes,
ResourceType: "DaemonSet",
}
}
// GetStatefulSetRollingUpgradeFuncs returns all callback funcs for a statefulSet
func GetStatefulSetRollingUpgradeFuncs() callbacks.RollingUpgradeFuncs {
return callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetStatefulSetItems,
AnnotationsFunc: callbacks.GetStatefulSetAnnotations,
PodAnnotationsFunc: callbacks.GetStatefulSetPodAnnotations,
ContainersFunc: callbacks.GetStatefulSetContainers,
InitContainersFunc: callbacks.GetStatefulSetInitContainers,
UpdateFunc: callbacks.UpdateStatefulSet,
VolumesFunc: callbacks.GetStatefulSetVolumes,
ResourceType: "StatefulSet",
}
}
// GetDeploymentConfigRollingUpgradeFuncs returns all callback funcs for a deploymentConfig
func GetDeploymentConfigRollingUpgradeFuncs() callbacks.RollingUpgradeFuncs {
return callbacks.RollingUpgradeFuncs{
ItemsFunc: callbacks.GetDeploymentConfigItems,
AnnotationsFunc: callbacks.GetDeploymentConfigAnnotations,
PodAnnotationsFunc: callbacks.GetDeploymentConfigPodAnnotations,
ContainersFunc: callbacks.GetDeploymentConfigContainers,
InitContainersFunc: callbacks.GetDeploymentConfigInitContainers,
UpdateFunc: callbacks.UpdateDeploymentConfig,
VolumesFunc: callbacks.GetDeploymentConfigVolumes,
ResourceType: "DeploymentConfig",
}
}
func doRollingUpgrade(config util.Config, collectors metrics.Collectors) {
clients := kube.GetClients()
rollingUpgrade(clients, config, GetDeploymentRollingUpgradeFuncs(), collectors)
rollingUpgrade(clients, config, GetDaemonSetRollingUpgradeFuncs(), collectors)
rollingUpgrade(clients, config, GetStatefulSetRollingUpgradeFuncs(), collectors)
if kube.IsOpenshift {
rollingUpgrade(clients, config, GetDeploymentConfigRollingUpgradeFuncs(), collectors)
}
}
func rollingUpgrade(clients kube.Clients, config util.Config, upgradeFuncs callbacks.RollingUpgradeFuncs, collectors metrics.Collectors) {
err := PerformRollingUpgrade(clients, config, upgradeFuncs, collectors)
if err != nil {
logrus.Errorf("Rolling upgrade for '%s' failed with error = %v", config.ResourceName, err)
}
}
// PerformRollingUpgrade upgrades the deployment if there is any change in configmap or secret data
func PerformRollingUpgrade(clients kube.Clients, config util.Config, upgradeFuncs callbacks.RollingUpgradeFuncs, collectors metrics.Collectors) error {
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
var err error
for _, i := range items {
// find correct annotation and update the resource
annotations := upgradeFuncs.AnnotationsFunc(i)
annotationValue, found := annotations[config.Annotation]
searchAnnotationValue, foundSearchAnn := annotations[options.AutoSearchAnnotation]
reloaderEnabledValue, foundAuto := annotations[options.ReloaderAutoAnnotation]
if !found && !foundAuto && !foundSearchAnn {
annotations = upgradeFuncs.PodAnnotationsFunc(i)
annotationValue = annotations[config.Annotation]
searchAnnotationValue = annotations[options.AutoSearchAnnotation]
reloaderEnabledValue = annotations[options.ReloaderAutoAnnotation]
}
result := constants.NotUpdated
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
if err == nil && reloaderEnabled {
result = updateContainers(upgradeFuncs, i, config, true)
}
if result != constants.Updated && annotationValue != "" {
values := strings.Split(annotationValue, ",")
for _, value := range values {
if value == config.ResourceName {
result = updateContainers(upgradeFuncs, i, config, false)
if result == constants.Updated {
break
}
}
}
}
if result != constants.Updated && searchAnnotationValue == "true" {
matchAnnotationValue := config.ResourceAnnotations[options.SearchMatchAnnotation]
if matchAnnotationValue == "true" {
result = updateContainers(upgradeFuncs, i, config, true)
}
}
if result == constants.Updated {
err = upgradeFuncs.UpdateFunc(clients, config.Namespace, i)
resourceName := util.ToObjectMeta(i).Name
if err != nil {
logrus.Errorf("Update for '%s' of type '%s' in namespace '%s' failed with error %v", resourceName, upgradeFuncs.ResourceType, config.Namespace, err)
collectors.Reloaded.With(prometheus.Labels{"success": "false"}).Inc()
} else {
logrus.Infof("Changes detected in '%s' of type '%s' in namespace '%s'", config.ResourceName, config.Type, config.Namespace)
logrus.Infof("Updated '%s' of type '%s' in namespace '%s'", resourceName, upgradeFuncs.ResourceType, config.Namespace)
collectors.Reloaded.With(prometheus.Labels{"success": "true"}).Inc()
}
}
}
return err
}
func getVolumeMountName(volumes []v1.Volume, mountType string, volumeName string) string {
for i := range volumes {
if mountType == constants.ConfigmapEnvVarPostfix {
if volumes[i].ConfigMap != nil && volumes[i].ConfigMap.Name == volumeName {
return volumes[i].Name
}
if volumes[i].Projected != nil {
for j := range volumes[i].Projected.Sources {
if volumes[i].Projected.Sources[j].ConfigMap != nil && volumes[i].Projected.Sources[j].ConfigMap.Name == volumeName {
return volumes[i].Name
}
}
}
} else if mountType == constants.SecretEnvVarPostfix {
if volumes[i].Secret != nil && volumes[i].Secret.SecretName == volumeName {
return volumes[i].Name
}
if volumes[i].Projected != nil {
for j := range volumes[i].Projected.Sources {
if volumes[i].Projected.Sources[j].Secret != nil && volumes[i].Projected.Sources[j].Secret.Name == volumeName {
return volumes[i].Name
}
}
}
}
}
return ""
}
func getContainerWithVolumeMount(containers []v1.Container, volumeMountName string) *v1.Container {
for i := range containers {
volumeMounts := containers[i].VolumeMounts
for j := range volumeMounts {
if volumeMounts[j].Name == volumeMountName {
return &containers[i]
}
}
}
return nil
}
func getContainerWithEnvReference(containers []v1.Container, resourceName string, resourceType string) *v1.Container {
for i := range containers {
envs := containers[i].Env
for j := range envs {
envVarSource := envs[j].ValueFrom
if envVarSource != nil {
if resourceType == constants.SecretEnvVarPostfix && envVarSource.SecretKeyRef != nil && envVarSource.SecretKeyRef.LocalObjectReference.Name == resourceName {
return &containers[i]
} else if resourceType == constants.ConfigmapEnvVarPostfix && envVarSource.ConfigMapKeyRef != nil && envVarSource.ConfigMapKeyRef.LocalObjectReference.Name == resourceName {
return &containers[i]
}
}
}
envsFrom := containers[i].EnvFrom
for j := range envsFrom {
if resourceType == constants.SecretEnvVarPostfix && envsFrom[j].SecretRef != nil && envsFrom[j].SecretRef.LocalObjectReference.Name == resourceName {
return &containers[i]
} else if resourceType == constants.ConfigmapEnvVarPostfix && envsFrom[j].ConfigMapRef != nil && envsFrom[j].ConfigMapRef.LocalObjectReference.Name == resourceName {
return &containers[i]
}
}
}
return nil
}
func getContainerToUpdate(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) *v1.Container {
volumes := upgradeFuncs.VolumesFunc(item)
containers := upgradeFuncs.ContainersFunc(item)
initContainers := upgradeFuncs.InitContainersFunc(item)
var container *v1.Container
// Get the volumeMountName to find volumeMount in container
volumeMountName := getVolumeMountName(volumes, config.Type, config.ResourceName)
// Get the container with mounted configmap/secret
if volumeMountName != "" {
container = getContainerWithVolumeMount(containers, volumeMountName)
if container == nil && len(initContainers) > 0 {
container = getContainerWithVolumeMount(initContainers, volumeMountName)
if container != nil {
// if configmap/secret is being used in init container then return the first Pod container to save reloader env
return &containers[0]
}
} else if container != nil {
return container
}
}
// Get the container with referenced secret or configmap as env var
container = getContainerWithEnvReference(containers, config.ResourceName, config.Type)
if container == nil && len(initContainers) > 0 {
container = getContainerWithEnvReference(initContainers, config.ResourceName, config.Type)
if container != nil {
// if configmap/secret is being used in init container then return the first Pod container to save reloader env
return &containers[0]
}
}
// Get the first container if the annotation is related to specified configmap or secret i.e. configmap.reloader.stakater.com/reload
if container == nil && !autoReload {
return &containers[0]
}
return container
}
func updateContainers(upgradeFuncs callbacks.RollingUpgradeFuncs, item interface{}, config util.Config, autoReload bool) constants.Result {
var result constants.Result
envar := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + config.Type
container := getContainerToUpdate(upgradeFuncs, item, config, autoReload)
if container == nil {
return constants.NoContainerFound
}
//update if env var exists
result = updateEnvVar(upgradeFuncs.ContainersFunc(item), envar, config.SHAValue)
// if no existing env var exists lets create one
if result == constants.NoEnvVarFound {
e := v1.EnvVar{
Name: envar,
Value: config.SHAValue,
}
container.Env = append(container.Env, e)
result = constants.Updated
}
return result
}
func updateEnvVar(containers []v1.Container, envar string, shaData string) constants.Result {
for i := range containers {
envs := containers[i].Env
for j := range envs {
if envs[j].Name == envar {
if envs[j].Value != shaData {
envs[j].Value = shaData
return constants.Updated
}
return constants.NotUpdated
}
}
}
return constants.NoEnvVarFound
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
"net/http"
)
type Collectors struct {
Reloaded *prometheus.CounterVec
}
func NewCollectors() Collectors {
reloaded := prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: "reloader",
Name: "reload_executed_total",
Help: "Counter of reloads executed by Reloader.",
},
[]string{"success"},
)
//set 0 as default value
reloaded.With(prometheus.Labels{"success": "true"}).Add(0)
reloaded.With(prometheus.Labels{"success": "false"}).Add(0)
return Collectors{
Reloaded: reloaded,
}
}
func SetupPrometheusEndpoint() Collectors {
collectors := NewCollectors()
prometheus.MustRegister(collectors.Reloaded)
go func() {
http.Handle("/metrics", promhttp.Handler())
logrus.Fatal(http.ListenAndServe(":9090", nil))
}()
return collectors
}

View File

@@ -0,0 +1,20 @@
package options
var (
// ConfigmapUpdateOnChangeAnnotation is an annotation to detect changes in
// configmaps specified by name
ConfigmapUpdateOnChangeAnnotation = "configmap.reloader.stakater.com/reload"
// SecretUpdateOnChangeAnnotation is an annotation to detect changes in
// secrets specified by name
SecretUpdateOnChangeAnnotation = "secret.reloader.stakater.com/reload"
// ReloaderAutoAnnotation is an annotation to detect changes in secrets
ReloaderAutoAnnotation = "reloader.stakater.com/auto"
// AutoSearchAnnotation is an annotation to detect changes in
// configmaps or triggers with the SearchMatchAnnotation
AutoSearchAnnotation = "reloader.stakater.com/search"
// SearchMatchAnnotation is an annotation to tag secrets to be found with
// AutoSearchAnnotation
SearchMatchAnnotation = "reloader.stakater.com/match"
// LogFormat is the log format to use (json, or empty string for default)
LogFormat = ""
)

View File

@@ -3,18 +3,21 @@ package testutil
import (
"math/rand"
"sort"
"strconv"
"strings"
"time"
openshiftv1 "github.com/openshift/api/apps/v1"
appsclient "github.com/openshift/client-go/apps/clientset/versioned"
"github.com/sirupsen/logrus"
"github.com/stakater/Reloader/internal/pkg/callbacks"
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/crypto"
"github.com/stakater/Reloader/internal/pkg/options"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
v1_beta1 "k8s.io/api/apps/v1beta1"
"k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
core_v1 "k8s.io/client-go/kubernetes/typed/core/v1"
@@ -28,19 +31,11 @@ var (
SecretResourceType = "secrets"
)
func GetClient() *kubernetes.Clientset {
newClient, err := kube.GetClient()
if err != nil {
logrus.Fatalf("Unable to create Kubernetes client error = %v", err)
}
return newClient
}
// CreateNamespace creates namespace for testing
func CreateNamespace(namespace string, client kubernetes.Interface) {
_, err := client.CoreV1().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}})
if err != nil {
logrus.Fatalf("Failed to create namespace for testing", err)
logrus.Fatalf("Failed to create namespace for testing %v", err)
} else {
logrus.Infof("Creating namespace for testing = %s", namespace)
}
@@ -50,42 +45,161 @@ func CreateNamespace(namespace string, client kubernetes.Interface) {
func DeleteNamespace(namespace string, client kubernetes.Interface) {
err := client.CoreV1().Namespaces().Delete(namespace, &metav1.DeleteOptions{})
if err != nil {
logrus.Fatalf("Failed to delete namespace that was created for testing", err)
logrus.Fatalf("Failed to delete namespace that was created for testing %v", err)
} else {
logrus.Infof("Deleting namespace for testing = %s", namespace)
}
}
// GetDeployment provides deployment for testing
func GetDeployment(namespace string, deploymentName string) *v1beta1.Deployment {
replicaset := int32(1)
return &v1beta1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: deploymentName,
Namespace: namespace,
Labels: map[string]string{"firstLabel": "temp"},
Annotations: map[string]string{
constants.ConfigmapUpdateOnChangeAnnotation: deploymentName,
constants.SecretUpdateOnChangeAnnotation: deploymentName},
},
Spec: v1beta1.DeploymentSpec{
Replicas: &replicaset,
Strategy: v1beta1.DeploymentStrategy{
Type: v1beta1.RollingUpdateDeploymentStrategyType,
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"secondLabel": "temp"},
func getObjectMeta(namespace string, name string, autoReload bool) metav1.ObjectMeta {
return metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: map[string]string{"firstLabel": "temp"},
Annotations: getAnnotations(name, autoReload),
}
}
func getAnnotations(name string, autoReload bool) map[string]string {
if autoReload {
return map[string]string{
options.ReloaderAutoAnnotation: "true"}
}
return map[string]string{
options.ConfigmapUpdateOnChangeAnnotation: name,
options.SecretUpdateOnChangeAnnotation: name}
}
func getEnvVarSources(name string) []v1.EnvFromSource {
return []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
Spec: v1.PodSpec{
Containers: []v1.Container{
},
},
{
SecretRef: &v1.SecretEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
},
},
}
}
func getVolumes(name string) []v1.Volume {
return []v1.Volume{
{
Name: "projectedconfigmap",
VolumeSource: v1.VolumeSource{
Projected: &v1.ProjectedVolumeSource{
Sources: []v1.VolumeProjection{
v1.VolumeProjection{
ConfigMap: &v1.ConfigMapProjection{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
},
},
},
},
},
},
{
Name: "projectedsecret",
VolumeSource: v1.VolumeSource{
Projected: &v1.ProjectedVolumeSource{
Sources: []v1.VolumeProjection{
v1.VolumeProjection{
Secret: &v1.SecretProjection{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
},
},
},
},
},
},
{
Name: "configmap",
VolumeSource: v1.VolumeSource{
ConfigMap: &v1.ConfigMapVolumeSource{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
},
},
},
{
Name: "secret",
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: name,
},
},
},
}
}
func getVolumeMounts(name string) []v1.VolumeMount {
return []v1.VolumeMount{
{
MountPath: "etc/config",
Name: "configmap",
},
{
MountPath: "etc/sec",
Name: "secret",
},
{
MountPath: "etc/projectedconfig",
Name: "projectedconfigmap",
},
{
MountPath: "etc/projectedsec",
Name: "projectedsecret",
},
}
}
func getPodTemplateSpecWithEnvVars(name string) v1.PodTemplateSpec {
return v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"secondLabel": "temp"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Image: "tutum/hello-world",
Name: name,
Env: []v1.EnvVar{
{
Image: "tutum/hello-world",
Name: deploymentName,
Env: []v1.EnvVar{
{
Name: "BUCKET_NAME",
Value: "test",
Name: "BUCKET_NAME",
Value: "test",
},
{
Name: "CONFIGMAP_" + util.ConvertToEnvVarName(name),
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
Key: "test.url",
},
},
},
{
Name: "SECRET_" + util.ConvertToEnvVarName(name),
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: name,
},
Key: "test.url",
},
},
},
@@ -96,78 +210,306 @@ func GetDeployment(namespace string, deploymentName string) *v1beta1.Deployment
}
}
// GetDaemonSet provides daemonset for testing
func GetDaemonSet(namespace string, daemonsetName string) *v1beta1.DaemonSet {
return &v1beta1.DaemonSet{
func getPodTemplateSpecWithEnvVarSources(name string) v1.PodTemplateSpec {
return v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: daemonsetName,
Namespace: namespace,
Labels: map[string]string{"firstLabel": "temp"},
Annotations: map[string]string{
constants.ConfigmapUpdateOnChangeAnnotation: daemonsetName,
constants.SecretUpdateOnChangeAnnotation: daemonsetName},
Labels: map[string]string{"secondLabel": "temp"},
},
Spec: v1beta1.DaemonSetSpec{
UpdateStrategy: v1beta1.DaemonSetUpdateStrategy{
Type: v1beta1.RollingUpdateDaemonSetStrategyType,
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"secondLabel": "temp"},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Image: "tutum/hello-world",
Name: name,
EnvFrom: getEnvVarSources(name),
},
Spec: v1.PodSpec{
Containers: []v1.Container{
},
},
}
}
func getPodTemplateSpecWithVolumes(name string) v1.PodTemplateSpec {
return v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"secondLabel": "temp"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Image: "tutum/hello-world",
Name: name,
Env: []v1.EnvVar{
{
Image: "tutum/hello-world",
Name: daemonsetName,
Env: []v1.EnvVar{
{
Name: "BUCKET_NAME",
Value: "test",
},
},
Name: "BUCKET_NAME",
Value: "test",
},
},
VolumeMounts: getVolumeMounts(name),
},
},
Volumes: getVolumes(name),
},
}
}
func getPodTemplateSpecWithInitContainer(name string) v1.PodTemplateSpec {
return v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"secondLabel": "temp"},
},
Spec: v1.PodSpec{
InitContainers: []v1.Container{
{
Image: "busybox",
Name: "busyBox",
VolumeMounts: getVolumeMounts(name),
},
},
Containers: []v1.Container{
{
Image: "tutum/hello-world",
Name: name,
Env: []v1.EnvVar{
{
Name: "BUCKET_NAME",
Value: "test",
},
},
},
},
Volumes: getVolumes(name),
},
}
}
func getPodTemplateSpecWithInitContainerAndEnv(name string) v1.PodTemplateSpec {
return v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"secondLabel": "temp"},
},
Spec: v1.PodSpec{
InitContainers: []v1.Container{
{
Image: "busybox",
Name: "busyBox",
EnvFrom: getEnvVarSources(name),
},
},
Containers: []v1.Container{
{
Image: "tutum/hello-world",
Name: name,
Env: []v1.EnvVar{
{
Name: "BUCKET_NAME",
Value: "test",
},
},
},
},
},
}
}
// GetDeployment provides deployment for testing
func GetDeployment(namespace string, deploymentName string) *appsv1.Deployment {
replicaset := int32(1)
return &appsv1.Deployment{
ObjectMeta: getObjectMeta(namespace, deploymentName, false),
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
Replicas: &replicaset,
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
Template: getPodTemplateSpecWithVolumes(deploymentName),
},
}
}
// GetDeploymentConfig provides deployment for testing
func GetDeploymentConfig(namespace string, deploymentConfigName string) *openshiftv1.DeploymentConfig {
replicaset := int32(1)
podTemplateSpecWithVolume := getPodTemplateSpecWithVolumes(deploymentConfigName)
return &openshiftv1.DeploymentConfig{
ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false),
Spec: openshiftv1.DeploymentConfigSpec{
Replicas: replicaset,
Strategy: openshiftv1.DeploymentStrategy{
Type: openshiftv1.DeploymentStrategyTypeRolling,
},
Template: &podTemplateSpecWithVolume,
},
}
}
// GetDeploymentWithInitContainer provides deployment with init container and volumeMounts
func GetDeploymentWithInitContainer(namespace string, deploymentName string) *appsv1.Deployment {
replicaset := int32(1)
return &appsv1.Deployment{
ObjectMeta: getObjectMeta(namespace, deploymentName, false),
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
Replicas: &replicaset,
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
Template: getPodTemplateSpecWithInitContainer(deploymentName),
},
}
}
// GetDeploymentWithInitContainerAndEnv provides deployment with init container and EnvSource
func GetDeploymentWithInitContainerAndEnv(namespace string, deploymentName string) *appsv1.Deployment {
replicaset := int32(1)
return &appsv1.Deployment{
ObjectMeta: getObjectMeta(namespace, deploymentName, true),
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
Replicas: &replicaset,
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
Template: getPodTemplateSpecWithInitContainerAndEnv(deploymentName),
},
}
}
func GetDeploymentWithEnvVars(namespace string, deploymentName string) *appsv1.Deployment {
replicaset := int32(1)
return &appsv1.Deployment{
ObjectMeta: getObjectMeta(namespace, deploymentName, true),
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
Replicas: &replicaset,
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
Template: getPodTemplateSpecWithEnvVars(deploymentName),
},
}
}
func GetDeploymentConfigWithEnvVars(namespace string, deploymentConfigName string) *openshiftv1.DeploymentConfig {
replicaset := int32(1)
podTemplateSpecWithEnvVars := getPodTemplateSpecWithEnvVars(deploymentConfigName)
return &openshiftv1.DeploymentConfig{
ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false),
Spec: openshiftv1.DeploymentConfigSpec{
Replicas: replicaset,
Strategy: openshiftv1.DeploymentStrategy{
Type: openshiftv1.DeploymentStrategyTypeRolling,
},
Template: &podTemplateSpecWithEnvVars,
},
}
}
func GetDeploymentWithEnvVarSources(namespace string, deploymentName string) *appsv1.Deployment {
replicaset := int32(1)
return &appsv1.Deployment{
ObjectMeta: getObjectMeta(namespace, deploymentName, true),
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
Replicas: &replicaset,
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
Template: getPodTemplateSpecWithEnvVarSources(deploymentName),
},
}
}
func GetDeploymentWithPodAnnotations(namespace string, deploymentName string, both bool) *appsv1.Deployment {
replicaset := int32(1)
deployment := &appsv1.Deployment{
ObjectMeta: getObjectMeta(namespace, deploymentName, false),
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
Replicas: &replicaset,
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
Template: getPodTemplateSpecWithEnvVarSources(deploymentName),
},
}
if !both {
deployment.ObjectMeta.Annotations = nil
}
deployment.Spec.Template.ObjectMeta.Annotations = getAnnotations(deploymentName, true)
return deployment
}
// GetDaemonSet provides daemonset for testing
func GetDaemonSet(namespace string, daemonsetName string) *appsv1.DaemonSet {
return &appsv1.DaemonSet{
ObjectMeta: getObjectMeta(namespace, daemonsetName, false),
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
UpdateStrategy: appsv1.DaemonSetUpdateStrategy{
Type: appsv1.RollingUpdateDaemonSetStrategyType,
},
Template: getPodTemplateSpecWithVolumes(daemonsetName),
},
}
}
func GetDaemonSetWithEnvVars(namespace string, daemonSetName string) *appsv1.DaemonSet {
return &appsv1.DaemonSet{
ObjectMeta: getObjectMeta(namespace, daemonSetName, true),
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
UpdateStrategy: appsv1.DaemonSetUpdateStrategy{
Type: appsv1.RollingUpdateDaemonSetStrategyType,
},
Template: getPodTemplateSpecWithEnvVars(daemonSetName),
},
}
}
// GetStatefulSet provides statefulset for testing
func GetStatefulSet(namespace string, statefulsetName string) *v1_beta1.StatefulSet {
return &v1_beta1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: statefulsetName,
Namespace: namespace,
Labels: map[string]string{"firstLabel": "temp"},
Annotations: map[string]string{
constants.ConfigmapUpdateOnChangeAnnotation: statefulsetName,
constants.SecretUpdateOnChangeAnnotation: statefulsetName},
func GetStatefulSet(namespace string, statefulsetName string) *appsv1.StatefulSet {
return &appsv1.StatefulSet{
ObjectMeta: getObjectMeta(namespace, statefulsetName, false),
Spec: appsv1.StatefulSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
UpdateStrategy: appsv1.StatefulSetUpdateStrategy{
Type: appsv1.RollingUpdateStatefulSetStrategyType,
},
Template: getPodTemplateSpecWithVolumes(statefulsetName),
},
Spec: v1_beta1.StatefulSetSpec{
UpdateStrategy: v1_beta1.StatefulSetUpdateStrategy{
Type: v1_beta1.RollingUpdateStatefulSetStrategyType,
}
}
// GetStatefulSet provides statefulset for testing
func GetStatefulSetWithEnvVar(namespace string, statefulsetName string) *appsv1.StatefulSet {
return &appsv1.StatefulSet{
ObjectMeta: getObjectMeta(namespace, statefulsetName, true),
Spec: appsv1.StatefulSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"secondLabel": "temp"},
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"secondLabel": "temp"},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Image: "tutum/hello-world",
Name: statefulsetName,
Env: []v1.EnvVar{
{
Name: "BUCKET_NAME",
Value: "test",
},
},
},
},
},
UpdateStrategy: appsv1.StatefulSetUpdateStrategy{
Type: appsv1.RollingUpdateStatefulSetStrategyType,
},
Template: getPodTemplateSpecWithEnvVars(statefulsetName),
},
}
}
@@ -256,7 +598,7 @@ func CreateConfigMap(client kubernetes.Interface, namespace string, configmapNam
logrus.Infof("Creating configmap")
configmapClient := client.CoreV1().ConfigMaps(namespace)
_, err := configmapClient.Create(GetConfigmap(namespace, configmapName, data))
time.Sleep(10 * time.Second)
time.Sleep(3 * time.Second)
return configmapClient, err
}
@@ -265,58 +607,146 @@ func CreateSecret(client kubernetes.Interface, namespace string, secretName stri
logrus.Infof("Creating secret")
secretClient := client.CoreV1().Secrets(namespace)
_, err := secretClient.Create(GetSecret(namespace, secretName, data))
time.Sleep(10 * time.Second)
time.Sleep(3 * time.Second)
return secretClient, err
}
// CreateDeployment creates a deployment in given namespace and returns the Deployment
func CreateDeployment(client kubernetes.Interface, deploymentName string, namespace string) (*v1beta1.Deployment, error) {
func CreateDeployment(client kubernetes.Interface, deploymentName string, namespace string, volumeMount bool) (*appsv1.Deployment, error) {
logrus.Infof("Creating Deployment")
deploymentClient := client.ExtensionsV1beta1().Deployments(namespace)
deployment, err := deploymentClient.Create(GetDeployment(namespace, deploymentName))
time.Sleep(10 * time.Second)
deploymentClient := client.AppsV1().Deployments(namespace)
var deploymentObj *appsv1.Deployment
if volumeMount {
deploymentObj = GetDeployment(namespace, deploymentName)
} else {
deploymentObj = GetDeploymentWithEnvVars(namespace, deploymentName)
}
deployment, err := deploymentClient.Create(deploymentObj)
time.Sleep(3 * time.Second)
return deployment, err
}
// CreateDeploymentConfig creates a deploymentConfig in given namespace and returns the DeploymentConfig
func CreateDeploymentConfig(client appsclient.Interface, deploymentName string, namespace string, volumeMount bool) (*openshiftv1.DeploymentConfig, error) {
logrus.Infof("Creating DeploymentConfig")
deploymentConfigsClient := client.AppsV1().DeploymentConfigs(namespace)
var deploymentConfigObj *openshiftv1.DeploymentConfig
if volumeMount {
deploymentConfigObj = GetDeploymentConfig(namespace, deploymentName)
} else {
deploymentConfigObj = GetDeploymentConfigWithEnvVars(namespace, deploymentName)
}
deploymentConfig, err := deploymentConfigsClient.Create(deploymentConfigObj)
time.Sleep(5 * time.Second)
return deploymentConfig, err
}
// CreateDeploymentWithInitContainer creates a deployment in given namespace with init container and returns the Deployment
func CreateDeploymentWithInitContainer(client kubernetes.Interface, deploymentName string, namespace string, volumeMount bool) (*appsv1.Deployment, error) {
logrus.Infof("Creating Deployment")
deploymentClient := client.AppsV1().Deployments(namespace)
var deploymentObj *appsv1.Deployment
if volumeMount {
deploymentObj = GetDeploymentWithInitContainer(namespace, deploymentName)
} else {
deploymentObj = GetDeploymentWithInitContainerAndEnv(namespace, deploymentName)
}
deployment, err := deploymentClient.Create(deploymentObj)
time.Sleep(3 * time.Second)
return deployment, err
}
// CreateDeploymentWithEnvVarSource creates a deployment in given namespace and returns the Deployment
func CreateDeploymentWithEnvVarSource(client kubernetes.Interface, deploymentName string, namespace string) (*appsv1.Deployment, error) {
logrus.Infof("Creating Deployment")
deploymentClient := client.AppsV1().Deployments(namespace)
deploymentObj := GetDeploymentWithEnvVarSources(namespace, deploymentName)
deployment, err := deploymentClient.Create(deploymentObj)
time.Sleep(3 * time.Second)
return deployment, err
}
// CreateDeploymentWithPodAnnotations creates a deployment in given namespace and returns the Deployment
func CreateDeploymentWithPodAnnotations(client kubernetes.Interface, deploymentName string, namespace string, both bool) (*appsv1.Deployment, error) {
logrus.Infof("Creating Deployment")
deploymentClient := client.AppsV1().Deployments(namespace)
deploymentObj := GetDeploymentWithPodAnnotations(namespace, deploymentName, both)
deployment, err := deploymentClient.Create(deploymentObj)
time.Sleep(3 * time.Second)
return deployment, err
}
// CreateDeploymentWithEnvVarSourceAndAnnotations returns a deployment in given
// namespace with given annotations.
func CreateDeploymentWithEnvVarSourceAndAnnotations(client kubernetes.Interface, deploymentName string, namespace string, annotations map[string]string) (*appsv1.Deployment, error) {
logrus.Infof("Creating Deployment")
deploymentClient := client.AppsV1().Deployments(namespace)
deploymentObj := GetDeploymentWithEnvVarSources(namespace, deploymentName)
deploymentObj.Annotations = annotations
deployment, err := deploymentClient.Create(deploymentObj)
time.Sleep(3 * time.Second)
return deployment, err
}
// CreateDaemonSet creates a deployment in given namespace and returns the DaemonSet
func CreateDaemonSet(client kubernetes.Interface, daemonsetName string, namespace string) (*v1beta1.DaemonSet, error) {
func CreateDaemonSet(client kubernetes.Interface, daemonsetName string, namespace string, volumeMount bool) (*appsv1.DaemonSet, error) {
logrus.Infof("Creating DaemonSet")
daemonsetClient := client.ExtensionsV1beta1().DaemonSets(namespace)
daemonset, err := daemonsetClient.Create(GetDaemonSet(namespace, daemonsetName))
time.Sleep(10 * time.Second)
daemonsetClient := client.AppsV1().DaemonSets(namespace)
var daemonsetObj *appsv1.DaemonSet
if volumeMount {
daemonsetObj = GetDaemonSet(namespace, daemonsetName)
} else {
daemonsetObj = GetDaemonSetWithEnvVars(namespace, daemonsetName)
}
daemonset, err := daemonsetClient.Create(daemonsetObj)
time.Sleep(3 * time.Second)
return daemonset, err
}
// CreateStatefulSet creates a deployment in given namespace and returns the StatefulSet
func CreateStatefulSet(client kubernetes.Interface, statefulsetName string, namespace string) (*v1_beta1.StatefulSet, error) {
func CreateStatefulSet(client kubernetes.Interface, statefulsetName string, namespace string, volumeMount bool) (*appsv1.StatefulSet, error) {
logrus.Infof("Creating StatefulSet")
statefulsetClient := client.AppsV1beta1().StatefulSets(namespace)
statefulset, err := statefulsetClient.Create(GetStatefulSet(namespace, statefulsetName))
time.Sleep(10 * time.Second)
statefulsetClient := client.AppsV1().StatefulSets(namespace)
var statefulsetObj *appsv1.StatefulSet
if volumeMount {
statefulsetObj = GetStatefulSet(namespace, statefulsetName)
} else {
statefulsetObj = GetStatefulSetWithEnvVar(namespace, statefulsetName)
}
statefulset, err := statefulsetClient.Create(statefulsetObj)
time.Sleep(3 * time.Second)
return statefulset, err
}
// DeleteDeployment creates a deployment in given namespace and returns the error if any
func DeleteDeployment(client kubernetes.Interface, namespace string, deploymentName string) error {
logrus.Infof("Deleting Deployment")
deploymentError := client.ExtensionsV1beta1().Deployments(namespace).Delete(deploymentName, &metav1.DeleteOptions{})
time.Sleep(10 * time.Second)
deploymentError := client.AppsV1().Deployments(namespace).Delete(deploymentName, &metav1.DeleteOptions{})
time.Sleep(3 * time.Second)
return deploymentError
}
// DeleteDeploymentConfig deletes a deploymentConfig in given namespace and returns the error if any
func DeleteDeploymentConfig(client appsclient.Interface, namespace string, deploymentConfigName string) error {
logrus.Infof("Deleting DeploymentConfig")
deploymentConfigError := client.AppsV1().DeploymentConfigs(namespace).Delete(deploymentConfigName, &metav1.DeleteOptions{})
time.Sleep(3 * time.Second)
return deploymentConfigError
}
// DeleteDaemonSet creates a daemonset in given namespace and returns the error if any
func DeleteDaemonSet(client kubernetes.Interface, namespace string, daemonsetName string) error {
logrus.Infof("Deleting DaemonSet %s", daemonsetName)
daemonsetError := client.ExtensionsV1beta1().DaemonSets(namespace).Delete(daemonsetName, &metav1.DeleteOptions{})
time.Sleep(10 * time.Second)
daemonsetError := client.AppsV1().DaemonSets(namespace).Delete(daemonsetName, &metav1.DeleteOptions{})
time.Sleep(3 * time.Second)
return daemonsetError
}
// DeleteStatefulSet creates a statefulset in given namespace and returns the error if any
func DeleteStatefulSet(client kubernetes.Interface, namespace string, statefulsetName string) error {
logrus.Infof("Deleting StatefulSet %s", statefulsetName)
statefulsetError := client.AppsV1beta1().StatefulSets(namespace).Delete(statefulsetName, &metav1.DeleteOptions{})
time.Sleep(10 * time.Second)
statefulsetError := client.AppsV1().StatefulSets(namespace).Delete(statefulsetName, &metav1.DeleteOptions{})
time.Sleep(3 * time.Second)
return statefulsetError
}
@@ -330,7 +760,7 @@ func UpdateConfigMap(configmapClient core_v1.ConfigMapInterface, namespace strin
configmap = GetConfigmap(namespace, configmapName, data)
}
_, updateErr := configmapClient.Update(configmap)
time.Sleep(10 * time.Second)
time.Sleep(3 * time.Second)
return updateErr
}
@@ -344,7 +774,7 @@ func UpdateSecret(secretClient core_v1.SecretInterface, namespace string, secret
secret = GetSecret(namespace, secretName, data)
}
_, updateErr := secretClient.Update(secret)
time.Sleep(10 * time.Second)
time.Sleep(3 * time.Second)
return updateErr
}
@@ -352,7 +782,7 @@ func UpdateSecret(secretClient core_v1.SecretInterface, namespace string, secret
func DeleteConfigMap(client kubernetes.Interface, namespace string, configmapName string) error {
logrus.Infof("Deleting configmap %q.\n", configmapName)
err := client.CoreV1().ConfigMaps(namespace).Delete(configmapName, &metav1.DeleteOptions{})
time.Sleep(10 * time.Second)
time.Sleep(3 * time.Second)
return err
}
@@ -360,7 +790,7 @@ func DeleteConfigMap(client kubernetes.Interface, namespace string, configmapNam
func DeleteSecret(client kubernetes.Interface, namespace string, secretName string) error {
logrus.Infof("Deleting secret %q.\n", secretName)
err := client.CoreV1().Secrets(namespace).Delete(secretName, &metav1.DeleteOptions{})
time.Sleep(10 * time.Second)
time.Sleep(3 * time.Second)
return err
}
@@ -374,28 +804,38 @@ func RandSeq(n int) string {
return string(b)
}
func VerifyResourceUpdate(client kubernetes.Interface, config util.Config, envVarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
items := upgradeFuncs.ItemsFunc(client, config.Namespace)
// VerifyResourceUpdate verifies whether the rolling upgrade happened or not
func VerifyResourceUpdate(clients kube.Clients, config util.Config, envVarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
items := upgradeFuncs.ItemsFunc(clients, config.Namespace)
for _, i := range items {
containers := upgradeFuncs.ContainersFunc(i)
// match statefulsets with the correct annotation
annotationValue := util.ToObjectMeta(i).Annotations[config.Annotation]
if annotationValue != "" {
searchAnnotationValue := util.ToObjectMeta(i).Annotations[options.AutoSearchAnnotation]
reloaderEnabledValue := util.ToObjectMeta(i).Annotations[options.ReloaderAutoAnnotation]
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
matches := false
if err == nil && reloaderEnabled {
matches = true
} else if annotationValue != "" {
values := strings.Split(annotationValue, ",")
matches := false
for _, value := range values {
if value == config.ResourceName {
matches = true
break
}
}
if matches {
envName := constants.EnvVarPrefix + util.ConvertToEnvVarName(annotationValue) + "_" + envVarPostfix
updated := GetResourceSHA(containers, envName)
} else if searchAnnotationValue == "true" {
if config.ResourceAnnotations[options.SearchMatchAnnotation] == "true" {
matches = true
}
}
if updated == config.SHAValue {
return true
}
if matches {
envName := constants.EnvVarPrefix + util.ConvertToEnvVarName(config.ResourceName) + "_" + envVarPostfix
updated := GetResourceSHA(containers, envName)
if updated == config.SHAValue {
return true
}
}
}

View File

@@ -1,9 +1,41 @@
package util
import (
"github.com/stakater/Reloader/internal/pkg/constants"
"github.com/stakater/Reloader/internal/pkg/options"
v1 "k8s.io/api/core/v1"
)
//Config contains rolling upgrade configuration parameters
type Config struct {
Namespace string
ResourceName string
Annotation string
SHAValue string
Namespace string
ResourceName string
ResourceAnnotations map[string]string
Annotation string
SHAValue string
Type string
}
// GetConfigmapConfig provides utility config for configmap
func GetConfigmapConfig(configmap *v1.ConfigMap) Config {
return Config{
Namespace: configmap.Namespace,
ResourceName: configmap.Name,
ResourceAnnotations: configmap.Annotations,
Annotation: options.ConfigmapUpdateOnChangeAnnotation,
SHAValue: GetSHAfromConfigmap(configmap.Data),
Type: constants.ConfigmapEnvVarPostfix,
}
}
// GetSecretConfig provides utility config for secret
func GetSecretConfig(secret *v1.Secret) Config {
return Config{
Namespace: secret.Namespace,
ResourceName: secret.Name,
ResourceAnnotations: secret.Annotations,
Annotation: options.SecretUpdateOnChangeAnnotation,
SHAValue: GetSHAfromSecret(secret.Data),
Type: constants.SecretEnvVarPostfix,
}
}

View File

@@ -2,6 +2,7 @@ package util
import (
"reflect"
"strconv"
"github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -36,3 +37,14 @@ func ToObjectMeta(kubernetesObject interface{}) ObjectMeta {
ObjectMeta: field,
}
}
// ParseBool returns result in bool format after parsing
func ParseBool(value interface{}) bool {
if reflect.Bool == reflect.TypeOf(value).Kind() {
return value.(bool)
} else if reflect.String == reflect.TypeOf(value).Kind() {
result, _ := strconv.ParseBool(value.(string))
return result
}
return false
}

View File

@@ -2,7 +2,10 @@ package util
import (
"bytes"
"sort"
"strings"
"github.com/stakater/Reloader/internal/pkg/crypto"
)
// ConvertToEnvVarName converts the given text into a usable env var
@@ -25,3 +28,32 @@ func ConvertToEnvVarName(text string) string {
}
return buffer.String()
}
func GetSHAfromConfigmap(data map[string]string) string {
values := []string{}
for k, v := range data {
values = append(values, k+"="+v)
}
sort.Strings(values)
return crypto.GenerateSHA(strings.Join(values, ";"))
}
func GetSHAfromSecret(data map[string][]byte) string {
values := []string{}
for k, v := range data {
values = append(values, k+"="+string(v[:]))
}
sort.Strings(values)
return crypto.GenerateSHA(strings.Join(values, ";"))
}
type List []string
func (l *List) Contains(s string) bool {
for _, v := range *l {
if v == s {
return true
}
}
return false
}

View File

@@ -3,13 +3,80 @@ package kube
import (
"os"
"k8s.io/client-go/tools/clientcmd"
appsclient "github.com/openshift/client-go/apps/clientset/versioned"
"github.com/sirupsen/logrus"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
// GetClient gets the client for k8s, if ~/.kube/config exists so get that config else incluster config
func GetClient() (*kubernetes.Clientset, error) {
// Clients struct exposes interfaces for kubernetes as well as openshift if available
type Clients struct {
KubernetesClient kubernetes.Interface
OpenshiftAppsClient appsclient.Interface
}
var (
// IsOpenshift is true if environment is Openshift, it is false if environment is Kubernetes
IsOpenshift = isOpenshift()
)
// GetClients returns a `Clients` object containing both openshift and kubernetes clients with an openshift identifier
func GetClients() Clients {
client, err := GetKubernetesClient()
if err != nil {
logrus.Fatalf("Unable to create Kubernetes client error = %v", err)
}
var appsClient *appsclient.Clientset
if IsOpenshift {
appsClient, err = GetOpenshiftAppsClient()
if err != nil {
logrus.Warnf("Unable to create Openshift Apps client error = %v", err)
}
}
return Clients{
KubernetesClient: client,
OpenshiftAppsClient: appsClient,
}
}
func isOpenshift() bool {
client, err := GetKubernetesClient()
if err != nil {
logrus.Fatalf("Unable to create Kubernetes client error = %v", err)
}
_, err = client.RESTClient().Get().AbsPath("/apis/project.openshift.io").Do().Raw()
if err == nil {
logrus.Info("Environment: Openshift")
return true
}
logrus.Info("Environment: Kubernetes")
return false
}
// GetOpenshiftAppsClient returns an Openshift Client that can query on Apps
func GetOpenshiftAppsClient() (*appsclient.Clientset, error) {
config, err := getConfig()
if err != nil {
return nil, err
}
return appsclient.NewForConfig(config)
}
// GetKubernetesClient gets the client for k8s, if ~/.kube/config exists so get that config else incluster config
func GetKubernetesClient() (*kubernetes.Clientset, error) {
config, err := getConfig()
if err != nil {
return nil, err
}
return kubernetes.NewForConfig(config)
}
func getConfig() (*rest.Config, error) {
var config *rest.Config
var err error
kubeconfigPath := os.Getenv("KUBECONFIG")
@@ -31,5 +98,6 @@ func GetClient() (*kubernetes.Clientset, error) {
if err != nil {
return nil, err
}
return kubernetes.NewForConfig(config)
return config, nil
}

View File

@@ -1,7 +1,7 @@
package kube
import (
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
)