mirror of
https://github.com/stakater/Reloader.git
synced 2026-02-14 18:09:50 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b637e33d9d | ||
|
|
130741480e | ||
|
|
cd19d739ab | ||
|
|
f15ec9b4d4 | ||
|
|
013fcdc052 | ||
|
|
78e98c7999 | ||
|
|
44c6333910 | ||
|
|
0316bcd938 | ||
|
|
8c77c230e0 | ||
|
|
bcffb62e3f | ||
|
|
85c10da63d | ||
|
|
b17ab76a24 | ||
|
|
23ab5692fa | ||
|
|
55c93a4dd8 | ||
|
|
32eb9e7959 | ||
|
|
09046c45ff | ||
|
|
f346ca84ab | ||
|
|
5041d1a1cf | ||
|
|
1ad93145b4 | ||
|
|
61b398539e | ||
|
|
0cb86cf665 | ||
|
|
b973c37a4f | ||
|
|
1cfa756178 | ||
|
|
e8854000cb | ||
|
|
291f25fd0e | ||
|
|
19d5704bf9 | ||
|
|
d24b112150 | ||
|
|
c5e00d7614 | ||
|
|
4779ef93c8 | ||
|
|
b73f14aef9 | ||
|
|
67012d9544 | ||
|
|
f36c3e4dbb | ||
|
|
b7ac8b8f07 | ||
|
|
9bef611a1a | ||
|
|
ea62b0036c | ||
|
|
decb9b06be | ||
|
|
94bd7bb694 | ||
|
|
67843f839a | ||
|
|
342395cd84 | ||
|
|
695c5b05d2 | ||
|
|
163aede486 | ||
|
|
4d6da476ee | ||
|
|
d5ea5d810d | ||
|
|
0d10b35d3a | ||
|
|
807e0c0c1b |
8
Jenkinsfile
vendored
8
Jenkinsfile
vendored
@@ -1,8 +1,10 @@
|
||||
#!/usr/bin/groovy
|
||||
@Library('github.com/stakater/fabric8-pipeline-library@v2.5.3')
|
||||
@Library('github.com/stakater/fabric8-pipeline-library@v2.10.8')
|
||||
|
||||
def dummy
|
||||
|
||||
goBuildAndRelease {
|
||||
|
||||
}
|
||||
chartRepositoryURL = 'https://chartmuseum.release.stakater.com'
|
||||
publicChartRepositoryURL = 'https://stakater.github.io/stakater-charts'
|
||||
publicChartGitURL = 'git@github.com:stakater/stakater-charts.git'
|
||||
}
|
||||
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
104
README.md
104
README.md
@@ -1,35 +1,102 @@
|
||||
# RELOADER
|
||||
#  RELOADER
|
||||
|
||||
[](https://goreportcard.com/report/github.com/stakater/reloader)
|
||||
[](http://godoc.org/github.com/stakater/reloader)
|
||||
[](https://github.com/stakater/reloader/releases/latest)
|
||||
[](https://github.com/stakater/reloader/releases/latest)
|
||||
[](https://hub.docker.com/r/stakater/reloader/)
|
||||
[](https://hub.docker.com/r/stakater/reloader/)
|
||||
[](https://microbadger.com/images/stakater/reloader)
|
||||
[](https://microbadger.com/images/stakater/reloader)
|
||||
[](LICENSE)
|
||||
[](http://stakater.com/?utm_source=Reloader&utm_medium=github)
|
||||
|
||||
## Problem
|
||||
|
||||
We would like to watch if some change happens in `ConfigMap` and `Secret` objects and then perform 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 `Deployment`, `Deamonset` and `Statefulset`
|
||||
|
||||
## Solution
|
||||
|
||||
Reloader can watch changes in `ConfigMap` and `Secret` and do rolling upgrades on Pods with their associated `Deployments`, `Deamonsets` and `Statefulsets`.
|
||||
|
||||
**NOTE:** This controller has been inspired from [configmapController](https://github.com/fabric8io/configmapcontroller)
|
||||
|
||||
## How to use Reloader
|
||||
|
||||
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-configmap` or `Secret` called `foo-secret` or both. Then add this annotation to main metadata of your `Deployment`
|
||||
|
||||
```yaml
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
configmap.reloader.stakater.com/reload: "foo"
|
||||
reloader.stakater.com/auto: "true"
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
```
|
||||
|
||||
OR
|
||||
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.
|
||||
|
||||
For a `Deployment` called `foo` have a `Secret` called `foo`. Then add this annotation to your `Deployment`
|
||||
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 `reloader.stakater.com/auto: "false"` or remove this annotation altogather, 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
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
secret.reloader.stakater.com/reload: "foo"
|
||||
configmap.reloader.stakater.com/reload: "foo-configmap"
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
```
|
||||
|
||||
Use comma separated list to define multiple configmaps.
|
||||
|
||||
```yaml
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
configmap.reloader.stakater.com/reload: "foo-configmap,bar-configmap,baz-configmap"
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
```
|
||||
|
||||
### Secret
|
||||
|
||||
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
|
||||
metadata:
|
||||
annotations:
|
||||
secret.reloader.stakater.com/reload: "foo-secret"
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
```
|
||||
|
||||
Use comma separated list to define multiple secrets.
|
||||
|
||||
```yaml
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
secret.reloader.stakater.com/reload: "foo-secret,bar-secret,baz-secret"
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
```
|
||||
|
||||
### NOTE
|
||||
`reloader.stakater.com/auto: "true"` will always override when use with either `secret.reloader.stakater.com/reload` or `configmap.reloader.stakater.com/reload` annotation.
|
||||
|
||||
## Deploying to Kubernetes
|
||||
|
||||
You can deploy Reloader by following methods:
|
||||
@@ -42,6 +109,8 @@ You can apply vanilla manifests by running the following command
|
||||
kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
|
||||
```
|
||||
|
||||
By default Reloader gets deployed in `default` namespace and watches changes `secrets` and `configmaps` in all namespaces.
|
||||
|
||||
### 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
|
||||
@@ -54,13 +123,18 @@ helm repo update
|
||||
helm install stakater/reloader
|
||||
```
|
||||
|
||||
## Monitor All namespaces
|
||||
**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.
|
||||
|
||||
By default Reloader gets deployed in `default` namespace and watches changes `secrets` and `configmaps` in all namespaces.
|
||||
```bash
|
||||
helm install stakater/reloader --set reloader.watchGlobally=false --namespace test
|
||||
```
|
||||
|
||||
## Help
|
||||
|
||||
**Got a question?**
|
||||
### 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
|
||||
@@ -68,7 +142,7 @@ File a GitHub [issue](https://github.com/stakater/Reloader/issues), or send us a
|
||||
Join and talk to us on Slack for discussing Reloader
|
||||
|
||||
[](https://stakater-slack.herokuapp.com/)
|
||||
[](https://stakater.slack.com/)
|
||||
[](https://stakater.slack.com/messages/CC5S05S12)
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -105,3 +179,7 @@ or contact us in case of professional services and queries on <hello@stakater.co
|
||||
|
||||
[website]: http://stakater.com/
|
||||
[community]: https://github.com/stakater/
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
- [ConfigmapController](https://github.com/fabric8io/configmapcontroller); We documented here why we re-created [Reloader](docs/Reloader-vs-ConfigmapController.md)
|
||||
|
||||
BIN
assets/web/reloader-round-100px.png
Normal file
BIN
assets/web/reloader-round-100px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
2
deployments/kubernetes/chart/reloader/.helmignore
Normal file
2
deployments/kubernetes/chart/reloader/.helmignore
Normal file
@@ -0,0 +1,2 @@
|
||||
# OWNERS file for Kubernetes
|
||||
OWNERS
|
||||
@@ -3,11 +3,27 @@
|
||||
apiVersion: v1
|
||||
name: reloader
|
||||
description: Reloader chart that runs on kubernetes
|
||||
version: 0.0.10
|
||||
version: v0.0.22
|
||||
appVersion: v0.0.22
|
||||
keywords:
|
||||
- Reloader
|
||||
- kubernetes
|
||||
home: https://github.com/stakater/Reloader
|
||||
sources:
|
||||
- https://github.com/stakater/IngressMonitorController
|
||||
icon: https://raw.githubusercontent.com/stakater/Reloader/master/assets/web/reloader-round-100px.png
|
||||
maintainers:
|
||||
- name: Stakater
|
||||
email: hello@stakater.com
|
||||
email: hello@stakater.com
|
||||
- name: rasheedamir
|
||||
email: rasheed@aurorasolutions.io
|
||||
- name: waseem-h
|
||||
email: waseemhassan@stakater.com
|
||||
- name: faizanahmad055
|
||||
email: faizan.ahmad55@outlook.com
|
||||
- name: kahootali
|
||||
email: ali.kahoot@aurorasolutions.io
|
||||
- name: ahmadiq
|
||||
email: ahmad@aurorasolutions.io
|
||||
- name: ahsan-storm
|
||||
email: ahsanmuhammad1@outlook.com
|
||||
|
||||
14
deployments/kubernetes/chart/reloader/OWNERS
Normal file
14
deployments/kubernetes/chart/reloader/OWNERS
Normal file
@@ -0,0 +1,14 @@
|
||||
approvers:
|
||||
- faizanahmad055
|
||||
- kahootali
|
||||
- ahmadiq
|
||||
- waseem-h
|
||||
- rasheedamir
|
||||
- ahsan-storm
|
||||
reviewers:
|
||||
- faizanahmad055
|
||||
- kahootali
|
||||
- ahmadiq
|
||||
- waseem-h
|
||||
- rasheedamir
|
||||
- ahsan-storm
|
||||
@@ -0,0 +1,7 @@
|
||||
- For a `Deployment` called `foo` have a `ConfigMap` called `foo-configmap`. Then add this annotation to main metadata of your `Deployment`
|
||||
configmap.reloader.stakater.com/reload: "foo-configmap"
|
||||
|
||||
- For a `Deployment` called `foo` have a `Secret` called `foo-secret`. Then add this annotation to main metadata of your `Deployment`
|
||||
secret.reloader.stakater.com/reload: "foo-secret"
|
||||
|
||||
- After successful installation, your pods will get rolling updates when a change in data of configmap or secret will happen.
|
||||
@@ -15,19 +15,20 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "reloader-labels.selector" -}}
|
||||
app: {{ template "reloader-name" . }}
|
||||
group: {{ .Values.reloader.labels.group }}
|
||||
provider: {{ .Values.reloader.labels.provider }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "reloader-labels.stakater" -}}
|
||||
{{ template "reloader-labels.selector" . }}
|
||||
version: {{ .Values.reloader.labels.version }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "reloader-labels.chart" -}}
|
||||
app: {{ template "reloader-name" . }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
release: {{ .Release.Name | quote }}
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "serviceAccountName" -}}
|
||||
{{- if .Values.reloader.serviceAccount.create -}}
|
||||
{{ default (include "reloader-fullname" .) .Values.reloader.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.reloader.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{{- if and .Values.reloader.watchGlobally (.Values.reloader.rbac.enabled) }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
{{- if .Values.reloader.rbac.labels }}
|
||||
{{ toYaml .Values.reloader.rbac.labels | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
|
||||
{{- end }}
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
namespace: {{ .Release.Namespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
- configmaps
|
||||
verbs:
|
||||
- list
|
||||
- get
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "extensions"
|
||||
- "apps"
|
||||
resources:
|
||||
- deployments
|
||||
- daemonsets
|
||||
- statefulsets
|
||||
verbs:
|
||||
- list
|
||||
- get
|
||||
- update
|
||||
- patch
|
||||
{{- end }}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{- if and .Values.reloader.watchGlobally (.Values.reloader.rbac.enabled) }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
{{- if .Values.reloader.rbac.labels }}
|
||||
{{ toYaml .Values.reloader.rbac.labels | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
|
||||
{{- end }}
|
||||
name: {{ template "reloader-name" . }}-role-binding
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
@@ -1,31 +1,73 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
{{- if .Values.reloader.deployment.annotations }}
|
||||
annotations:
|
||||
{{ toYaml .Values.reloader.deployment.annotations | indent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{ include "reloader-labels.stakater" . | indent 4 }}
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
{{- if .Values.reloader.deployment.labels }}
|
||||
{{ toYaml .Values.reloader.deployment.labels | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
|
||||
{{- end }}
|
||||
name: {{ template "reloader-name" . }}
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
{{ include "reloader-labels.selector" . | indent 6 }}
|
||||
app: {{ template "reloader-name" . }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 6 }}
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.selector" . | indent 8 }}
|
||||
{{ include "reloader-labels.chart" . | indent 8 }}
|
||||
{{- if .Values.reloader.deployment.labels }}
|
||||
{{ toYaml .Values.reloader.deployment.labels | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
{{- range $name, $value := .Values.reloader.deployment.env.open }}
|
||||
{{- if not (empty $value) }}
|
||||
- name: {{ $name | quote }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- $secret_name := include "reloader-fullname" . }}
|
||||
{{- range $name, $value := .Values.reloader.deployment.env.secret }}
|
||||
{{- if not ( empty $value) }}
|
||||
- name: {{ $name | quote }}
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ $secret_name }}
|
||||
key: {{ $name | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $name, $value := .Values.reloader.deployment.env.field }}
|
||||
{{- if not ( empty $value) }}
|
||||
- name: {{ $name | quote }}
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: {{ $value | quote}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if eq .Values.reloader.watchGlobally false }}
|
||||
- name: KUBERNETES_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
{{- end }}
|
||||
image: "{{ .Values.reloader.image.name }}:{{ .Values.reloader.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.reloader.image.pullPolicy }}
|
||||
image: "{{ .Values.reloader.deployment.image.name }}:{{ .Values.reloader.deployment.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.reloader.deployment.image.pullPolicy }}
|
||||
name: {{ template "reloader-name" . }}
|
||||
serviceAccountName: {{ template "reloader-name" . }}
|
||||
|
||||
serviceAccountName: {{ template "serviceAccountName" . }}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.stakater" . | indent 4 }}
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
name: {{ template "reloader-name" . }}
|
||||
---
|
||||
{{- if .Values.reloader.watchGlobally }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.stakater" . | indent 4 }}
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
namespace: {{ .Release.Namespace }}
|
||||
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:
|
||||
{{ include "reloader-labels.stakater" . | indent 4 }}
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
name: {{ template "reloader-name" . }}-role-binding
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "reloader-name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- else }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: Role
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.stakater" . | indent 4 }}
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
namespace: {{ .Release.Namespace }}
|
||||
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: RoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.stakater" . | indent 4 }}
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
name: {{ template "reloader-name" . }}-role-binding
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "reloader-name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
37
deployments/kubernetes/chart/reloader/templates/role.yaml
Normal file
37
deployments/kubernetes/chart/reloader/templates/role.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
{{- if and (not (.Values.reloader.watchGlobally)) (.Values.reloader.rbac.enabled) }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: Role
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
{{- if .Values.reloader.rbac.labels }}
|
||||
{{ toYaml .Values.reloader.rbac.labels | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
|
||||
{{- end }}
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
namespace: {{ .Release.Namespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
- configmaps
|
||||
verbs:
|
||||
- list
|
||||
- get
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "extensions"
|
||||
- "apps"
|
||||
resources:
|
||||
- deployments
|
||||
- daemonsets
|
||||
- statefulsets
|
||||
verbs:
|
||||
- list
|
||||
- get
|
||||
- update
|
||||
- patch
|
||||
{{- end }}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{- if and (not (.Values.reloader.watchGlobally)) (.Values.reloader.rbac.enabled) }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
{{- if .Values.reloader.rbac.labels }}
|
||||
{{ toYaml .Values.reloader.rbac.labels | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
|
||||
{{- end }}
|
||||
name: {{ template "reloader-name" . }}-role-binding
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ template "reloader-name" . }}-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.reloader.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "reloader-labels.chart" . | indent 4 }}
|
||||
{{- if .Values.reloader.serviceAccount.labels }}
|
||||
{{ toYaml .Values.reloader.serviceAccount.labels | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.reloader.matchLabels }}
|
||||
{{ toYaml .Values.reloader.matchLabels | indent 4 }}
|
||||
{{- end }}
|
||||
name: {{ template "serviceAccountName" . }}
|
||||
{{- end }}
|
||||
@@ -4,12 +4,34 @@ kubernetes:
|
||||
host: https://kubernetes.default
|
||||
|
||||
reloader:
|
||||
labels:
|
||||
provider: stakater
|
||||
group: com.stakater.platform
|
||||
version: 0.0.10
|
||||
image:
|
||||
name: stakater/reloader
|
||||
tag: "0.0.10"
|
||||
pullPolicy: IfNotPresent
|
||||
watchGlobally: true
|
||||
watchGlobally: true
|
||||
matchLabels: {}
|
||||
deployment:
|
||||
annotations: {}
|
||||
labels:
|
||||
provider: stakater
|
||||
group: com.stakater.platform
|
||||
version: v0.0.22
|
||||
image:
|
||||
name: stakater/reloader
|
||||
tag: "v0.0.22"
|
||||
pullPolicy: IfNotPresent
|
||||
# Support for extra environment variables.
|
||||
env:
|
||||
# Open supports Key value pair as environment variables.
|
||||
open:
|
||||
# secret supports Key value pair as environment variables. It gets the values based on keys from default reloader secret if any.
|
||||
secret:
|
||||
# field supports Key value pair as environment variables. It gets the values from other fields of pod.
|
||||
field:
|
||||
rbac:
|
||||
enabled: true
|
||||
labels: {}
|
||||
# Service account config for the agent pods
|
||||
serviceAccount:
|
||||
# Specifies whether a ServiceAccount should be created
|
||||
create: true
|
||||
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
|
||||
|
||||
36
deployments/kubernetes/manifests/clusterrole.yaml
Normal file
36
deployments/kubernetes/manifests/clusterrole.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
# Source: reloader/templates/clusterrole.yaml
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
chart: "reloader-v0.0.22"
|
||||
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
|
||||
|
||||
22
deployments/kubernetes/manifests/clusterrolebinding.yaml
Normal file
22
deployments/kubernetes/manifests/clusterrolebinding.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# Source: reloader/templates/clusterrolebinding.yaml
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
chart: "reloader-v0.0.22"
|
||||
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
|
||||
|
||||
@@ -5,12 +5,13 @@ kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
chart: "reloader-v0.0.22"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: v0.0.22
|
||||
|
||||
name: reloader
|
||||
spec:
|
||||
replicas: 1
|
||||
@@ -18,19 +19,23 @@ spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
release: "RELEASE-NAME"
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
chart: "reloader-v0.0.22"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: v0.0.22
|
||||
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
image: "stakater/reloader:0.0.10"
|
||||
image: "stakater/reloader:v0.0.22"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: reloader
|
||||
serviceAccountName: reloader
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ metadata:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
version: 0.0.18
|
||||
chart: "reloader-0.0.18"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader
|
||||
@@ -20,8 +20,8 @@ metadata:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
version: 0.0.18
|
||||
chart: "reloader-0.0.18"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader-role
|
||||
@@ -57,8 +57,8 @@ metadata:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
version: 0.0.18
|
||||
chart: "reloader-0.0.18"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader-role-binding
|
||||
|
||||
4
deployments/kubernetes/manifests/role.yaml
Normal file
4
deployments/kubernetes/manifests/role.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
# Source: reloader/templates/role.yaml
|
||||
|
||||
|
||||
4
deployments/kubernetes/manifests/rolebinding.yaml
Normal file
4
deployments/kubernetes/manifests/rolebinding.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
# Source: reloader/templates/rolebinding.yaml
|
||||
|
||||
|
||||
13
deployments/kubernetes/manifests/serviceaccount.yaml
Normal file
13
deployments/kubernetes/manifests/serviceaccount.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
# Source: reloader/templates/serviceaccount.yaml
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
chart: "reloader-v0.0.22"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
---
|
||||
# Source: reloader/templates/role.yaml
|
||||
|
||||
|
||||
---
|
||||
# Source: reloader/templates/deployment.yaml
|
||||
apiVersion: extensions/v1beta1
|
||||
@@ -5,12 +9,13 @@ kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
chart: "reloader-v0.0.22"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: v0.0.22
|
||||
|
||||
name: reloader
|
||||
spec:
|
||||
replicas: 1
|
||||
@@ -18,22 +23,66 @@ spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
release: "RELEASE-NAME"
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
chart: "reloader-v0.0.22"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: v0.0.22
|
||||
|
||||
spec:
|
||||
containers:
|
||||
- env:
|
||||
image: "stakater/reloader:0.0.10"
|
||||
image: "stakater/reloader:v0.0.22"
|
||||
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-v0.0.22"
|
||||
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
|
||||
|
||||
---
|
||||
# Source: reloader/templates/rolebinding.yaml
|
||||
|
||||
|
||||
---
|
||||
# Source: reloader/templates/rbac.yaml
|
||||
apiVersion: v1
|
||||
@@ -43,8 +92,8 @@ metadata:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
version: 0.0.18
|
||||
chart: "reloader-0.0.18"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader
|
||||
@@ -56,8 +105,8 @@ metadata:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
version: 0.0.18
|
||||
chart: "reloader-0.0.18"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader-role
|
||||
@@ -93,8 +142,8 @@ metadata:
|
||||
app: reloader
|
||||
group: com.stakater.platform
|
||||
provider: stakater
|
||||
version: 0.0.10
|
||||
chart: "reloader-0.0.10"
|
||||
version: 0.0.18
|
||||
chart: "reloader-0.0.18"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader-role-binding
|
||||
@@ -107,3 +156,38 @@ 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-v0.0.22"
|
||||
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/serviceaccount.yaml
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app: reloader
|
||||
chart: "reloader-v0.0.22"
|
||||
release: "RELEASE-NAME"
|
||||
heritage: "Tiller"
|
||||
name: reloader
|
||||
|
||||
|
||||
@@ -4,10 +4,26 @@ apiVersion: v1
|
||||
name: reloader
|
||||
description: Reloader chart that runs on kubernetes
|
||||
version: {{ getenv "VERSION" }}
|
||||
appVersion: {{ getenv "VERSION" }}
|
||||
keywords:
|
||||
- Reloader
|
||||
- kubernetes
|
||||
home: https://github.com/stakater/Reloader
|
||||
sources:
|
||||
- https://github.com/stakater/IngressMonitorController
|
||||
icon: https://raw.githubusercontent.com/stakater/Reloader/master/assets/web/reloader-round-100px.png
|
||||
maintainers:
|
||||
- name: Stakater
|
||||
email: hello@stakater.com
|
||||
email: hello@stakater.com
|
||||
- name: rasheedamir
|
||||
email: rasheed@aurorasolutions.io
|
||||
- name: waseem-h
|
||||
email: waseemhassan@stakater.com
|
||||
- name: faizanahmad055
|
||||
email: faizan.ahmad55@outlook.com
|
||||
- name: kahootali
|
||||
email: ali.kahoot@aurorasolutions.io
|
||||
- name: ahmadiq
|
||||
email: ahmad@aurorasolutions.io
|
||||
- name: ahsan-storm
|
||||
email: ahsanmuhammad1@outlook.com
|
||||
|
||||
@@ -4,12 +4,34 @@ kubernetes:
|
||||
host: https://kubernetes.default
|
||||
|
||||
reloader:
|
||||
labels:
|
||||
provider: stakater
|
||||
group: com.stakater.platform
|
||||
version: {{ getenv "VERSION" }}
|
||||
image:
|
||||
name: {{ getenv "DOCKER_IMAGE" }}
|
||||
tag: "{{ getenv "VERSION" }}"
|
||||
pullPolicy: IfNotPresent
|
||||
watchGlobally: true
|
||||
watchGlobally: true
|
||||
matchLabels: {}
|
||||
deployment:
|
||||
annotations: {}
|
||||
labels:
|
||||
provider: stakater
|
||||
group: com.stakater.platform
|
||||
version: {{ getenv "VERSION" }}
|
||||
image:
|
||||
name: {{ getenv "DOCKER_IMAGE" }}
|
||||
tag: "{{ getenv "VERSION" }}"
|
||||
pullPolicy: IfNotPresent
|
||||
# Support for extra environment variables.
|
||||
env:
|
||||
# Open supports Key value pair as environment variables.
|
||||
open:
|
||||
# secret supports Key value pair as environment variables. It gets the values based on keys from default reloader secret if any.
|
||||
secret:
|
||||
# field supports Key value pair as environment variables. It gets the values from other fields of pod.
|
||||
field:
|
||||
rbac:
|
||||
enabled: true
|
||||
labels: {}
|
||||
# Service account config for the agent pods
|
||||
serviceAccount:
|
||||
# Specifies whether a ServiceAccount should be created
|
||||
create: true
|
||||
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
|
||||
|
||||
@@ -75,3 +75,6 @@ And render manifest file using helm command
|
||||
helm --namespace {replace this with namespace name} template . > reloader.yaml
|
||||
```
|
||||
The output file can then be used to deploy reloader in specific namespace.
|
||||
|
||||
## Compatibility with helm install and upgrade
|
||||
Reloader has no impact on helm deployment cycle. Reloader only injects an environment variable in `deployment`, `daemonset` or `statefulset`. The environment variable contains the SHA1 value of configmap's or secret's data. So if a deployment is created using Helm and Reloader updates the deployment, then next time you upgrade the helm release, reloader will do nothing except changing that environment variable value in `deployment` , `daemonset` or `statefulset`.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
|
||||
# Reloader vs ConfigmapController
|
||||
|
||||
Reloader is inspired from [configmapcontroller](https://github.com/fabric8io/configmapcontroller) but there are many ways in which it differs from configmapController. Below is the small comparison between these two controllers.
|
||||
Reloader is inspired from [Configmapcontroller](https://github.com/fabric8io/configmapcontroller) but there are many ways in which it differs from configmapController. Below is the small comparison between these two controllers.
|
||||
|
||||
| Configmap | Reloader |
|
||||
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| ConfigmapController can only watch changes in `configmaps`. It cannot detect changes in other resources like `secrets`. | Reloader on the other hand can watch and detect changes in both `secrets` and `configmaps`. |
|
||||
| ConfigmapController can only perform rolling upgrades on `deployments`. It currently does not support rolling upgrades on `statefulsets` and `daemonsets` | Reloader on the other hand can perform rolling upgrades on `deployments` as well as on `statefulsets` and `daemonsets` |
|
||||
| Currently there are no 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 if new changes break any older functionality or not. | 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 older functionality. |
|
||||
| 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 also very less pron to collision. |
|
||||
| Reloader | Configmap |
|
||||
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| 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. |
|
||||
7
docs/features.md
Normal file
7
docs/features.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Features
|
||||
|
||||
These are the key features of Reloader:
|
||||
|
||||
1. Restart pod in a depoloyment on change in linked/related configmap's or secret's
|
||||
2. Restart pod in a daemonset on change in linked/related configmap's or secret's
|
||||
3. Restart pod in a statefulset on change in linked/related configmap's or secret's
|
||||
@@ -16,6 +16,9 @@ type ItemsFunc func(kubernetes.Interface, string) []interface{}
|
||||
//ContainersFunc is a generic func to return containers
|
||||
type ContainersFunc 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
|
||||
|
||||
@@ -24,6 +27,7 @@ type RollingUpgradeFuncs struct {
|
||||
ItemsFunc ItemsFunc
|
||||
ContainersFunc ContainersFunc
|
||||
UpdateFunc UpdateFunc
|
||||
VolumesFunc VolumesFunc
|
||||
ResourceType string
|
||||
}
|
||||
|
||||
@@ -89,3 +93,18 @@ func UpdateStatefulset(client kubernetes.Interface, namespace string, resource i
|
||||
_, err := client.AppsV1beta1().StatefulSets(namespace).Update(&statefulSet)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetDeploymentVolumes returns the Volumes of given deployment
|
||||
func GetDeploymentVolumes(item interface{}) []v1.Volume {
|
||||
return item.(v1beta1.Deployment).Spec.Template.Spec.Volumes
|
||||
}
|
||||
|
||||
// GetDaemonSetVolumes returns the Volumes of given daemonset
|
||||
func GetDaemonSetVolumes(item interface{}) []v1.Volume {
|
||||
return item.(v1beta1.DaemonSet).Spec.Template.Spec.Volumes
|
||||
}
|
||||
|
||||
// GetStatefulsetVolumes returns the Volumes of given statefulSet
|
||||
func GetStatefulsetVolumes(item interface{}) []v1.Volume {
|
||||
return item.(apps_v1beta1.StatefulSet).Spec.Template.Spec.Volumes
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func startReloader(cmd *cobra.Command, args []string) {
|
||||
// Now let's start the controller
|
||||
stop := make(chan struct{})
|
||||
defer close(stop)
|
||||
|
||||
logrus.Infof("Starting Controller to watch resource type: %s", k)
|
||||
go c.Run(1, stop)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,4 +5,6 @@ const (
|
||||
ConfigmapUpdateOnChangeAnnotation = "configmap.reloader.stakater.com/reload"
|
||||
// SecretUpdateOnChangeAnnotation is an annotation to detect changes in secrets
|
||||
SecretUpdateOnChangeAnnotation = "secret.reloader.stakater.com/reload"
|
||||
// ReloaderAutoAnnotation is an annotation to detect changes in secrets
|
||||
ReloaderAutoAnnotation = "reloader.stakater.com/auto"
|
||||
)
|
||||
|
||||
15
internal/pkg/constants/enums.go
Normal file
15
internal/pkg/constants/enums.go
Normal 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
|
||||
)
|
||||
@@ -64,13 +64,11 @@ func (c *Controller) Update(old interface{}, new interface{}) {
|
||||
|
||||
// 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
|
||||
func (c *Controller) Run(threadiness int, stopCh chan struct{}) {
|
||||
|
||||
logrus.Infof("Starting Controller")
|
||||
defer runtime.HandleCrash()
|
||||
|
||||
// Let the workers stop when we are done
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"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/handler"
|
||||
"github.com/stakater/Reloader/internal/pkg/testutil"
|
||||
"github.com/stakater/Reloader/internal/pkg/util"
|
||||
"github.com/stakater/Reloader/pkg/kube"
|
||||
@@ -60,7 +60,7 @@ func TestControllerUpdatingConfigmapShouldCreateEnvInDeployment(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace)
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
@@ -80,12 +80,120 @@ func TestControllerUpdatingConfigmapShouldCreateEnvInDeployment(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDeploymentItems,
|
||||
ContainersFunc: callbacks.GetDeploymentContainers,
|
||||
UpdateFunc: callbacks.UpdateDeployment,
|
||||
ResourceType: "Deployment",
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, deploymentFuncs)
|
||||
if !updated {
|
||||
t.Errorf("Deployment was not updated")
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Deleting deployment
|
||||
err = testutil.DeleteDeployment(client, namespace, configmapName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the deployment %v", err)
|
||||
}
|
||||
|
||||
// Deleting configmap
|
||||
err = testutil.DeleteConfigMap(client, namespace, configmapName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the configmap %v", err)
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Perform rolling upgrade on deployment and create env var upon updating the configmap
|
||||
func TestControllerUpdatingConfigmapShouldAutoCreateEnvInDeployment(t *testing.T) {
|
||||
|
||||
// Creating configmap
|
||||
configmapName := configmapNamePrefix + "-update-" + testutil.RandSeq(5)
|
||||
configmapClient, err := testutil.CreateConfigMap(client, namespace, configmapName, "www.google.com")
|
||||
if err != nil {
|
||||
t.Errorf("Error while creating the configmap %v", err)
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace, false)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
|
||||
// Updating configmap for first time
|
||||
updateErr := testutil.UpdateConfigMap(configmapClient, namespace, configmapName, "", "www.stakater.com")
|
||||
if updateErr != nil {
|
||||
t.Errorf("Configmap was not updated")
|
||||
}
|
||||
|
||||
// Verifying deployment update
|
||||
logrus.Infof("Verifying env var has been created")
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapName, "www.stakater.com")
|
||||
config := util.Config{
|
||||
Namespace: namespace,
|
||||
ResourceName: configmapName,
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, deploymentFuncs)
|
||||
if !updated {
|
||||
t.Errorf("Deployment was not updated")
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Deleting deployment
|
||||
err = testutil.DeleteDeployment(client, namespace, configmapName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the deployment %v", err)
|
||||
}
|
||||
|
||||
// Deleting configmap
|
||||
err = testutil.DeleteConfigMap(client, namespace, configmapName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the configmap %v", err)
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Perform rolling upgrade on deployment and create env var upon creating the configmap
|
||||
func TestControllerCreatingConfigmapShouldCreateEnvInDeployment(t *testing.T) {
|
||||
|
||||
// Creating configmap
|
||||
configmapName := configmapNamePrefix + "-create-" + testutil.RandSeq(5)
|
||||
_, err := testutil.CreateConfigMap(client, namespace, configmapName, "www.google.com")
|
||||
if err != nil {
|
||||
t.Errorf("Error while creating the configmap %v", err)
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
|
||||
// Deleting configmap for first time
|
||||
err = testutil.DeleteConfigMap(client, namespace, configmapName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the configmap %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
_, err = testutil.CreateConfigMap(client, namespace, configmapName, "www.stakater.com")
|
||||
if err != nil {
|
||||
t.Errorf("Error while creating the configmap second time %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Verifying deployment update
|
||||
logrus.Infof("Verifying env var has been created")
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapName, "www.stakater.com")
|
||||
config := util.Config{
|
||||
Namespace: namespace,
|
||||
ResourceName: configmapName,
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, deploymentFuncs)
|
||||
if !updated {
|
||||
t.Errorf("Deployment was not updated")
|
||||
@@ -116,7 +224,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateDeployment(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace)
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
@@ -143,12 +251,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateDeployment(t *testing.T) {
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
|
||||
deploymentFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDeploymentItems,
|
||||
ContainersFunc: callbacks.GetDeploymentContainers,
|
||||
UpdateFunc: callbacks.UpdateDeployment,
|
||||
ResourceType: "Deployment",
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, deploymentFuncs)
|
||||
if !updated {
|
||||
@@ -180,7 +283,7 @@ func TestControllerUpdatingConfigmapLabelsShouldNotCreateorUpdateEnvInDeployment
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace)
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
@@ -200,12 +303,7 @@ func TestControllerUpdatingConfigmapLabelsShouldNotCreateorUpdateEnvInDeployment
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDeploymentItems,
|
||||
ContainersFunc: callbacks.GetDeploymentContainers,
|
||||
UpdateFunc: callbacks.UpdateDeployment,
|
||||
ResourceType: "Deployment",
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, deploymentFuncs)
|
||||
if updated {
|
||||
t.Errorf("Deployment should not be updated by changing label")
|
||||
@@ -226,7 +324,66 @@ func TestControllerUpdatingConfigmapLabelsShouldNotCreateorUpdateEnvInDeployment
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Perform rolling upgrade on secret and create a env var upon updating the secret
|
||||
// Perform rolling upgrade on pod and create a env var upon creating the secret
|
||||
func TestControllerCreatingSecretShouldCreateEnvInDeployment(t *testing.T) {
|
||||
// Creating secret
|
||||
secretName := secretNamePrefix + "-create-" + testutil.RandSeq(5)
|
||||
_, err := testutil.CreateSecret(client, namespace, secretName, data)
|
||||
if err != nil {
|
||||
t.Errorf("Error in secret creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
|
||||
//Deleting Secret
|
||||
err = testutil.DeleteSecret(client, namespace, secretName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the secret %v", err)
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
_, err = testutil.CreateSecret(client, namespace, secretName, newData)
|
||||
if err != nil {
|
||||
t.Errorf("Error in secret creation: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Verifying Upgrade
|
||||
logrus.Infof("Verifying env var has been created")
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.SecretResourceType, namespace, secretName, newData)
|
||||
config := util.Config{
|
||||
Namespace: namespace,
|
||||
ResourceName: secretName,
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
time.Sleep(5 * time.Second)
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, deploymentFuncs)
|
||||
if !updated {
|
||||
t.Errorf("Deployment was not updated")
|
||||
}
|
||||
|
||||
// Deleting Deployment
|
||||
err = testutil.DeleteDeployment(client, namespace, secretName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the deployment %v", err)
|
||||
}
|
||||
|
||||
//Deleting Secret
|
||||
err = testutil.DeleteSecret(client, namespace, secretName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the secret %v", err)
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Perform rolling upgrade on pod and create a env var upon updating the secret
|
||||
func TestControllerUpdatingSecretShouldCreateEnvInDeployment(t *testing.T) {
|
||||
// Creating secret
|
||||
secretName := secretNamePrefix + "-update-" + testutil.RandSeq(5)
|
||||
@@ -236,7 +393,7 @@ func TestControllerUpdatingSecretShouldCreateEnvInDeployment(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace)
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
@@ -256,12 +413,7 @@ func TestControllerUpdatingSecretShouldCreateEnvInDeployment(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDeploymentItems,
|
||||
ContainersFunc: callbacks.GetDeploymentContainers,
|
||||
UpdateFunc: callbacks.UpdateDeployment,
|
||||
ResourceType: "Deployment",
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, deploymentFuncs)
|
||||
if !updated {
|
||||
t.Errorf("Deployment was not updated")
|
||||
@@ -291,7 +443,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInDeployment(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace)
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
@@ -317,12 +469,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInDeployment(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDeploymentItems,
|
||||
ContainersFunc: callbacks.GetDeploymentContainers,
|
||||
UpdateFunc: callbacks.UpdateDeployment,
|
||||
ResourceType: "Deployment",
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, deploymentFuncs)
|
||||
if !updated {
|
||||
t.Errorf("Deployment was not updated")
|
||||
@@ -342,7 +489,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInDeployment(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Do not Perform rolling upgrade on secret and create or update a env var upon updating the label in secret
|
||||
// Do not Perform rolling upgrade on pod and create or update a env var upon updating the label in secret
|
||||
func TestControllerUpdatingSecretLabelsShouldNotCreateorUpdateEnvInDeployment(t *testing.T) {
|
||||
// Creating secret
|
||||
secretName := secretNamePrefix + "-update-" + testutil.RandSeq(5)
|
||||
@@ -352,7 +499,7 @@ func TestControllerUpdatingSecretLabelsShouldNotCreateorUpdateEnvInDeployment(t
|
||||
}
|
||||
|
||||
// Creating deployment
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace)
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in deployment creation: %v", err)
|
||||
}
|
||||
@@ -371,12 +518,7 @@ func TestControllerUpdatingSecretLabelsShouldNotCreateorUpdateEnvInDeployment(t
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
deploymentFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDeploymentItems,
|
||||
ContainersFunc: callbacks.GetDeploymentContainers,
|
||||
UpdateFunc: callbacks.UpdateDeployment,
|
||||
ResourceType: "Deployment",
|
||||
}
|
||||
deploymentFuncs := handler.GetDeploymentRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, deploymentFuncs)
|
||||
if updated {
|
||||
t.Errorf("Deployment should not be updated by changing label in secret")
|
||||
@@ -406,7 +548,7 @@ func TestControllerUpdatingConfigmapShouldCreateEnvInDaemonSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating DaemonSet
|
||||
_, err = testutil.CreateDaemonSet(client, configmapName, namespace)
|
||||
_, err = testutil.CreateDaemonSet(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in DaemonSet creation: %v", err)
|
||||
}
|
||||
@@ -426,12 +568,7 @@ func TestControllerUpdatingConfigmapShouldCreateEnvInDaemonSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
daemonSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDaemonSetItems,
|
||||
ContainersFunc: callbacks.GetDaemonSetContainers,
|
||||
UpdateFunc: callbacks.UpdateDaemonSet,
|
||||
ResourceType: "DaemonSet",
|
||||
}
|
||||
daemonSetFuncs := handler.GetDaemonSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, daemonSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("DaemonSet was not updated")
|
||||
@@ -462,7 +599,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateDaemonSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating DaemonSet
|
||||
_, err = testutil.CreateDaemonSet(client, configmapName, namespace)
|
||||
_, err = testutil.CreateDaemonSet(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in DaemonSet creation: %v", err)
|
||||
}
|
||||
@@ -473,12 +610,16 @@ func TestControllerForUpdatingConfigmapShouldUpdateDaemonSet(t *testing.T) {
|
||||
t.Errorf("Configmap was not updated")
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Updating configmap for second time
|
||||
updateErr = testutil.UpdateConfigMap(configmapClient, namespace, configmapName, "", "aurorasolutions.io")
|
||||
if updateErr != nil {
|
||||
t.Errorf("Configmap was not updated")
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Verifying DaemonSet update
|
||||
logrus.Infof("Verifying env var has been updated")
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapName, "aurorasolutions.io")
|
||||
@@ -488,12 +629,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateDaemonSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
daemonSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDaemonSetItems,
|
||||
ContainersFunc: callbacks.GetDaemonSetContainers,
|
||||
UpdateFunc: callbacks.UpdateDaemonSet,
|
||||
ResourceType: "DaemonSet",
|
||||
}
|
||||
daemonSetFuncs := handler.GetDaemonSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, daemonSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("DaemonSet was not updated")
|
||||
@@ -514,7 +650,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateDaemonSet(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Perform rolling upgrade on secret and create a env var upon updating the secret
|
||||
// Perform rolling upgrade on pod and create a env var upon updating the secret
|
||||
func TestControllerUpdatingSecretShouldCreateEnvInDaemonSet(t *testing.T) {
|
||||
// Creating secret
|
||||
secretName := secretNamePrefix + "-update-" + testutil.RandSeq(5)
|
||||
@@ -524,7 +660,7 @@ func TestControllerUpdatingSecretShouldCreateEnvInDaemonSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating DaemonSet
|
||||
_, err = testutil.CreateDaemonSet(client, secretName, namespace)
|
||||
_, err = testutil.CreateDaemonSet(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in DaemonSet creation: %v", err)
|
||||
}
|
||||
@@ -544,12 +680,7 @@ func TestControllerUpdatingSecretShouldCreateEnvInDaemonSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
daemonSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDaemonSetItems,
|
||||
ContainersFunc: callbacks.GetDaemonSetContainers,
|
||||
UpdateFunc: callbacks.UpdateDaemonSet,
|
||||
ResourceType: "DaemonSet",
|
||||
}
|
||||
daemonSetFuncs := handler.GetDaemonSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, daemonSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("DaemonSet was not updated")
|
||||
@@ -579,7 +710,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInDaemonSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating DaemonSet
|
||||
_, err = testutil.CreateDaemonSet(client, secretName, namespace)
|
||||
_, err = testutil.CreateDaemonSet(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in DaemonSet creation: %v", err)
|
||||
}
|
||||
@@ -606,12 +737,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInDaemonSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
daemonSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDaemonSetItems,
|
||||
ContainersFunc: callbacks.GetDaemonSetContainers,
|
||||
UpdateFunc: callbacks.UpdateDaemonSet,
|
||||
ResourceType: "DaemonSet",
|
||||
}
|
||||
daemonSetFuncs := handler.GetDaemonSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, daemonSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("DaemonSet was not updated")
|
||||
@@ -631,7 +757,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInDaemonSet(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Do not Perform rolling upgrade on secret and create or update a env var upon updating the label in secret
|
||||
// Do not Perform rolling upgrade on pod and create or update a env var upon updating the label in secret
|
||||
func TestControllerUpdatingSecretLabelsShouldNotCreateorUpdateEnvInDaemonSet(t *testing.T) {
|
||||
// Creating secret
|
||||
secretName := secretNamePrefix + "-update-" + testutil.RandSeq(5)
|
||||
@@ -641,7 +767,7 @@ func TestControllerUpdatingSecretLabelsShouldNotCreateorUpdateEnvInDaemonSet(t *
|
||||
}
|
||||
|
||||
// Creating DaemonSet
|
||||
_, err = testutil.CreateDaemonSet(client, secretName, namespace)
|
||||
_, err = testutil.CreateDaemonSet(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in DaemonSet creation: %v", err)
|
||||
}
|
||||
@@ -660,12 +786,7 @@ func TestControllerUpdatingSecretLabelsShouldNotCreateorUpdateEnvInDaemonSet(t *
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
daemonSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDaemonSetItems,
|
||||
ContainersFunc: callbacks.GetDaemonSetContainers,
|
||||
UpdateFunc: callbacks.UpdateDaemonSet,
|
||||
ResourceType: "DaemonSet",
|
||||
}
|
||||
daemonSetFuncs := handler.GetDaemonSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, daemonSetFuncs)
|
||||
if updated {
|
||||
t.Errorf("DaemonSet should not be updated by changing label in secret")
|
||||
@@ -695,7 +816,7 @@ func TestControllerUpdatingConfigmapShouldCreateEnvInStatefulSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating StatefulSet
|
||||
_, err = testutil.CreateStatefulSet(client, configmapName, namespace)
|
||||
_, err = testutil.CreateStatefulSet(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in StatefulSet creation: %v", err)
|
||||
}
|
||||
@@ -715,12 +836,7 @@ func TestControllerUpdatingConfigmapShouldCreateEnvInStatefulSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
statefulSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetStatefulSetItems,
|
||||
ContainersFunc: callbacks.GetStatefulsetContainers,
|
||||
UpdateFunc: callbacks.UpdateStatefulset,
|
||||
ResourceType: "StatefulSet",
|
||||
}
|
||||
statefulSetFuncs := handler.GetStatefulSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, statefulSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("StatefulSet was not updated")
|
||||
@@ -751,7 +867,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateStatefulSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating StatefulSet
|
||||
_, err = testutil.CreateStatefulSet(client, configmapName, namespace)
|
||||
_, err = testutil.CreateStatefulSet(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in StatefulSet creation: %v", err)
|
||||
}
|
||||
@@ -777,12 +893,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateStatefulSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.ConfigmapUpdateOnChangeAnnotation,
|
||||
}
|
||||
statefulSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetStatefulSetItems,
|
||||
ContainersFunc: callbacks.GetStatefulsetContainers,
|
||||
UpdateFunc: callbacks.UpdateStatefulset,
|
||||
ResourceType: "StatefulSet",
|
||||
}
|
||||
statefulSetFuncs := handler.GetStatefulSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.ConfigmapEnvVarPostfix, statefulSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("StatefulSet was not updated")
|
||||
@@ -803,7 +914,7 @@ func TestControllerForUpdatingConfigmapShouldUpdateStatefulSet(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
// Perform rolling upgrade on secret and create a env var upon updating the secret
|
||||
// Perform rolling upgrade on pod and create a env var upon updating the secret
|
||||
func TestControllerUpdatingSecretShouldCreateEnvInStatefulSet(t *testing.T) {
|
||||
// Creating secret
|
||||
secretName := secretNamePrefix + "-update-" + testutil.RandSeq(5)
|
||||
@@ -813,7 +924,7 @@ func TestControllerUpdatingSecretShouldCreateEnvInStatefulSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating StatefulSet
|
||||
_, err = testutil.CreateStatefulSet(client, secretName, namespace)
|
||||
_, err = testutil.CreateStatefulSet(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in StatefulSet creation: %v", err)
|
||||
}
|
||||
@@ -833,12 +944,7 @@ func TestControllerUpdatingSecretShouldCreateEnvInStatefulSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
statefulSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetStatefulSetItems,
|
||||
ContainersFunc: callbacks.GetStatefulsetContainers,
|
||||
UpdateFunc: callbacks.UpdateStatefulset,
|
||||
ResourceType: "StatefulSet",
|
||||
}
|
||||
statefulSetFuncs := handler.GetStatefulSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, statefulSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("StatefulSet was not updated")
|
||||
@@ -868,7 +974,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInStatefulSet(t *testing.T) {
|
||||
}
|
||||
|
||||
// Creating StatefulSet
|
||||
_, err = testutil.CreateStatefulSet(client, secretName, namespace)
|
||||
_, err = testutil.CreateStatefulSet(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
t.Errorf("Error in StatefulSet creation: %v", err)
|
||||
}
|
||||
@@ -894,12 +1000,7 @@ func TestControllerUpdatingSecretShouldUpdateEnvInStatefulSet(t *testing.T) {
|
||||
SHAValue: shaData,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
}
|
||||
statefulSetFuncs := callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetStatefulSetItems,
|
||||
ContainersFunc: callbacks.GetStatefulsetContainers,
|
||||
UpdateFunc: callbacks.UpdateStatefulset,
|
||||
ResourceType: "StatefulSet",
|
||||
}
|
||||
statefulSetFuncs := handler.GetStatefulSetRollingUpgradeFuncs()
|
||||
updated := testutil.VerifyResourceUpdate(client, config, constants.SecretEnvVarPostfix, statefulSetFuncs)
|
||||
if !updated {
|
||||
t.Errorf("StatefulSet was not updated")
|
||||
|
||||
@@ -2,6 +2,8 @@ package handler
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stakater/Reloader/internal/pkg/util"
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// ResourceCreatedHandler contains new objects
|
||||
@@ -13,6 +15,25 @@ type ResourceCreatedHandler struct {
|
||||
func (r ResourceCreatedHandler) Handle() error {
|
||||
if r.Resource == nil {
|
||||
logrus.Errorf("Resource creation handler received nil resource")
|
||||
} else {
|
||||
config, _ := r.GetConfig()
|
||||
logrus.Infof("Resource '%s' of type '%s' in namespace '%s' has been created", config.ResourceName, config.Type, config.Namespace)
|
||||
// process resource based on its type
|
||||
doRollingUpgrade(config)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
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/util"
|
||||
"github.com/stakater/Reloader/pkg/kube"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// ResourceUpdatedHandler contains updated objects
|
||||
@@ -25,162 +17,28 @@ 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)
|
||||
logrus.Infof("Changes detected in '%s' of type '%s' in namespace '%s'", config.ResourceName, config.Type, 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)
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
191
internal/pkg/handler/upgrade.go
Normal file
191
internal/pkg/handler/upgrade.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"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/util"
|
||||
"github.com/stakater/Reloader/pkg/kube"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// GetDeploymentRollingUpgradeFuncs returns all callback funcs for a deployment
|
||||
func GetDeploymentRollingUpgradeFuncs() callbacks.RollingUpgradeFuncs {
|
||||
return callbacks.RollingUpgradeFuncs{
|
||||
ItemsFunc: callbacks.GetDeploymentItems,
|
||||
ContainersFunc: callbacks.GetDeploymentContainers,
|
||||
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,
|
||||
ContainersFunc: callbacks.GetDaemonSetContainers,
|
||||
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,
|
||||
ContainersFunc: callbacks.GetStatefulsetContainers,
|
||||
UpdateFunc: callbacks.UpdateStatefulset,
|
||||
VolumesFunc: callbacks.GetStatefulsetVolumes,
|
||||
ResourceType: "StatefulSet",
|
||||
}
|
||||
}
|
||||
|
||||
func doRollingUpgrade(config util.Config) {
|
||||
rollingUpgrade(config, GetDeploymentRollingUpgradeFuncs())
|
||||
rollingUpgrade(config, GetDaemonSetRollingUpgradeFuncs())
|
||||
rollingUpgrade(config, GetStatefulSetRollingUpgradeFuncs())
|
||||
}
|
||||
|
||||
func rollingUpgrade(config util.Config, upgradeFuncs callbacks.RollingUpgradeFuncs) {
|
||||
client, err := kube.GetClient()
|
||||
if err != nil {
|
||||
logrus.Fatalf("Unable to create Kubernetes client error = %v", err)
|
||||
}
|
||||
|
||||
err = PerformRollingUpgrade(client, config, upgradeFuncs)
|
||||
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(client kubernetes.Interface, config util.Config, upgradeFuncs callbacks.RollingUpgradeFuncs) error {
|
||||
items := upgradeFuncs.ItemsFunc(client, config.Namespace)
|
||||
var err error
|
||||
for _, i := range items {
|
||||
containers := upgradeFuncs.ContainersFunc(i)
|
||||
volumes := upgradeFuncs.VolumesFunc(i)
|
||||
// find correct annotation and update the resource
|
||||
annotationValue := util.ToObjectMeta(i).Annotations[config.Annotation]
|
||||
reloaderEnabledValue := util.ToObjectMeta(i).Annotations[constants.ReloaderAutoAnnotation]
|
||||
if len(containers) > 0 {
|
||||
resourceName := util.ToObjectMeta(i).Name
|
||||
result := constants.NotUpdated
|
||||
reloaderEnabled, err := strconv.ParseBool(reloaderEnabledValue)
|
||||
if err == nil && reloaderEnabled {
|
||||
result = updateContainers(volumes, containers, config.ResourceName, config)
|
||||
} else if annotationValue != "" {
|
||||
values := strings.Split(annotationValue, ",")
|
||||
for _, value := range values {
|
||||
if value == config.ResourceName {
|
||||
result = updateContainers(volumes, containers, value, config)
|
||||
if result == constants.Updated {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if result == constants.Updated {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getVolumeMountName(volumes []v1.Volume, mountType string, volumeName string) string {
|
||||
for i := range volumes {
|
||||
if mountType == constants.ConfigmapEnvVarPostfix && volumes[i].ConfigMap != nil && volumes[i].ConfigMap.Name == volumeName {
|
||||
return volumes[i].Name
|
||||
} else if mountType == constants.SecretEnvVarPostfix && volumes[i].Secret != nil && volumes[i].Secret.SecretName == volumeName {
|
||||
return volumes[i].Name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getContainerToUpdate(volumes []v1.Volume, containers []v1.Container, envarPostfix string, volumeName string) *v1.Container {
|
||||
// Get the volumeMountName to find volumeMount in container
|
||||
if len(volumes) > 0 {
|
||||
volumeMountName := getVolumeMountName(volumes, envarPostfix, volumeName)
|
||||
// Get the container with mounted configmap/secret
|
||||
if volumeMountName != "" {
|
||||
for i := range containers {
|
||||
volumeMounts := containers[i].VolumeMounts
|
||||
for j := range volumeMounts {
|
||||
if volumeMounts[j].Name == volumeMountName {
|
||||
return &containers[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the container with referenced secret or configmap
|
||||
for i := range containers {
|
||||
envs := containers[i].Env
|
||||
for j := range envs {
|
||||
envVarSource := envs[j].ValueFrom
|
||||
if envVarSource != nil {
|
||||
if envVarSource.SecretKeyRef != nil && envVarSource.SecretKeyRef.LocalObjectReference.Name == volumeName {
|
||||
return &containers[i]
|
||||
} else if envVarSource.ConfigMapKeyRef != nil && envVarSource.ConfigMapKeyRef.LocalObjectReference.Name == volumeName {
|
||||
return &containers[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateContainers(volumes []v1.Volume, containers []v1.Container, annotationValue string, config util.Config) constants.Result {
|
||||
var result constants.Result
|
||||
envar := constants.EnvVarPrefix + util.ConvertToEnvVarName(annotationValue) + "_" + config.Type
|
||||
container := getContainerToUpdate(volumes, containers, config.Type, config.ResourceName)
|
||||
|
||||
if container == nil {
|
||||
return constants.NoContainerFound
|
||||
}
|
||||
|
||||
//update if env var exists
|
||||
result = updateEnvVar(containers, 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
|
||||
}
|
||||
413
internal/pkg/handler/upgrade_test.go
Normal file
413
internal/pkg/handler/upgrade_test.go
Normal file
@@ -0,0 +1,413 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"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)
|
||||
configmapWithEnvName = "testconfigmapWithEnv-handler-" + testutil.RandSeq(3)
|
||||
secretWithEnvName = "testsecretWithEnv-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)
|
||||
}
|
||||
|
||||
_, err = testutil.CreateConfigMap(client, namespace, configmapWithEnvName, "www.google.com")
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in configmap creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating secret
|
||||
_, err = testutil.CreateSecret(client, namespace, secretWithEnvName, data)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in secret creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating Deployment with configmap
|
||||
_, err = testutil.CreateDeployment(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in Deployment with configmap creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating Deployment with secret
|
||||
_, err = testutil.CreateDeployment(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in Deployment with secret creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating Deployment with env var source as configmap
|
||||
_, err = testutil.CreateDeployment(client, configmapWithEnvName, namespace, false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in Deployment with configmap configmap as env var source creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating Deployment with env var source as secret
|
||||
_, err = testutil.CreateDeployment(client, secretWithEnvName, namespace, false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in Deployment with secret configmap as env var source creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating DaemonSet with configmap
|
||||
_, err = testutil.CreateDaemonSet(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in DaemonSet with configmap creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating DaemonSet with secret
|
||||
_, err = testutil.CreateDaemonSet(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in DaemonSet with secret creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating DaemonSet with env var source as configmap
|
||||
_, err = testutil.CreateDaemonSet(client, configmapWithEnvName, namespace, false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in DaemonSet with configmap as env var source creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating DaemonSet with env var source as secret
|
||||
_, err = testutil.CreateDaemonSet(client, secretWithEnvName, namespace, false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in DaemonSet with secret configmap as env var source creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating StatefulSet with configmap
|
||||
_, err = testutil.CreateStatefulSet(client, configmapName, namespace, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in StatefulSet with configmap creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating StatefulSet with secret
|
||||
_, err = testutil.CreateStatefulSet(client, secretName, namespace, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in StatefulSet with secret creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating StatefulSet with env var source as configmap
|
||||
_, err = testutil.CreateStatefulSet(client, configmapWithEnvName, namespace, false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in StatefulSet with configmap configmap as env var source creation: %v", err)
|
||||
}
|
||||
|
||||
// Creating StatefulSet with env var source as secret
|
||||
_, err = testutil.CreateStatefulSet(client, secretWithEnvName, namespace, false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error in StatefulSet with secret configmap as env var source 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 Deployment with configmap as env var source
|
||||
deploymentError = testutil.DeleteDeployment(client, namespace, configmapWithEnvName)
|
||||
if deploymentError != nil {
|
||||
logrus.Errorf("Error while deleting deployment with configmap as env var source %v", deploymentError)
|
||||
}
|
||||
|
||||
// Deleting Deployment with secret
|
||||
deploymentError = testutil.DeleteDeployment(client, namespace, secretWithEnvName)
|
||||
if deploymentError != nil {
|
||||
logrus.Errorf("Error while deleting deployment with secret as env var source %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 Deployment with configmap as env var source
|
||||
daemonSetError = testutil.DeleteDaemonSet(client, namespace, configmapWithEnvName)
|
||||
if daemonSetError != nil {
|
||||
logrus.Errorf("Error while deleting daemonSet with configmap as env var source %v", daemonSetError)
|
||||
}
|
||||
|
||||
// Deleting Deployment with secret as env var source
|
||||
daemonSetError = testutil.DeleteDaemonSet(client, namespace, secretWithEnvName)
|
||||
if daemonSetError != nil {
|
||||
logrus.Errorf("Error while deleting daemonSet with secret as env var source %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 StatefulSet with configmap as env var source
|
||||
statefulSetError = testutil.DeleteStatefulSet(client, namespace, configmapWithEnvName)
|
||||
if statefulSetError != nil {
|
||||
logrus.Errorf("Error while deleting statefulSet with configmap as env var source %v", statefulSetError)
|
||||
}
|
||||
|
||||
// Deleting Deployment with secret as env var source
|
||||
statefulSetError = testutil.DeleteStatefulSet(client, namespace, secretWithEnvName)
|
||||
if statefulSetError != nil {
|
||||
logrus.Errorf("Error while deleting statefulSet with secret as env var source %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 Configmap used as env var source
|
||||
err = testutil.DeleteConfigMap(client, namespace, configmapWithEnvName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the configmap used as env var source %v", err)
|
||||
}
|
||||
|
||||
// Deleting Secret used as env var source
|
||||
err = testutil.DeleteSecret(client, namespace, secretWithEnvName)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error while deleting the secret used as env var source %v", err)
|
||||
}
|
||||
|
||||
// Deleting namespace
|
||||
testutil.DeleteNamespace(namespace, client)
|
||||
|
||||
}
|
||||
|
||||
func getConfigWithAnnotations(resourceType string, name string, shaData string, annotation string) util.Config {
|
||||
return util.Config{
|
||||
Namespace: namespace,
|
||||
ResourceName: name,
|
||||
SHAValue: shaData,
|
||||
Annotation: annotation,
|
||||
Type: resourceType,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestRollingUpgradeForDeploymentWithConfigmap(t *testing.T) {
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapName, "www.stakater.com")
|
||||
config := getConfigWithAnnotations(constants.ConfigmapEnvVarPostfix, configmapName, shaData, constants.ConfigmapUpdateOnChangeAnnotation)
|
||||
deploymentFuncs := GetDeploymentRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, 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 TestRollingUpgradeForDeploymentWithConfigmapAsEnvVar(t *testing.T) {
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapWithEnvName, "www.stakater.com")
|
||||
config := getConfigWithAnnotations(constants.ConfigmapEnvVarPostfix, configmapWithEnvName, shaData, constants.ReloaderAutoAnnotation)
|
||||
deploymentFuncs := GetDeploymentRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, deploymentFuncs)
|
||||
time.Sleep(5 * time.Second)
|
||||
if err != nil {
|
||||
t.Errorf("Rolling upgrade failed for Deployment with Configmap used as env var")
|
||||
}
|
||||
|
||||
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 := getConfigWithAnnotations(constants.SecretEnvVarPostfix, secretName, shaData, constants.SecretUpdateOnChangeAnnotation)
|
||||
deploymentFuncs := GetDeploymentRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, 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 TestRollingUpgradeForDeploymentWithSecretAsEnvVar(t *testing.T) {
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.SecretResourceType, namespace, secretWithEnvName, "dGVzdFVwZGF0ZWRTZWNyZXRFbmNvZGluZ0ZvclJlbG9hZGVy")
|
||||
config := getConfigWithAnnotations(constants.SecretEnvVarPostfix, secretWithEnvName, shaData, constants.ReloaderAutoAnnotation)
|
||||
deploymentFuncs := GetDeploymentRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, 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 := getConfigWithAnnotations(constants.ConfigmapEnvVarPostfix, configmapName, shaData, constants.ConfigmapUpdateOnChangeAnnotation)
|
||||
daemonSetFuncs := GetDaemonSetRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, 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 TestRollingUpgradeForDaemonSetWithConfigmapAsEnvVar(t *testing.T) {
|
||||
shaData := testutil.ConvertResourceToSHA(testutil.ConfigmapResourceType, namespace, configmapWithEnvName, "www.facebook.com")
|
||||
config := getConfigWithAnnotations(constants.ConfigmapEnvVarPostfix, configmapWithEnvName, shaData, constants.ReloaderAutoAnnotation)
|
||||
daemonSetFuncs := GetDaemonSetRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, daemonSetFuncs)
|
||||
time.Sleep(5 * time.Second)
|
||||
if err != nil {
|
||||
t.Errorf("Rolling upgrade failed for DaemonSet with configmap used as env var")
|
||||
}
|
||||
|
||||
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 := getConfigWithAnnotations(constants.SecretEnvVarPostfix, secretName, shaData, constants.SecretUpdateOnChangeAnnotation)
|
||||
daemonSetFuncs := GetDaemonSetRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, 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 := getConfigWithAnnotations(constants.ConfigmapEnvVarPostfix, configmapName, shaData, constants.ConfigmapUpdateOnChangeAnnotation)
|
||||
statefulSetFuncs := GetStatefulSetRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, 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 := getConfigWithAnnotations(constants.SecretEnvVarPostfix, secretName, shaData, constants.SecretUpdateOnChangeAnnotation)
|
||||
statefulSetFuncs := GetStatefulSetRollingUpgradeFuncs()
|
||||
|
||||
err := PerformRollingUpgrade(client, config, 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")
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package testutil
|
||||
import (
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -40,7 +41,7 @@ func GetClient() *kubernetes.Clientset {
|
||||
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,48 +51,153 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
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{
|
||||
constants.ReloaderAutoAnnotation: "true"}
|
||||
}
|
||||
|
||||
return map[string]string{
|
||||
constants.ConfigmapUpdateOnChangeAnnotation: name,
|
||||
constants.SecretUpdateOnChangeAnnotation: name}
|
||||
}
|
||||
|
||||
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{
|
||||
{
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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{
|
||||
{
|
||||
Name: "BUCKET_NAME",
|
||||
Value: "test",
|
||||
},
|
||||
},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
MountPath: "etc/config",
|
||||
Name: "configmap",
|
||||
},
|
||||
{
|
||||
MountPath: "etc/sec",
|
||||
Name: "secret",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "configmap",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
ConfigMap: &v1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: v1.LocalObjectReference{
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secret",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
Secret: &v1.SecretVolumeSource{
|
||||
SecretName: name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 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},
|
||||
},
|
||||
ObjectMeta: getObjectMeta(namespace, deploymentName, false),
|
||||
Spec: v1beta1.DeploymentSpec{
|
||||
Replicas: &replicaset,
|
||||
Strategy: v1beta1.DeploymentStrategy{
|
||||
Type: v1beta1.RollingUpdateDeploymentStrategyType,
|
||||
},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{"secondLabel": "temp"},
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Image: "tutum/hello-world",
|
||||
Name: deploymentName,
|
||||
Env: []v1.EnvVar{
|
||||
{
|
||||
Name: "BUCKET_NAME",
|
||||
Value: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Template: getPodTemplateSpecWithVolumes(deploymentName),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func GetDeploymentWithEnvVars(namespace string, deploymentName string) *v1beta1.Deployment {
|
||||
replicaset := int32(1)
|
||||
return &v1beta1.Deployment{
|
||||
ObjectMeta: getObjectMeta(namespace, deploymentName, true),
|
||||
Spec: v1beta1.DeploymentSpec{
|
||||
Replicas: &replicaset,
|
||||
Strategy: v1beta1.DeploymentStrategy{
|
||||
Type: v1beta1.RollingUpdateDeploymentStrategyType,
|
||||
},
|
||||
Template: getPodTemplateSpecWithEnvVars(deploymentName),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -99,37 +205,24 @@ func GetDeployment(namespace string, deploymentName string) *v1beta1.Deployment
|
||||
// GetDaemonSet provides daemonset for testing
|
||||
func GetDaemonSet(namespace string, daemonsetName string) *v1beta1.DaemonSet {
|
||||
return &v1beta1.DaemonSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: daemonsetName,
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{"firstLabel": "temp"},
|
||||
Annotations: map[string]string{
|
||||
constants.ConfigmapUpdateOnChangeAnnotation: daemonsetName,
|
||||
constants.SecretUpdateOnChangeAnnotation: daemonsetName},
|
||||
},
|
||||
ObjectMeta: getObjectMeta(namespace, daemonsetName, false),
|
||||
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: daemonsetName,
|
||||
Env: []v1.EnvVar{
|
||||
{
|
||||
Name: "BUCKET_NAME",
|
||||
Value: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Template: getPodTemplateSpecWithVolumes(daemonsetName),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func GetDaemonSetWithEnvVars(namespace string, daemonSetName string) *v1beta1.DaemonSet {
|
||||
return &v1beta1.DaemonSet{
|
||||
ObjectMeta: getObjectMeta(namespace, daemonSetName, true),
|
||||
Spec: v1beta1.DaemonSetSpec{
|
||||
UpdateStrategy: v1beta1.DaemonSetUpdateStrategy{
|
||||
Type: v1beta1.RollingUpdateDaemonSetStrategyType,
|
||||
},
|
||||
Template: getPodTemplateSpecWithEnvVars(daemonSetName),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -137,37 +230,25 @@ func GetDaemonSet(namespace string, daemonsetName string) *v1beta1.DaemonSet {
|
||||
// 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},
|
||||
},
|
||||
ObjectMeta: getObjectMeta(namespace, statefulsetName, false),
|
||||
Spec: v1_beta1.StatefulSetSpec{
|
||||
UpdateStrategy: v1_beta1.StatefulSetUpdateStrategy{
|
||||
Type: v1_beta1.RollingUpdateStatefulSetStrategyType,
|
||||
},
|
||||
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",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Template: getPodTemplateSpecWithVolumes(statefulsetName),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetStatefulSet provides statefulset for testing
|
||||
func GetStatefulSetWithEnvVar(namespace string, statefulsetName string) *v1_beta1.StatefulSet {
|
||||
return &v1_beta1.StatefulSet{
|
||||
ObjectMeta: getObjectMeta(namespace, statefulsetName, true),
|
||||
Spec: v1_beta1.StatefulSetSpec{
|
||||
UpdateStrategy: v1_beta1.StatefulSetUpdateStrategy{
|
||||
Type: v1_beta1.RollingUpdateStatefulSetStrategyType,
|
||||
},
|
||||
Template: getPodTemplateSpecWithEnvVars(statefulsetName),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -270,28 +351,46 @@ func CreateSecret(client kubernetes.Interface, namespace string, secretName stri
|
||||
}
|
||||
|
||||
// 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) (*v1beta1.Deployment, error) {
|
||||
logrus.Infof("Creating Deployment")
|
||||
deploymentClient := client.ExtensionsV1beta1().Deployments(namespace)
|
||||
deployment, err := deploymentClient.Create(GetDeployment(namespace, deploymentName))
|
||||
var deploymentObj *v1beta1.Deployment
|
||||
if volumeMount {
|
||||
deploymentObj = GetDeployment(namespace, deploymentName)
|
||||
} else {
|
||||
deploymentObj = GetDeploymentWithEnvVars(namespace, deploymentName)
|
||||
}
|
||||
deployment, err := deploymentClient.Create(deploymentObj)
|
||||
time.Sleep(10 * 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) (*v1beta1.DaemonSet, error) {
|
||||
logrus.Infof("Creating DaemonSet")
|
||||
daemonsetClient := client.ExtensionsV1beta1().DaemonSets(namespace)
|
||||
daemonset, err := daemonsetClient.Create(GetDaemonSet(namespace, daemonsetName))
|
||||
var daemonsetObj *v1beta1.DaemonSet
|
||||
if volumeMount {
|
||||
daemonsetObj = GetDaemonSet(namespace, daemonsetName)
|
||||
} else {
|
||||
daemonsetObj = GetDaemonSetWithEnvVars(namespace, daemonsetName)
|
||||
}
|
||||
daemonset, err := daemonsetClient.Create(daemonsetObj)
|
||||
time.Sleep(10 * 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) (*v1_beta1.StatefulSet, error) {
|
||||
logrus.Infof("Creating StatefulSet")
|
||||
statefulsetClient := client.AppsV1beta1().StatefulSets(namespace)
|
||||
statefulset, err := statefulsetClient.Create(GetStatefulSet(namespace, statefulsetName))
|
||||
var statefulsetObj *v1_beta1.StatefulSet
|
||||
if volumeMount {
|
||||
statefulsetObj = GetStatefulSet(namespace, statefulsetName)
|
||||
} else {
|
||||
statefulsetObj = GetStatefulSetWithEnvVar(namespace, statefulsetName)
|
||||
}
|
||||
statefulset, err := statefulsetClient.Create(statefulsetObj)
|
||||
time.Sleep(10 * time.Second)
|
||||
return statefulset, err
|
||||
}
|
||||
@@ -374,28 +473,33 @@ func RandSeq(n int) string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// VerifyResourceUpdate verifies whether the rolling upgrade happened or not
|
||||
func VerifyResourceUpdate(client kubernetes.Interface, config util.Config, envVarPostfix string, upgradeFuncs callbacks.RollingUpgradeFuncs) bool {
|
||||
items := upgradeFuncs.ItemsFunc(client, 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 != "" {
|
||||
reloaderEnabledValue := util.ToObjectMeta(i).Annotations[constants.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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"github.com/stakater/Reloader/internal/pkg/constants"
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
//Config contains rolling upgrade configuration parameters
|
||||
type Config struct {
|
||||
Namespace string
|
||||
ResourceName 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,
|
||||
Annotation: constants.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,
|
||||
Annotation: constants.SecretUpdateOnChangeAnnotation,
|
||||
SHAValue: GetSHAfromSecret(secret.Data),
|
||||
Type: constants.SecretEnvVarPostfix,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,21 @@ 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, ";"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user