Commit d68116b6 authored by gaoshiyao's avatar gaoshiyao

2.13.2

parent 2133e634
name: Integration test
on:
pull_request:
push:
jobs:
integration-test:
runs-on: ubuntu-latest
strategy:
matrix:
k8s_version: [v1.18.2, v1.17.5, v1.16.9]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Docker
uses: docker-practice/actions-setup-docker@0.0.1
with:
docker_version: 18.09
docker_channel: stable
docker_daemon_json: '{"insecure-registries":["0.0.0.0/0"]}'
- name: Create kind cluster
uses: helm/kind-action@v1.0.0-rc.1
with:
version: v0.8.1
node_image: kindest/node:${{ matrix.k8s_version }}
cluster_name: kind-cluster-${{ matrix.k8s_version }}
config: test/integration/kind-cluster.yaml
- name: Install Nginx ingress controller
run: |
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/ingress-nginx-2.3.0/deploy/static/provider/kind/deploy.yaml
kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=120s
- name: Set up Go 1.13
uses: actions/setup-go@v2
with:
go-version: 1.13
- name: Cache go mod
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Set /etc/hosts
run: |
sudo -- sh -c "echo '127.0.0.1 harbor.local' >> /etc/hosts"
sudo -- sh -c "echo '127.0.0.1 notary.harbor.local' >> /etc/hosts"
- name: Run integration tests
working-directory: ./test
run:
go test -v -timeout 30m github.com/goharbor/harbor-helm/integration
\ No newline at end of file
name: Lint
on:
pull_request:
push:
jobs:
lint:
runs-on: ubuntu-latest
strategy:
matrix:
helm_version: [3.2.3, 2.16.8]
steps:
- name: Checkout
uses: actions/checkout@v2
with:
path: harbor
- name: Set up Helm
uses: azure/setup-helm@v1
with:
version: '${{ matrix.helm_version }}'
- name: Helm version
run:
helm version -c
- name: Run lint
working-directory: ./harbor
run:
helm lint .
- name: Update dependency
working-directory: ./harbor
run:
helm dependency update .
- name: Run template for ingress expose
working-directory: ./harbor
run:
helm template --set "expose.type=ingress" --output-dir $(mktemp -d -t output-XXXXXXXXXX) .
- name: Run template for nodePort expose
working-directory: ./harbor
run:
helm template --set "expose.type=nodePort,expose.tls.auto.commonName=127.0.0.1" --output-dir $(mktemp -d -t output-XXXXXXXXXX) .
\ No newline at end of file
name: Unit test
on:
pull_request:
push:
jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Helm 3.2.3
uses: azure/setup-helm@v1
with:
version: '3.2.3'
- name: Set up Go 1.13
uses: actions/setup-go@v2
with:
go-version: 1.13
- name: Cache go mod
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Run unit tests
working-directory: ./test
run:
go test -v github.com/goharbor/harbor-helm/unittest
apiVersion: v1 apiVersion: v1
name: beagle-harbor appVersion: 2.13.2
version: 2.1.7 description: An open source trusted cloud native registry that stores, signs, and
appVersion: 2.1.7 scans content
description: An open source trusted cloud native registry that stores, signs, and scans content home: https://goharbor.io
keywords: icon: https://raw.githubusercontent.com/goharbor/website/main/static/img/logos/harbor-icon-color.png
- docker keywords:
- registry - docker
- harbor - registry
home: https://goharbor.io - harbor
icon: https://raw.githubusercontent.com/goharbor/website/master/static/img/logos/harbor-icon-color.png maintainers:
sources: - email: yan-yw.wang@broadcom.com
- https://github.com/goharbor/harbor name: Yan Wang
- https://github.com/goharbor/harbor-helm - email: wenkai.yin@broadcom.com
maintainers: name: Wenkai Yin
- name: Wenkai Yin - email: miner.yang@broadcom.com
email: yinw@vmware.com name: Miner Yang
- name: Weiwei He - email: shengwen.yu@broadcom.com
email: hweiwei@vmware.com name: Shengwen Yu
- name: Qian Deng name: harbor
email: dengq@vmware.com sources:
engine: gotpl - https://github.com/goharbor/harbor
- https://github.com/goharbor/harbor-helm
version: 1.17.2
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004
http://www.apache.org/licenses/ http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions. 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, "License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document. and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by "Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License. the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all "Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition, control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the "control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity. outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity "You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License. exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, "Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation including but not limited to software source code, documentation
source, and configuration files. source, and configuration files.
"Object" form shall mean any form resulting from mechanical "Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation, not limited to compiled object code, generated documentation,
and conversions to other media types. and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or "Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work copyright notice that is included in or attached to the work
(an example is provided in the Appendix below). (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object "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 form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of, separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof. the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including "Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner 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 or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted" the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution." designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity "Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work. subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of 2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of, copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form. Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of 3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made, (except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work, use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s) Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate granted to You under this License for that Work shall terminate
as of the date such litigation is filed. as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the 4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You modifications, and in Source or Object form, provided that You
meet the following conditions: meet the following conditions:
(a) You must give any other recipients of the Work or (a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices (b) You must cause any modified files to carry prominent notices
stating that You changed the files; and stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works (c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work, attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of excluding those notices that do not pertain to any part of
the Derivative Works; and the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its (d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or, documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed that such additional attribution notices cannot be construed
as modifying the License. as modifying the License.
You may add Your own copyright statement to Your modifications and You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use, for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License. the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, 5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions. this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions. with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade 6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor, names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file. origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or 7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS, Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License. risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, 8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise, whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the 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 (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages. has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing 9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer, the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity, and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify, of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability. of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work. APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]" boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
This source diff could not be displayed because it is too large. You can view the blob instead.
IMAGES:
harbor-portal:
NAME: harbor-portal
VERSION: 'v2.1.6'
harbor-core:
NAME: harbor-core
VERSION: 'v2.1.6'
harbor-jobservice:
NAME: harbor-jobservice
VERSION: 'v2.1.6'
harbor-db:
NAME: harbor-db
VERSION: 'v2.1.6'
harbor-registryctl:
NAME: harbor-registryctl
VERSION: 'v2.1.6'
chartmuseum:
NAME: chartmuseum
VERSION: 'v0.12.0'
clair:
NAME: clair
VERSION: 'v2.1.7'
harbor-scanner-clair:
NAME: harbor-scanner-clair
VERSION: 'v1.1.1'
harbor-scanner-trivy:
NAME: harbor-scanner-trivy
VERSION: v0.17.0
notary-server:
NAME: notary-server
VERSION: v0.6.1
notary-signer:
NAME: notary-signer
VERSION: v0.6.1
registry:
NAME: registry
VERSION: 'v2.7.1'
redis:
NAME: redis
VERSION: '6.2.6'
-----BEGIN CERTIFICATE-----
MIIE0zCCArugAwIBAgIJAPY/OzLMeVq2MA0GCSqGSIb3DQEBCwUAMAAwHhcNMTkw
NDE4MDIyNzM3WhcNMjkwNDE1MDIyNzM3WjAAMIICIjANBgkqhkiG9w0BAQEFAAOC
Ag8AMIICCgKCAgEA3xlUJs2b/aI2NLoy4OIQ+dn/yMb/O99iKDRyZKpH8rSOmS+o
F9unmSAzL65XA/v6nY0OLI/dASDjkqkBpIdTGzogR5f8UiB6osuEY7V71XZdzWLr
PjnJq6ZLAaoKmwG80W5+Wd6V8PygOx52mkr1w7IWKz+1ZLI5izbppon7XVGVRaAT
RvNZDiJ6CeJpcJ5H723lkf5RvJWatZLCYIYDbRfTiKsyQ/SlRcv5BVfHg/LJSH9Q
LGRhPMARldl9wyZCwZZDHxheI4a+26aa8MY3u9st/l0/Oo6VCTGpMiEhiGF2LVjp
UWq/+BP4SFEvJfq/DuinI139W/5aZZ7/HwRPlmYU6pXTRLyIg7jd+19fJwR7X37q
w0o8t06FhjmrCzaYCUjoReqDmHaNmZN/ddvG7jZWBu+jNh0YavsyQyCIVmv6yqSc
jPiD9uivxqTwjJidIBRfuUrz3aERQ7cQgf0qhqjIzflzHbFKhILocBWq7zyNl9hr
vUGT/WZcw0t/OtM72SPaplmTgVbbQRxf2VHzyptGIvtydlXK8thxOMpXo4e+Sl8d
1gdQcC4oisN9F29oNs8P5yFQP//xYuv8C607nCj1DzrId5avG/NVfKB/fbDKEFgN
2WhHInTzPLEcjF4fErcUAEuWW0buX/6FHCG3iTtrqyD92KTVDfN1J56rrcsCAwEA
AaNQME4wHQYDVR0OBBYEFFhNhTo4UAC2PUsf8jYaWj160vGEMB8GA1UdIwQYMBaA
FFhNhTo4UAC2PUsf8jYaWj160vGEMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggIBAMAsEtVlELMwdtcifHeOT0kOmf5wo9In/eFSgscCzBMDaRx2B3q36AoS
Il7XWAZpevaR7W7yeARKaAshBLhygUqLD0zWbKlSN9Hprd1wdpM0ffyPpN5dxOYA
er04y12GRnCbMYqi4cvztP4TinXqq2yHSYhLbO9qkI5gbWVxkRuIcMKvixddllNY
Q3obJaDDHmovM3+g/G+1YFgt4qES38XnJ7BrSshHnn5EIQh286xfJriyrK2hHbLJ
qz0YuF6G3DXPeWGgXvj0Hipc0f8UDZkKkk/eGEI6vEkytyvoepoZI2XbAf/ZMy5n
KwuhEn4hhkFMwWaSWp/h0QdMCaxk4BVSOqmNVaLSB7+FjsIj4CasFotYiyJ2gpRB
Nf8QaS4bz0Tn1eBbC8ksj+e3ZWeX2b5wVMjql9jTt2X1ICs8KKe3vEBkjqT2AUi2
52TtKzm73aWrz/GPy/Q2LCor3Fh9FGVSBOBBDXGy6MJpNHJnYVH9EENFGOh85ol1
2pADOBB5vAU/kLB5LHPj2kue/FMiHaNnrSYIGrMlBSX2jj9EYa1uuUH+pd4MBj1F
5uH8ORiaQ6ht2+WHklxic1Rj5yTYQwVlH70CBOn+qVEdo63yQwzAMJKFIwlGUQEX
jiljgc86q4cZtUTFrcwMidbk+8Q6+JbDVg7HV/+pnC+wnv197kwe
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEA3xlUJs2b/aI2NLoy4OIQ+dn/yMb/O99iKDRyZKpH8rSOmS+o
F9unmSAzL65XA/v6nY0OLI/dASDjkqkBpIdTGzogR5f8UiB6osuEY7V71XZdzWLr
PjnJq6ZLAaoKmwG80W5+Wd6V8PygOx52mkr1w7IWKz+1ZLI5izbppon7XVGVRaAT
RvNZDiJ6CeJpcJ5H723lkf5RvJWatZLCYIYDbRfTiKsyQ/SlRcv5BVfHg/LJSH9Q
LGRhPMARldl9wyZCwZZDHxheI4a+26aa8MY3u9st/l0/Oo6VCTGpMiEhiGF2LVjp
UWq/+BP4SFEvJfq/DuinI139W/5aZZ7/HwRPlmYU6pXTRLyIg7jd+19fJwR7X37q
w0o8t06FhjmrCzaYCUjoReqDmHaNmZN/ddvG7jZWBu+jNh0YavsyQyCIVmv6yqSc
jPiD9uivxqTwjJidIBRfuUrz3aERQ7cQgf0qhqjIzflzHbFKhILocBWq7zyNl9hr
vUGT/WZcw0t/OtM72SPaplmTgVbbQRxf2VHzyptGIvtydlXK8thxOMpXo4e+Sl8d
1gdQcC4oisN9F29oNs8P5yFQP//xYuv8C607nCj1DzrId5avG/NVfKB/fbDKEFgN
2WhHInTzPLEcjF4fErcUAEuWW0buX/6FHCG3iTtrqyD92KTVDfN1J56rrcsCAwEA
AQKCAgEAk8q8s4PrvYby79UVlWJNKqceykwBkxE1fjrYORWQ2hiAirxGV5+8lDT/
k6ujm1EWwb5K0HxxRKkb+PEa1HqNNHE6JxNpJKK9exDlYAQ+x7dFBqVr/2nazmo4
MB8MLYlmIztWWoSYwe8o2mEg4q+bxYs5Imdu7AkhE7dJ63hm23gLMfeMLalRqopu
XBPwE5nXP6aGuUNHtG1K8tQJDlZY+LEbAeOfReNQhT9NdRukYSW579vfKblJrSvz
ulg89sVm3cWEK5pB6rj9wJbK94voKftVqbbuBwWjd1a9pibKhwVBe2L2FWhpSZc5
F/coC7njTaYT6tr91y5VhhJhIZQCf/vv4Zl5XhFHs5VTZNbM/OfqyFQLYXVJO48K
F7tmazAEQQBQwVZqH9C9NQdzPHWmc38Okhtc1wzaqn/rg9+1sgAMD8hWCtQJUe97
b9ymh5A0Z4QXKpyFT0b+pXcD1jRha07UtkX+/zLJ9HpAXcUmzkG+j5CXNpnxsIq5
fJFeq3hBj9w6n4h+50M4W0Fse5YoEUsc3B0fz8BlQBb+YJLFLNH34MH8p1l0ZDYJ
yae0psxlBijg4OPZ+WCBa+jtFW4LiWgEcxwgz8w+hEOAQr2a1Dc7w8jd+Y4IK8Um
lTVs5dbp4mOmPMlRv/GM7kDudFqbMg3YFwXg3QbquVqLZzEzjVkCggEBAPJKZbCW
YfLejkS/fkRyV3VIb54mKwQHoMWub88tPgGuXzjsJyd5QTQ58PpUjXrLHmn8lS2+
viE8GJylKwN1yMlZw40+kZhpHUpCWx/2ZKjAqvqA9OOKo2fv6Hd/wOAnU4CtioC1
pri7lKFYXoP8DtQVwHYvIzCRqDnhc4mwJDqzTC9xduI+svxzl4xH82fx0jrPiFY+
/wOdXjyfIPjyhHC4jPTWbairwXS9dBjSl128aIRT580/yXE/SYAugg05jKtg5zQA
So13MTezXRHXdO0di3tEMHGREEkFpeVnnPQvCCedK0DV36iNwiWc8pwdfLMVneTt
DKwZedCx+o/7ev0CggEBAOu48DGEJJJzHxVR5mY1K2AlZyYtpTOWehK1zX74JvM3
YxN4nd+Zx5n9uSPmmKzqF3TU+44RVtdJK6ejoFE8dMDTNWaSLW/ZDmN1nT0njvOn
IWJn59ynOChWWKZgXZ/9UqGR7Pt6OxSkkex9c/fYBsMX/xusdXQigeogl0iOYVFW
gXIiiLRLHpHJsK/uNxIizj0hTYYn7uD7PRENwFRcCYf8J1eUFbd6DuCVWeQCKWgf
Nd2tSWoi0Vylj4uUX8Iw0tjLNMD5CREJEk4GSv4EDSmvUdv1LiBKJCL2lEcgoPeC
oOD2iCc5KqgnmQraRilFFk8RVXA9PWZGY3C0b6TVmmcCggEANZO2AOKALlCAbTtb
FI+kP08RP4t5H58AMjZsiweaGo0QiWnPDq+Fd6MIYpKn5mtcAlvUMRVovbioSJtN
c6psB/pNf8JCN82mqHEb7WlywM46AMLbZCWYFLe8VBBv+iE4GdBGPEfu4hK4vyTn
YZAvRz64HGo4Adlztbjg76V/nWtggW05uLXcpm55KJAQhv+2WULjBw9PHOGDoSwf
Am2+U567rLht70prsQDj10laJ2QuSHS1YXGlfeFcw3eFUp9TN+JpvdoCol2lCIgl
IHjgZj6ORWfCvpoxW7RgBuZukqCD0R60HdYtavxN3jtiepsapA83pxO0JapMgZWZ
rpURkQKCAQBOcEv9Liu9T/GX9pjkiezVIZ0hZy8B66DTeQvYpFrRtCyT3h8quNFi
vLtO5v0HDR6hEf5jWAG9wet07U37ulJfl+i9KQdVoLTZA9o+71ryWTsSs+DD3CEj
yxfUxVxiULmeaiChzhq608h7GYPthUU6xlFttAWhj5oLfqzYyAg6OL76a+Nxm02g
1ayl3m8U6eAXF23kpoUm+HNpqVnGuJmzVoUA75YKZ+NreEdhSBbfPwN9sJwtZUil
u7H4kHcM95Ix8eysCjKqKIqezBlITbDTnjNvLjcbJ5C+0a6lvIXT1vQR5/eGlc9M
BWE360pNkV/LD8mOf9Jepi2Q43oDL9EhAoIBAQDTWImfy0K9gGzA2rPy169mWYQK
OlcnD3+hQq6x51Zn1e/texFeVlhHn4rrnRdCFOAp47uFkJ2m72GCVD74EwQucK9y
AD5jorqgVHqCKZdkHjb2V60Mzm6g3rtL9WJXFVLvNBb/QGB2vgHVOO0zqiqGZj4e
Ex7l2m//5SE4DLtn70J9CgG1HtXCS8dWrGPL1pzDnk8VXtnoXzb0LChLUFEgZRmh
cV6AFHEK2H8wBHviNyehsRQiDkl2AiWOcJNvkzW68ck2nJjRWyPYK1JL3NCKpB3Q
OohrP0fHcWAXMW97wFXZhRfnQfDxxIOlj3McYT0AlanXd0F4NGc2Nvmphx04
-----END RSA PRIVATE KEY-----
clair:
database:
type: pgsql
options:
source: "{{ template "harbor.database.clair" . }}"
# Number of elements kept in the cache
# Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database.
cachesize: 16384
api:
# API server port
port: 6060
healthport: 6061
# Deadline before an API request will respond with a 503
timeout: 300s
updater:
interval: {{ .Values.clair.updatersInterval }}h
{
"server": {
"http_addr": ":4443"
},
"trust_service": {
"type": "remote",
"hostname": "{{ template "harbor.notary-signer" . }}",
"port": "7899",
"tls_ca_file": "/etc/ssl/notary/ca.crt",
"key_algorithm": "ecdsa"
},
"logging": {
"level": "{{ .Values.logLevel }}"
},
"storage": {
"backend": "postgres",
"db_url": "{{ template "harbor.database.notaryServer" . }}"
},
"auth": {
"type": "token",
"options": {
"realm": "{{ .Values.externalURL }}.{{ $.Values.global.host }}/service/token",
"service": "harbor-notary",
"issuer": "harbor-token-issuer",
"rootcertbundle": "/root.crt"
}
}
}
\ No newline at end of file
{
"server": {
"grpc_addr": ":7899",
"tls_cert_file": "/etc/ssl/notary/tls.crt",
"tls_key_file": "/etc/ssl/notary/tls.key"
},
"logging": {
"level": "{{ .Values.logLevel }}"
},
"storage": {
"backend": "postgres",
"db_url": "{{ template "harbor.database.notarySigner" . }}",
"default_alias": "defaultalias"
}
}
\ No newline at end of file
---
title: Harbor High Availability Guide
---
## Goal
Deploy Harbor on K8S via helm to make it highly available, that is, if one of node that has Harbor's container running becomes un accessible. Users does not experience interrupt of service of Harbor.
## Prerequisites
- Kubernetes cluster 1.10+
- Helm 2.10.0+
- High available ingress controller (Harbor does not manage the external endpoint)
- High available PostgreSQL database (Harbor does not handle the deployment of HA of database)
- High available Redis (Harbor does not handle the deployment of HA of Redis)
- PVC that can be shared across nodes or external object storage
## Architecture
Most of Harbor's components are stateless now. So we can simply increase the replica of the pods to make sure the components are distributed to multiple worker nodes, and leverage the "Service" mechanism of K8S to ensure the connectivity across pods.
As for storage layer, it is expected that the user provide high available PostgreSQL, Redis cluster for application data and PVCs or object storage for storing images and charts.
![HA](img/ha.png)
## Usage
### Download Chart
Download Harbor helm chart:
```bash
helm repo add harbor https://helm.goharbor.io
helm fetch harbor/harbor --untar
```
### Configuration
Configure the followings items in `values.yaml`, you can also set them as parameters via `--set` flag during running `helm install`:
- **Ingress rule**
Configure the `expose.ingress.hosts.core` and `expose.ingress.hosts.notary`.
- **External URL**
Configure the `externalURL`.
- **External PostgreSQL**
Set the `database.type` to `external` and fill the information in `database.external` section.
Four empty databases should be created manually for `Harbor core`, `Clair`, `Notary server` and `Notary signer` and configure them in the section. Harbor will create tables automatically when starting up.
- **External Redis**
Set the `redis.type` to `external` and fill the information in `redis.external` section.
As the Redis client used by Harbor's upstream projects doesn't support `Sentinel`, Harbor can only work with a single entry point Redis. You can refer to this [guide](https://community.pivotal.io/s/article/How-to-setup-HAProxy-and-Redis-Sentinel-for-automatic-failover-between-Redis-Master-and-Slave-servers) to setup a HAProxy before the Redis to expose a single entry point.
- **Storage**
By default, a default `StorageClass` is needed in the K8S cluster to provision volumes to store images, charts and job logs.
If you want to specify the `StorageClass`, set `persistence.persistentVolumeClaim.registry.storageClass`, `persistence.persistentVolumeClaim.chartmuseum.storageClass` and `persistence.persistentVolumeClaim.jobservice.storageClass`.
If you use `StorageClass`, for both default or specified one, set `persistence.persistentVolumeClaim.registry.accessMode`, `persistence.persistentVolumeClaim.chartmuseum.accessMode` and `persistence.persistentVolumeClaim.jobservice.accessMode` as `ReadWriteMany`, and make sure that the persistent volumes must can be shared cross different nodes.
You can also use the existing PVCs to store data, set `persistence.persistentVolumeClaim.registry.existingClaim`, `persistence.persistentVolumeClaim.chartmuseum.existingClaim` and `persistence.persistentVolumeClaim.jobservice.existingClaim`.
If you have no PVCs that can be shared across nodes, you can use external object storage to store images and charts and store the job logs in database. Set the `persistence.imageChartStorage.type` to the value you want to use and fill the corresponding section and set `jobservice.jobLogger` to `database`.
- **Replica**
Set `portal.replicas`, `core.replicas`, `jobservice.replicas`, `registry.replicas`, `chartmuseum.replicas`, `clair.replicas`, `notary.server.replicas` and `notary.signer.replicas` to `n`(`n`>=2).
### Installation
Install the Harbor helm chart with a release name `my-release`:
helm 2:
```bash
helm install --name my-release .
```
helm 3:
```
helm install my-release .
```
---
title: Upgrade Guide
---
This guide is used to upgrade Harbor deployed by chart since version 0.3.0.
## Notes
- As the database schema may change between different versions of Harbor, there is a progress to migrate the schema during the upgrade and the downtime cannot be avoid
- The database schema cannot be downgraded automatically, so the `helm rollback` is not supported
## Upgrade
### 1. Backup database
Backup the database used by Harbor in case the upgrade process fails.
### 2. Download new chart
Download the latest version of Harbor chart.
### 3. Configure new chart
Configure the new chart to make sure that the configuration items have the same values with the old one.
> Note: if TLS is enabled and the certificate is generated by chart automatically, a new certificate will be generated and overwrite the old one during the upgrade, this may cause some issues if you have distributed the certificate. You can follow the below steps to configure the new chart to use the old certificate:
1) Get the secret name which certificate is stored in:
```bash
kubectl get secret
```
Find the secret whose name ends with `-harbor-ingress` (expose service via `Ingress`) or `-harbor-nginx`(expose service via `ClusterIP` or `NodePort`)
2) Export the secret as yaml file:
```bash
kubectl get secret <secret-name-from-step-1> -o yaml > secret.yaml
```
3) Rename the secret by setting `metadata.name` in `secret.yaml`
4) Create a new secret:
```bash
kubectl create -f secret.yaml
```
5) Configure the chart to use the new secret by setting `expose.tls.secretName` as the value you set in step **3**
### 4. Upgrade
Run upgrade command:
```bash
helm upgrade release-name --force .
```
> The `--force` is necessary if upgrade from version 0.3.0 due to issue [#30](https://github.com/goharbor/harbor-helm/issues/30).
## Known issues
- The job logs will be lost if you upgrade from version 0.3.0 as the logs are store in a `emptyDir` in 0.3.0.
---
title: Managing Harbor with Helm
weight: 50
---
This documentation focuses on deploying and managing Harbor via [Helm](https://helm.sh). For general documentation for Harbor, please see the [Harbor docs](https://goharbor.io/docs).
\ No newline at end of file
expose:
type: ingress
tls:
enabled: false
ingress:
hosts:
core: hub.wodcloud.local
notary: notary.wodcloud.local
annotations:
ingress.kubernetes.io/proxy-body-size: '0'
externalURL: https://hub.wodcloud.local
persistence:
enabled: true
persistentVolumeClaim:
registry:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
chartmuseum:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
jobservice:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
database:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
redis:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
trivy:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
imageChartStorage:
# s3 , filesystem
type: filesystem
s3:
accesskey: AKIAIOSFODNN7EXAMPLE
secretkey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region: us-east-1
regionendpoint: http://minio.wodcloud.local
bucket: registry
encrypt: false
v4auth: true
chunksize: '5242880'
rootdirectory: /
imagePullPolicy: IfNotPresent
logLevel: info
harborAdminPassword: 'spaceIN511'
secretKey: 'IpTIscRIgmerlare'
portal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-portal
tag: v2.1.6
core:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-core
tag: v2.1.6
jobservice:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-jobservice
tag: v2.1.6
registry:
registry:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/registry
tag: v2.7.1
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
controller:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-registryctl
tag: v2.1.6
chartmuseum:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/chartmuseum
tag: v2.1.6
nodeSelector: {}
# nodeSelector:
# harbor: enabled
storageSpec:
type: hostPath
emptyDir: {}
hostPath:
root: /data
clair:
clair:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/clair
tag: v2.1.6
adapter:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-scanner-clair
tag: v2.1.6
trivy:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-scanner-trivy
tag: v2.1.6
notary:
server:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-server
tag: v2.1.6
signer:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-signer
tag: v2.1.6
database:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-db
tag: v2.1.6
password: 'spaceIN511'
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
redis:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/redis
tag: 6.2.6
expose:
type: ingress
tls:
enabled: false
ingress:
hosts:
core: hub.wodcloud.local
notary: notary.wodcloud.local
annotations:
ingress.kubernetes.io/proxy-body-size: '0'
externalURL: https://hub.wodcloud.local
persistence:
enabled: true
persistentVolumeClaim:
registry:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
chartmuseum:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
jobservice:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
database:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
redis:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
trivy:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
imageChartStorage:
# s3 , filesystem
type: filesystem
s3:
accesskey: AKIAIOSFODNN7EXAMPLE
secretkey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region: us-east-1
regionendpoint: http://minio.wodcloud.local
bucket: registry
encrypt: false
v4auth: true
chunksize: '5242880'
rootdirectory: /
imagePullPolicy: IfNotPresent
logLevel: info
harborAdminPassword: 'spaceIN511'
secretKey: 'IpTIscRIgmerlare'
portal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-portal
tag: v2.1.6-arm64
core:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-core
tag: v2.1.6-arm64
jobservice:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-jobservice
tag: v2.1.6-arm64
registry:
registry:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/registry
tag: v2.7.1-arm64
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
controller:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-registryctl
tag: v2.1.6-arm64
chartmuseum:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/chartmuseum
tag: v2.1.6-arm64
nodeSelector: {}
# nodeSelector:
# harbor: enabled
storageSpec:
type: hostPath
emptyDir: {}
hostPath:
root: /data
clair:
clair:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/clair
tag: v2.1.6-arm64
adapter:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-scanner-clair
tag: v2.1.6-arm64
trivy:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-scanner-trivy
tag: v2.1.6-arm64
notary:
server:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-server
tag: v2.1.6-arm64
signer:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-signer
tag: v2.1.6-arm64
database:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-db
tag: v2.1.6-arm64
password: 'spaceIN511'
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
redis:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/redis
tag: 6.2.6-arm64
expose:
type: ingress
tls:
enabled: false
ingress:
hosts:
core: hub.test.wodcloud.com
notary: notary.test.wodcloud.com
annotations:
ingress.kubernetes.io/proxy-body-size: '0'
externalURL: https://hub.test.wodcloud.com
persistence:
enabled: true
imageChartStorage:
# s3 , filesystem
type: filesystem
filesystem:
rootdirectory: /data
#s3:
# accesskey: AKIAIOSFODNN7EXAMPLE
# secretkey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# region: us-east-1
# regionendpoint: https://minio.sxwh.local
# bucket: registry
# encrypt: false
# v4auth: true
# chunksize: '5242880'
# rootdirectory: /
imagePullPolicy: IfNotPresent
logLevel: info
harborAdminPassword: 'spaceIN511'
secretKey: 'IpTIscRIgmerlare'
portal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-portal
tag: v1.8.2
replicas: 1
core:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-core
tag: v1.8.2
replicas: 1
jobservice:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-jobservice
tag: v1.8.2
replicas: 1
maxJobWorkers: 10
jobLogger: file
registry:
registry:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/registry
tag: v2.7.1
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
nodeSelector:
harbor: enabled
storageSpec:
# type: emptyDir , hostPath , volumeClaimTemplate
type: hostPath
emptyDir: {}
hostPath:
root: /data
volumeClaimTemplate:
spec:
storageClassName: rook-ceph-block
accessModes: ['ReadWriteOnce']
resources:
requests:
storage: 100Gi
selector: {}
controller:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-registryctl
tag: v1.8.2
replicas: 1
chartmuseum:
enabled: true
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/chartmuseum-photon
tag: v0.9.0-v1.8.2
replicas: 1
nodeSelector:
harbor: enabled
storageSpec:
type: hostPath
emptyDir: {}
hostPath:
root: /data
clair:
enabled: true
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/clair-photon
tag: v2.0.8-v1.8.2
replicas: 1
notary:
enabled: true
server:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-server-photon
tag: v0.6.1-v1.8.2
replicas: 1
signer:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-signer-photon
tag: v0.6.1-v1.8.2
replicas: 1
database:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-db
tag: v1.8.2
password: 'spaceIN511'
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
nodeSelector:
harbor: enabled
storageSpec:
type: hostPath
emptyDir: {}
hostPath:
root: /data
volumeClaimTemplate:
spec:
storageClassName: rook-ceph-block
accessModes: ['ReadWriteOnce']
resources:
requests:
storage: 20Gi
selector: {}
redis:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/redis
tag: 4.0.14-alpine
expose:
type: ingress
tls:
enabled: false
ingress:
hosts:
core: hub.wodcloud.local
notary: notary.wodcloud.local
annotations:
ingress.kubernetes.io/proxy-body-size: '0'
externalURL: https://hub.wodcloud.local
persistence:
enabled: true
persistentVolumeClaim:
registry:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
chartmuseum:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
jobservice:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
database:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
redis:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
trivy:
existingClaim: ''
storageClass: 'hostpath'
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
imageChartStorage:
# s3 , filesystem
type: filesystem
s3:
accesskey: AKIAIOSFODNN7EXAMPLE
secretkey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
region: us-east-1
regionendpoint: http://minio.wodcloud.local
bucket: registry
encrypt: false
v4auth: true
chunksize: '5242880'
rootdirectory: /
imagePullPolicy: IfNotPresent
logLevel: info
harborAdminPassword: 'spaceIN511'
secretKey: 'IpTIscRIgmerlare'
portal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-portal
tag: v2.1.6-ppc64le
core:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-core
tag: v2.1.6-ppc64le
jobservice:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-jobservice
tag: v2.1.6-ppc64le
registry:
registry:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/registry
tag: v2.7.1-ppc64le
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
controller:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-registryctl
tag: v2.1.6-ppc64le
chartmuseum:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/chartmuseum
tag: v2.1.1-ppc64le
nodeSelector: {}
# nodeSelector:
# harbor: enabled
storageSpec:
type: hostPath
emptyDir: {}
hostPath:
root: /data
clair:
clair:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/clair
tag: v2.1.1-ppc64le
adapter:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-scanner-clair
tag: v2.1.1-ppc64le
trivy:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-scanner-trivy
tag: v2.1.1-ppc64le
notary:
server:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-server
tag: v2.1.1-ppc64le
signer:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-signer
tag: v2.1.1-ppc64le
database:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-db
tag: v2.1.6-ppc64le
password: 'spaceIN511'
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
redis:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/redis
tag: 6.2.6-ppc64le
expose:
type: ingress
tls:
enabled: false
ingress:
hosts:
core: hub.test.wodcloud.com
notary: notary.test.wodcloud.com
annotations:
ingress.kubernetes.io/proxy-body-size: '0'
externalURL: https://hub.test.wodcloud.com
persistence:
enabled: true
imageChartStorage:
# s3 , filesystem
type: filesystem
filesystem:
rootdirectory: /data
#s3:
# accesskey: AKIAIOSFODNN7EXAMPLE
# secretkey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# region: us-east-1
# regionendpoint: https://minio.sxwh.local
# bucket: registry
# encrypt: false
# v4auth: true
# chunksize: '5242880'
# rootdirectory: /
imagePullPolicy: IfNotPresent
logLevel: info
harborAdminPassword: 'spaceIN511'
secretKey: 'IpTIscRIgmerlare'
portal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-portal
tag: v1.8.2
replicas: 1
core:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-core
tag: v1.8.2
replicas: 1
jobservice:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-jobservice
tag: v1.8.2
replicas: 1
maxJobWorkers: 10
jobLogger: file
registry:
registry:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/registry
tag: v2.7.1
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
nodeSelector:
harbor: enabled
storageSpec:
# type: emptyDir , hostPath , volumeClaimTemplate
type: hostPath
emptyDir: {}
hostPath:
root: /data
volumeClaimTemplate:
spec:
storageClassName: rook-ceph-block
accessModes: ['ReadWriteOnce']
resources:
requests:
storage: 100Gi
selector: {}
controller:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-registryctl
tag: v1.8.2
replicas: 1
chartmuseum:
enabled: true
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/chartmuseum-photon
tag: v0.9.0-v1.8.2
replicas: 1
nodeSelector:
harbor: enabled
storageSpec:
type: hostPath
emptyDir: {}
hostPath:
root: /data
clair:
enabled: true
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/clair-photon
tag: v2.0.8-v1.8.2
replicas: 1
notary:
enabled: true
server:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-server-photon
tag: v0.6.1-v1.8.2
replicas: 1
signer:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-signer-photon
tag: v0.6.1-v1.8.2
replicas: 1
database:
type: external
external:
host: 'stolon-proxy.devops'
port: '5432'
username: 'postgres'
password: 'spaceIN511'
coreDatabase: 'hub_registry'
clairDatabase: 'hub_clair'
notaryServerDatabase: 'hub_notary_server'
notarySignerDatabase: 'hub_notary_signer'
sslmode: 'disable'
redis:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/redis
tag: 4.0.14-alpine
expose:
# Set the way how to expose the service. Set the type as "ingress",
# "clusterIP", "nodePort" or "loadBalancer" and fill the information
# in the corresponding section
type: ingress
tls:
# Enable the tls or not. Note: if the type is "ingress" and the tls
# is disabled, the port must be included in the command when pull/push
# images. Refer to https://github.com/goharbor/harbor/issues/5291
# for the detail.
enabled: true
# The source of the tls certificate. Set it as "auto", "secret"
# or "none" and fill the information in the corresponding section
# 1) auto: generate the tls certificate automatically
# 2) secret: read the tls certificate from the specified secret.
# The tls certificate can be generated manually or by cert manager
# 3) none: configure no tls certificate for the ingress. If the default
# tls certificate is configured in the ingress controller, choose this option
certSource: auto
auto:
# The common name used to generate the certificate, it's necessary
# when the type isn't "ingress"
commonName: ''
secret:
# The name of secret which contains keys named:
# "tls.crt" - the certificate
# "tls.key" - the private key
secretName: ''
# The name of secret which contains keys named:
# "tls.crt" - the certificate
# "tls.key" - the private key
# Only needed when the "expose.type" is "ingress".
notarySecretName: ''
ingress:
hosts:
core: core.harbor.domain
notary: notary.harbor.domain
# set to the type of ingress controller if it has specific requirements.
# leave as `default` for most ingress controllers.
# set to `gce` if using the GCE ingress controller
# set to `ncp` if using the NCP (NSX-T Container Plugin) ingress controller
controller: default
annotations:
ingress.kubernetes.io/ssl-redirect: 'true'
ingress.kubernetes.io/proxy-body-size: '0'
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
nginx.ingress.kubernetes.io/proxy-body-size: '0'
clusterIP:
# The name of ClusterIP service
name: harbor
ports:
# The service port Harbor listens on when serving with HTTP
httpPort: 80
# The service port Harbor listens on when serving with HTTPS
httpsPort: 443
# The service port Notary listens on. Only needed when notary.enabled
# is set to true
notaryPort: 4443
nodePort:
# The name of NodePort service
name: harbor
ports:
http:
# The service port Harbor listens on when serving with HTTP
port: 80
# The node port Harbor listens on when serving with HTTP
nodePort: 30002
https:
# The service port Harbor listens on when serving with HTTPS
port: 443
# The node port Harbor listens on when serving with HTTPS
nodePort: 30003
# Only needed when notary.enabled is set to true
notary:
# The service port Notary listens on
port: 4443
# The node port Notary listens on
nodePort: 30004
loadBalancer:
# The name of LoadBalancer service
name: harbor
# Set the IP if the LoadBalancer supports assigning IP
IP: ''
ports:
# The service port Harbor listens on when serving with HTTP
httpPort: 80
# The service port Harbor listens on when serving with HTTPS
httpsPort: 443
# The service port Notary listens on. Only needed when notary.enabled
# is set to true
notaryPort: 4443
annotations: {}
sourceRanges: []
# The external URL for Harbor core service. It is used to
# 1) populate the docker/helm commands showed on portal
# 2) populate the token service URL returned to docker/notary client
#
# Format: protocol://domain[:port]. Usually:
# 1) if "expose.type" is "ingress", the "domain" should be
# the value of "expose.ingress.hosts.core"
# 2) if "expose.type" is "clusterIP", the "domain" should be
# the value of "expose.clusterIP.name"
# 3) if "expose.type" is "nodePort", the "domain" should be
# the IP address of k8s node
#
# If Harbor is deployed behind the proxy, set it as the URL of proxy
externalURL: https://core.harbor.domain
# The internal TLS used for harbor components secure communicating. In order to enable https
# in each components tls cert files need to provided in advance.
internalTLS:
# If internal TLS enabled
enabled: false
# There are three ways to provide tls
# 1) "auto" will generate cert automatically
# 2) "manual" need provide cert file manually in following value
# 3) "secret" internal certificates from secret
certSource: 'auto'
# The content of trust ca, only available when `certSource` is "manual"
trustCa: ''
# core related cert configuration
core:
# secret name for core's tls certs
secretName: ''
# Content of core's TLS cert file, only available when `certSource` is "manual"
crt: ''
# Content of core's TLS key file, only available when `certSource` is "manual"
key: ''
# jobservice related cert configuration
jobservice:
# secret name for jobservice's tls certs
secretName: ''
# Content of jobservice's TLS key file, only available when `certSource` is "manual"
crt: ''
# Content of jobservice's TLS key file, only available when `certSource` is "manual"
key: ''
# registry related cert configuration
registry:
# secret name for registry's tls certs
secretName: ''
# Content of registry's TLS key file, only available when `certSource` is "manual"
crt: ''
# Content of registry's TLS key file, only available when `certSource` is "manual"
key: ''
# portal related cert configuration
portal:
# secret name for portal's tls certs
secretName: ''
# Content of portal's TLS key file, only available when `certSource` is "manual"
crt: ''
# Content of portal's TLS key file, only available when `certSource` is "manual"
key: ''
# chartmuseum related cert configuration
chartmuseum:
# secret name for chartmuseum's tls certs
secretName: ''
# Content of chartmuseum's TLS key file, only available when `certSource` is "manual"
crt: ''
# Content of chartmuseum's TLS key file, only available when `certSource` is "manual"
key: ''
# clair related cert configuration
clair:
# secret name for clair's tls certs
secretName: ''
# Content of clair's TLS key file, only available when `certSource` is "manual"
crt: ''
# Content of clair's TLS key file, only available when `certSource` is "manual"
key: ''
# trivy related cert configuration
trivy:
# secret name for trivy's tls certs
secretName: ''
# Content of trivy's TLS key file, only available when `certSource` is "manual"
crt: ''
# Content of trivy's TLS key file, only available when `certSource` is "manual"
key: ''
# The persistence is enabled by default and a default StorageClass
# is needed in the k8s cluster to provision volumes dynamicly.
# Specify another StorageClass in the "storageClass" or set "existingClaim"
# if you have already existing persistent volumes to use
#
# For storing images and charts, you can also use "azure", "gcs", "s3",
# "swift" or "oss". Set it in the "imageChartStorage" section
persistence:
enabled: true
# Setting it to "keep" to avoid removing PVCs during a helm delete
# operation. Leaving it empty will delete PVCs after the chart deleted
# (this does not apply for PVCs that are created for internal database
# and redis components, i.e. they are never deleted automatically)
resourcePolicy: 'keep'
persistentVolumeClaim:
registry:
# Use the existing PVC which must be created manually before bound,
# and specify the "subPath" if the PVC is shared with other components
existingClaim: ''
# Specify the "storageClass" used to provision the volume. Or the default
# StorageClass will be used(the default).
# Set it to "-" to disable dynamic provisioning
storageClass: ''
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
chartmuseum:
existingClaim: ''
storageClass: ''
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
jobservice:
existingClaim: ''
storageClass: ''
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
# If external database is used, the following settings for database will
# be ignored
database:
existingClaim: ''
storageClass: ''
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
# If external Redis is used, the following settings for Redis will
# be ignored
redis:
existingClaim: ''
storageClass: ''
subPath: ''
accessMode: ReadWriteOnce
size: 1Gi
trivy:
existingClaim: ''
storageClass: ''
subPath: ''
accessMode: ReadWriteOnce
size: 5Gi
# Define which storage backend is used for registry and chartmuseum to store
# images and charts. Refer to
# https://github.com/docker/distribution/blob/master/docs/configuration.md#storage
# for the detail.
imageChartStorage:
# Specify whether to disable `redirect` for images and chart storage, for
# backends which not supported it (such as using minio for `s3` storage type), please disable
# it. To disable redirects, simply set `disableredirect` to `true` instead.
# Refer to
# https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect
# for the detail.
disableredirect: false
# Specify the "caBundleSecretName" if the storage service uses a self-signed certificate.
# The secret must contain keys named "ca.crt" which will be injected into the trust store
# of registry's and chartmuseum's containers.
# caBundleSecretName:
# Specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift",
# "oss" and fill the information needed in the corresponding section. The type
# must be "filesystem" if you want to use persistent volumes for registry
# and chartmuseum
type: filesystem
filesystem:
rootdirectory: /storage
#maxthreads: 100
azure:
accountname: accountname
accountkey: base64encodedaccountkey
container: containername
#realm: core.windows.net
gcs:
bucket: bucketname
# The base64 encoded json file which contains the key
encodedkey: base64-encoded-json-key-file
#rootdirectory: /gcs/object/name/prefix
#chunksize: "5242880"
s3:
region: us-west-1
bucket: bucketname
#accesskey: awsaccesskey
#secretkey: awssecretkey
#regionendpoint: http://myobjects.local
#encrypt: false
#keyid: mykeyid
#secure: true
#skipverify: false
#v4auth: true
#chunksize: "5242880"
#rootdirectory: /s3/object/name/prefix
#storageclass: STANDARD
#multipartcopychunksize: "33554432"
#multipartcopymaxconcurrency: 100
#multipartcopythresholdsize: "33554432"
swift:
authurl: https://storage.myprovider.com/v3/auth
username: username
password: password
container: containername
#region: fr
#tenant: tenantname
#tenantid: tenantid
#domain: domainname
#domainid: domainid
#trustid: trustid
#insecureskipverify: false
#chunksize: 5M
#prefix:
#secretkey: secretkey
#accesskey: accesskey
#authversion: 3
#endpointtype: public
#tempurlcontainerkey: false
#tempurlmethods:
oss:
accesskeyid: accesskeyid
accesskeysecret: accesskeysecret
region: regionname
bucket: bucketname
#endpoint: endpoint
#internal: false
#encrypt: false
#secure: true
#chunksize: 10M
#rootdirectory: rootdirectory
imagePullPolicy: IfNotPresent
# Use this set to assign a list of default pullSecrets
imagePullSecrets:
# - name: docker-registry-secret
# - name: internal-registry-secret
# The update strategy for deployments with persistent volumes(jobservice, registry
# and chartmuseum): "RollingUpdate" or "Recreate"
# Set it as "Recreate" when "RWM" for volumes isn't supported
updateStrategy:
type: RollingUpdate
# debug, info, warning, error or fatal
logLevel: info
# The initial password of Harbor admin. Change it from portal after launching Harbor
harborAdminPassword: 'Harbor12345'
# The name of the secret which contains key named "ca.crt". Setting this enables the
# download link on portal to download the certificate of CA when the certificate isn't
# generated automatically
caSecretName: ''
# The secret key used for encryption. Must be a string of 16 chars.
secretKey: 'not-a-secure-key'
# The proxy settings for updating clair vulnerabilities from the Internet and replicating
# artifacts from/to the registries that cannot be reached directly
proxy:
httpProxy:
httpsProxy:
noProxy: 127.0.0.1,localhost,.local,.internal
components:
- core
- jobservice
- clair
- trivy
# The custom ca bundle secret, the secret must contain key named "ca.crt"
# which will be injected into the trust store for chartmuseum, clair, core, jobservice, registry, trivy components
# caBundleSecretName: ""
## UAA Authentication Options
# If you're using UAA for authentication behind a self-signed
# certificate you will need to provide the CA Cert.
# Set uaaSecretName below to provide a pre-created secret that
# contains a base64 encoded CA Certificate named `ca.crt`.
# uaaSecretName:
# If expose the service via "ingress", the Nginx will not be used
nginx:
image:
repository: goharbor/nginx-photon
tag: v2.1.6
# set the service account to be used, default if left empty
serviceAccountName: ''
replicas: 1
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
portal:
image:
repository: goharbor/harbor-portal
tag: v2.1.6
# set the service account to be used, default if left empty
serviceAccountName: ''
replicas: 1
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
core:
image:
repository: goharbor/harbor-core
tag: v2.1.6
# set the service account to be used, default if left empty
serviceAccountName: ''
replicas: 1
## Startup probe values
startupProbe:
enabled: false
initialDelaySeconds: 10
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Secret is used when core server communicates with other components.
# If a secret key is not specified, Helm will generate one.
# Must be a string of 16 chars.
secret: ''
# Fill the name of a kubernetes secret if you want to use your own
# TLS certificate and private key for token encryption/decryption.
# The secret must contain keys named:
# "tls.crt" - the certificate
# "tls.key" - the private key
# The default key pair will be used if it isn't set
secretName: ''
# The XSRF key. Will be generated automatically if it isn't specified
xsrfKey: ''
jobservice:
image:
repository: goharbor/harbor-jobservice
tag: v2.1.6
replicas: 1
# set the service account to be used, default if left empty
serviceAccountName: ''
maxJobWorkers: 10
# The logger for jobs: "file", "database" or "stdout"
jobLogger: file
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Secret is used when job service communicates with other components.
# If a secret key is not specified, Helm will generate one.
# Must be a string of 16 chars.
secret: ''
registry:
# set the service account to be used, default if left empty
serviceAccountName: ''
registry:
image:
repository: goharbor/registry-photon
tag: v2.1.6
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
controller:
image:
repository: goharbor/harbor-registryctl
tag: v2.1.6
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
replicas: 1
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Secret is used to secure the upload state from client
# and registry storage backend.
# See: https://github.com/docker/distribution/blob/master/docs/configuration.md#http
# If a secret key is not specified, Helm will generate one.
# Must be a string of 16 chars.
secret: ''
# If true, the registry returns relative URLs in Location headers. The client is responsible for resolving the correct URL.
relativeurls: false
credentials:
username: 'harbor_registry_user'
password: 'harbor_registry_password'
# If you update the username or password of registry, make sure use cli tool htpasswd to generate the bcrypt hash
# e.g. "htpasswd -nbBC10 $username $password"
htpasswd: 'harbor_registry_user:$2y$10$9L4Tc0DJbFFMB6RdSCunrOpTHdwhid4ktBJmLD00bYgqkkGOvll3m'
middleware:
enabled: false
type: cloudFront
cloudFront:
baseurl: example.cloudfront.net
keypairid: KEYPAIRID
duration: 3000s
ipfilteredby: none
# The secret key that should be present is CLOUDFRONT_KEY_DATA, which should be the encoded private key
# that allows access to CloudFront
privateKeySecret: 'my-secret'
chartmuseum:
enabled: true
# set the service account to be used, default if left empty
serviceAccountName: ''
# Harbor defaults ChartMuseum to returning relative urls, if you want using absolute url you should enable it by change the following value to 'true'
absoluteUrl: false
image:
repository: goharbor/chartmuseum-photon
tag: v2.1.6
replicas: 1
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
clair:
enabled: true
# set the service account to be used, default if left empty
serviceAccountName: ''
clair:
image:
repository: goharbor/clair-photon
tag: v2.1.6
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
adapter:
image:
repository: goharbor/harbor-scanner-clair-photon
tag: v2.1.6
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
replicas: 1
# The interval of clair updaters, the unit is hour, set to 0 to
# disable the updaters
updatersInterval: 12
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
trivy:
# enabled the flag to enable Trivy scanner
enabled: true
image:
# repository the repository for Trivy adapter image
repository: goharbor/trivy-adapter-photon
# tag the tag for Trivy adapter image
tag: v2.1.6
# set the service account to be used, default if left empty
serviceAccountName: ''
# replicas the number of Pod replicas
replicas: 1
# debugMode the flag to enable Trivy debug mode with more verbose scanning log
debugMode: false
# vulnType a comma-separated list of vulnerability types. Possible values are `os` and `library`.
vulnType: 'os,library'
# severity a comma-separated list of severities to be checked
severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL'
# ignoreUnfixed the flag to display only fixed vulnerabilities
ignoreUnfixed: false
# insecure the flag to skip verifying registry certificate
insecure: false
# gitHubToken the GitHub access token to download Trivy DB
#
# Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases.
# It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached
# in the local file system (`/home/scanner/.cache/trivy/db/trivy.db`). In addition, the database contains the update
# timestamp so Trivy can detect whether it should download a newer version from the Internet or use the cached one.
# Currently, the database is updated every 12 hours and published as a new release to GitHub.
#
# Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough
# for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000
# requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult
# https://developer.github.com/v3/#rate-limiting
#
# You can create a GitHub token by following the instructions in
# https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
gitHubToken: ''
# skipUpdate the flag to disable Trivy DB downloads from GitHub
#
# You might want to set the value of this flag to `true` in test or CI/CD environments to avoid GitHub rate limiting issues.
# If the value is set to `true` you have to manually download the `trivy.db` file and mount it in the
# `/home/scanner/.cache/trivy/db/trivy.db` path.
skipUpdate: false
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1
memory: 1Gi
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
notary:
enabled: true
server:
# set the service account to be used, default if left empty
serviceAccountName: ''
image:
repository: goharbor/notary-server-photon
tag: v2.1.6
replicas: 1
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
signer:
# set the service account to be used, default if left empty
serviceAccountName: ''
image:
repository: goharbor/notary-signer-photon
tag: v2.1.6
replicas: 1
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
## Additional deployment annotations
podAnnotations: {}
# Fill the name of a kubernetes secret if you want to use your own
# TLS certificate authority, certificate and private key for notary
# communications.
# The secret must contain keys named ca.crt, tls.crt and tls.key that
# contain the CA, certificate and private key.
# They will be generated if not set.
secretName: ''
database:
# if external database is used, set "type" to "external"
# and fill the connection informations in "external" section
type: internal
internal:
# set the service account to be used, default if left empty
serviceAccountName: ''
image:
repository: goharbor/harbor-db
tag: v2.1.6
# The initial superuser password for internal database
password: 'changeit'
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
external:
host: '192.168.0.1'
port: '5432'
username: 'user'
password: 'password'
coreDatabase: 'registry'
clairDatabase: 'clair'
notaryServerDatabase: 'notary_server'
notarySignerDatabase: 'notary_signer'
# "disable" - No SSL
# "require" - Always SSL (skip verification)
# "verify-ca" - Always SSL (verify that the certificate presented by the
# server was signed by a trusted CA)
# "verify-full" - Always SSL (verify that the certification presented by the
# server was signed by a trusted CA and the server host name matches the one
# in the certificate)
sslmode: 'disable'
# The maximum number of connections in the idle connection pool.
# If it <=0, no idle connections are retained.
maxIdleConns: 50
# The maximum number of open connections to the database.
# If it <= 0, then there is no limit on the number of open connections.
# Note: the default number of connections is 1024 for postgre of harbor.
maxOpenConns: 1000
## Additional deployment annotations
podAnnotations: {}
redis:
# if external Redis is used, set "type" to "external"
# and fill the connection informations in "external" section
type: internal
internal:
# set the service account to be used, default if left empty
serviceAccountName: ''
image:
repository: goharbor/redis-photon
tag: v2.1.6
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
external:
# support redis, redis+sentinel
# addr for redis: <host_redis>:<port_redis>
# addr for redis+sentinel: <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3>
addr: '192.168.0.2:6379'
# The name of the set of Redis instances to monitor, it must be set to support redis+sentinel
sentinelMasterSet: ''
# The "coreDatabaseIndex" must be "0" as the library Harbor
# used doesn't support configuring it
coreDatabaseIndex: '0'
jobserviceDatabaseIndex: '1'
registryDatabaseIndex: '2'
chartmuseumDatabaseIndex: '3'
clairAdapterIndex: '4'
trivyAdapterIndex: '5'
password: ''
## Additional deployment annotations
podAnnotations: {}
commonLabels:
app.bd-apaas.com/cluster-component: registry
Please wait for several minutes for Harbor deployment to complete. Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at {{ $.Values.global.host }} Then you should be able to visit the Harbor portal at {{ .Values.externalURL }}
For more details, please visit https://github.com/goharbor/harbor For more details, please visit https://github.com/goharbor/harbor
{{/* {{/* vim: set filetype=mustache: */}}
Create chart imageArch suffix. {{/*
*/}} Expand the name of the chart.
{{- define ".beagle.imageArch" -}} We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
{{- if not (eq "amd64" .Values.global.imageArch) -}} */}}
{{- print "-" .Values.global.imageArch -}} {{- define "harbor.name" -}}
{{- else -}} {{- default "harbor" .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- print "" -}} {{- end -}}
{{- end -}}
{{- end }} {{/*
Create a default fully qualified app name.
{{/* vim: set filetype=mustache: */}} We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
{{/* If release name contains chart name it will be used as a full name.
Expand the name of the chart. */}}
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). {{- define "harbor.fullname" -}}
*/}} {{- if .Values.fullnameOverride }}
{{- define "harbor.name" -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- default "harbor" .Values.nameOverride | trunc 63 | trimSuffix "-" -}} {{- else }}
{{- end -}} {{- $name := default "harbor" .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{/* {{- .Release.Name | trunc 63 | trimSuffix "-" }}
Create a default fully qualified app name. {{- else }}
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
*/}} {{- end }}
{{- define "harbor.fullname" -}} {{- end }}
{{- $name := default "harbor" .Values.nameOverride -}} {{- end }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}} {{/* Helm required labels: legacy */}}
{{- define "harbor.legacy.labels" -}}
{{/* Helm required labels */}} heritage: {{ .Release.Service }}
{{- define "harbor.labels" -}} release: {{ .Release.Name }}
heritage: {{ .Release.Service }} chart: {{ .Chart.Name }}
release: {{ .Release.Name }} app: "{{ template "harbor.name" . }}"
chart: {{ .Chart.Name }} {{- end -}}
app: "{{ template "harbor.name" . }}"
{{- if .Values.commonLabels}} {{/* Helm required labels */}}
{{ toYaml .Values.commonLabels }} {{- define "harbor.labels" -}}
{{- end }} heritage: {{ .Release.Service }}
{{- end -}} release: {{ .Release.Name }}
chart: {{ .Chart.Name }}
{{/* matchLabels */}} app: "{{ template "harbor.name" . }}"
{{- define "harbor.matchLabels" -}} app.kubernetes.io/instance: {{ .Release.Name }}
release: {{ .Release.Name }} app.kubernetes.io/name: {{ include "harbor.name" . }}
app: "{{ template "harbor.name" . }}" app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}} app.kubernetes.io/part-of: {{ include "harbor.name" . }}
{{- if .Chart.AppVersion }}
{{- define "harbor.autoGenCert" -}} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- if and .Values.expose.tls.enabled (eq .Values.expose.tls.certSource "auto") -}} {{- end }}
{{- printf "true" -}} {{- end -}}
{{- else -}}
{{- printf "false" -}} {{/* matchLabels */}}
{{- end -}} {{- define "harbor.matchLabels" -}}
{{- end -}} release: {{ .Release.Name }}
app: "{{ template "harbor.name" . }}"
{{- define "harbor.autoGenCertForIngress" -}} {{- end -}}
{{- if and (eq (include "harbor.autoGenCert" .) "true") (eq .Values.expose.type "ingress") -}}
{{- printf "true" -}} {{/* Helper for printing values from existing secrets*/}}
{{- else -}} {{- define "harbor.secretKeyHelper" -}}
{{- printf "false" -}} {{- if and (not (empty .data)) (hasKey .data .key) }}
{{- end -}} {{- index .data .key | b64dec -}}
{{- end -}} {{- end -}}
{{- end -}}
{{- define "harbor.autoGenCertForNginx" -}}
{{- if and (eq (include "harbor.autoGenCert" .) "true") (ne .Values.expose.type "ingress") -}} {{- define "harbor.autoGenCert" -}}
{{- printf "true" -}} {{- if and .Values.expose.tls.enabled (eq .Values.expose.tls.certSource "auto") -}}
{{- else -}} {{- printf "true" -}}
{{- printf "false" -}} {{- else -}}
{{- end -}} {{- printf "false" -}}
{{- end -}} {{- end -}}
{{- end -}}
{{- define "harbor.database.host" -}}
{{- if eq .Values.database.type "internal" -}} {{- define "harbor.autoGenCertForIngress" -}}
{{- template "harbor.database" . }} {{- if and (eq (include "harbor.autoGenCert" .) "true") (eq .Values.expose.type "ingress") -}}
{{- else -}} {{- printf "true" -}}
{{- .Values.database.external.host -}} {{- else -}}
{{- end -}} {{- printf "false" -}}
{{- end -}} {{- end -}}
{{- end -}}
{{- define "harbor.database.port" -}}
{{- if eq .Values.database.type "internal" -}} {{- define "harbor.autoGenCertForNginx" -}}
{{- printf "%s" "5432" -}} {{- if and (eq (include "harbor.autoGenCert" .) "true") (ne .Values.expose.type "ingress") -}}
{{- else -}} {{- printf "true" -}}
{{- .Values.database.external.port -}} {{- else -}}
{{- end -}} {{- printf "false" -}}
{{- end -}} {{- end -}}
{{- end -}}
{{- define "harbor.database.username" -}}
{{- if eq .Values.database.type "internal" -}} {{- define "harbor.database.host" -}}
{{- printf "%s" "postgres" -}} {{- if eq .Values.database.type "internal" -}}
{{- else -}} {{- template "harbor.database" . }}
{{- .Values.database.external.username -}} {{- else -}}
{{- end -}} {{- .Values.database.external.host -}}
{{- end -}} {{- end -}}
{{- end -}}
{{- define "harbor.database.rawPassword" -}}
{{- if eq .Values.database.type "internal" -}} {{- define "harbor.database.port" -}}
{{- .Values.database.internal.password -}} {{- if eq .Values.database.type "internal" -}}
{{- else -}} {{- printf "%s" "5432" -}}
{{- .Values.database.external.password -}} {{- else -}}
{{- end -}} {{- .Values.database.external.port -}}
{{- end -}} {{- end -}}
{{- end -}}
{{- define "harbor.database.escapedRawPassword" -}}
{{- include "harbor.database.rawPassword" . | urlquery | replace "+" "%20" -}} {{- define "harbor.database.username" -}}
{{- end -}} {{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "postgres" -}}
{{- define "harbor.database.encryptedPassword" -}} {{- else -}}
{{- include "harbor.database.rawPassword" . | b64enc | quote -}} {{- .Values.database.external.username -}}
{{- end -}} {{- end -}}
{{- end -}}
{{- define "harbor.database.coreDatabase" -}}
{{- if eq .Values.database.type "internal" -}} {{- define "harbor.database.rawPassword" -}}
{{- printf "%s" "registry" -}} {{- if eq .Values.database.type "internal" -}}
{{- else -}} {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (include "harbor.database" .) -}}
{{- .Values.database.external.coreDatabase -}} {{- if and (not (empty $existingSecret)) (hasKey $existingSecret.data "POSTGRES_PASSWORD") -}}
{{- end -}} {{- .Values.database.internal.password | default (index $existingSecret.data "POSTGRES_PASSWORD" | b64dec) -}}
{{- end -}} {{- else -}}
{{- .Values.database.internal.password -}}
{{- define "harbor.database.clairDatabase" -}} {{- end -}}
{{- if eq .Values.database.type "internal" -}} {{- else -}}
{{- printf "%s" "postgres" -}} {{- .Values.database.external.password -}}
{{- else -}} {{- end -}}
{{- .Values.database.external.clairDatabase -}} {{- end -}}
{{- end -}}
{{- end -}} {{- define "harbor.database.escapedRawPassword" -}}
{{- include "harbor.database.rawPassword" . | urlquery | replace "+" "%20" -}}
{{- define "harbor.database.notaryServerDatabase" -}} {{- end -}}
{{- if eq .Values.database.type "internal" -}}
{{- printf "%s" "notaryserver" -}} {{- define "harbor.database.encryptedPassword" -}}
{{- else -}} {{- include "harbor.database.rawPassword" . | b64enc | quote -}}
{{- .Values.database.external.notaryServerDatabase -}} {{- end -}}
{{- end -}}
{{- end -}} {{- define "harbor.database.coreDatabase" -}}
{{- if eq .Values.database.type "internal" -}}
{{- define "harbor.database.notarySignerDatabase" -}} {{- printf "%s" "registry" -}}
{{- if eq .Values.database.type "internal" -}} {{- else -}}
{{- printf "%s" "notarysigner" -}} {{- .Values.database.external.coreDatabase -}}
{{- else -}} {{- end -}}
{{- .Values.database.external.notarySignerDatabase -}} {{- end -}}
{{- end -}}
{{- end -}} {{- define "harbor.database.sslmode" -}}
{{- if eq .Values.database.type "internal" -}}
{{- define "harbor.database.sslmode" -}} {{- printf "%s" "disable" -}}
{{- if eq .Values.database.type "internal" -}} {{- else -}}
{{- printf "%s" "disable" -}} {{- .Values.database.external.sslmode -}}
{{- else -}} {{- end -}}
{{- .Values.database.external.sslmode -}} {{- end -}}
{{- end -}}
{{- end -}} {{- define "harbor.redis.scheme" -}}
{{- with .Values.redis }}
{{- define "harbor.database.clair" -}} {{- if eq .type "external" -}}
postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.escapedRawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.clairDatabase" . }}?sslmode={{ template "harbor.database.sslmode" . }} {{- if not (not .external.sentinelMasterSet) -}}
{{- end -}} {{- ternary "rediss+sentinel" "redis+sentinel" (.external.tlsOptions.enable) }}
{{- else -}}
{{- define "harbor.database.notaryServer" -}} {{- ternary "rediss" "redis" (.external.tlsOptions.enable) }}
postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.escapedRawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.notaryServerDatabase" . }}?sslmode={{ template "harbor.database.sslmode" . }} {{- end -}}
{{- end -}} {{- else -}}
{{ print "redis" }}
{{- define "harbor.database.notarySigner" -}} {{- end -}}
postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.escapedRawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.notarySignerDatabase" . }}?sslmode={{ template "harbor.database.sslmode" . }} {{- end }}
{{- end -}} {{- end -}}
{{- define "harbor.redis.scheme" -}} {{- define "harbor.redis.enableTLS" -}}
{{- with .Values.redis }} {{- with .Values.redis }}
{{- ternary "redis+sentinel" "redis" (and (eq .type "external" ) (not (not .external.sentinelMasterSet))) }} {{- ternary "true" "false" (and ( eq .type "external") (.external.tlsOptions.enable)) }}
{{- end }} {{- end }}
{{- end -}} {{- end -}}
/*host:port*/ /*host:port*/
{{- define "harbor.redis.addr" -}} {{- define "harbor.redis.addr" -}}
{{- with .Values.redis }} {{- with .Values.redis }}
{{- ternary (printf "%s:6379" (include "harbor.redis" $ )) .external.addr (eq .type "internal") }} {{- ternary (printf "%s:6379" (include "harbor.redis" $ )) .external.addr (eq .type "internal") }}
{{- end }} {{- end }}
{{- end -}} {{- end -}}
{{- define "harbor.redis.masterSet" -}} {{- define "harbor.redis.masterSet" -}}
{{- with .Values.redis }} {{- with .Values.redis }}
{{- ternary .external.sentinelMasterSet "" (eq "redis+sentinel" (include "harbor.redis.scheme" $)) }} {{- ternary .external.sentinelMasterSet "" (contains "+sentinel" (include "harbor.redis.scheme" $)) }}
{{- end }} {{- end }}
{{- end -}} {{- end -}}
{{- define "harbor.redis.password" -}} {{- define "harbor.redis.password" -}}
{{- with .Values.redis }} {{- with .Values.redis }}
{{- ternary "" .external.password (eq .type "internal") }} {{- ternary "" .external.password (eq .type "internal") }}
{{- end }} {{- end }}
{{- end -}} {{- end -}}
/*scheme://[redis:password@]host:port[/master_set]*/
{{- define "harbor.redis.url" -}} {{- define "harbor.redis.pwdfromsecret" -}}
{{- with .Values.redis }} {{- (lookup "v1" "Secret" .Release.Namespace (.Values.redis.external.existingSecret)).data.REDIS_PASSWORD | b64dec }}
{{- $path := ternary "" (printf "/%s" (include "harbor.redis.masterSet" $)) (not (include "harbor.redis.masterSet" $)) }} {{- end -}}
{{- $cred := ternary (printf "redis:%s@" (.external.password | urlquery)) "" (and (eq .type "external" ) (not (not .external.password))) }}
{{- printf "%s://%s%s%s" (include "harbor.redis.scheme" $) $cred (include "harbor.redis.addr" $) $path -}} {{- define "harbor.redis.cred" -}}
{{- end }} {{- with .Values.redis }}
{{- end -}} {{- if (and (eq .type "external" ) (.external.existingSecret)) }}
{{- printf ":%s@" (include "harbor.redis.pwdfromsecret" $) }}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/ {{- else }}
{{- define "harbor.redis.urlForCore" -}} {{- ternary (printf "%s:%s@" (.external.username | urlquery) (.external.password | urlquery)) "" (and (eq .type "external" ) (not (not .external.password))) }}
{{- with .Values.redis }} {{- end }}
{{- $index := ternary "0" .external.coreDatabaseIndex (eq .type "internal") }} {{- end }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}} {{- end -}}
{{- end }}
{{- end -}} /*scheme://[:password@]host:port[/master_set]*/
{{- define "harbor.redis.url" -}}
/*scheme://[redis:password@]addr/db_index*/ {{- with .Values.redis }}
{{- define "harbor.redis.urlForJobservice" -}} {{- $path := ternary "" (printf "/%s" (include "harbor.redis.masterSet" $)) (not (include "harbor.redis.masterSet" $)) }}
{{- with .Values.redis }} {{- printf "%s://%s%s%s" (include "harbor.redis.scheme" $) (include "harbor.redis.cred" $) (include "harbor.redis.addr" $) $path -}}
{{- $index := ternary "1" .external.jobserviceDatabaseIndex (eq .type "internal") }} {{- end }}
{{- printf "%s/%s" (include "harbor.redis.url" $) $index -}} {{- end -}}
{{- end }}
{{- end -}} /*scheme://[:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForCore" -}}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/ {{- with .Values.redis }}
{{- define "harbor.redis.urlForRegistry" -}} {{- $index := ternary "0" .external.coreDatabaseIndex (eq .type "internal") }}
{{- with .Values.redis }} {{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- $index := ternary "2" .external.registryDatabaseIndex (eq .type "internal") }} {{- end }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}} {{- end -}}
{{- end }}
{{- end -}} /*scheme://[:password@]addr/db_index*/
{{- define "harbor.redis.urlForJobservice" -}}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/ {{- with .Values.redis }}
{{- define "harbor.redis.urlForClair" -}} {{- $index := ternary .internal.jobserviceDatabaseIndex .external.jobserviceDatabaseIndex (eq .type "internal") }}
{{- with .Values.redis }} {{- printf "%s/%s" (include "harbor.redis.url" $) $index -}}
{{- $index := ternary "4" .external.clairAdapterIndex (eq .type "internal") }} {{- end }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}} {{- end -}}
{{- end }}
{{- end -}} /*scheme://[:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForRegistry" -}}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/ {{- with .Values.redis }}
{{- define "harbor.redis.urlForTrivy" -}} {{- $index := ternary .internal.registryDatabaseIndex .external.registryDatabaseIndex (eq .type "internal") }}
{{- with .Values.redis }} {{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- $index := ternary "5" .external.trivyAdapterIndex (eq .type "internal") }} {{- end }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}} {{- end -}}
{{- end }}
{{- end -}} /*scheme://[:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForTrivy" -}}
{{- define "harbor.redis.dbForRegistry" -}} {{- with .Values.redis }}
{{- with .Values.redis }} {{- $index := ternary .internal.trivyAdapterIndex .external.trivyAdapterIndex (eq .type "internal") }}
{{- ternary "2" .external.registryDatabaseIndex (eq .type "internal") }} {{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- end }} {{- end }}
{{- end -}} {{- end -}}
{{- define "harbor.redis.dbForChartmuseum" -}} /*scheme://[:password@]addr/db_index?idle_timeout_seconds=30*/
{{- with .Values.redis }} {{- define "harbor.redis.urlForHarbor" -}}
{{- ternary "3" .external.chartmuseumDatabaseIndex (eq .type "internal") }} {{- with .Values.redis }}
{{- end }} {{- $index := ternary .internal.harborDatabaseIndex .external.harborDatabaseIndex (eq .type "internal") }}
{{- end -}} {{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- end }}
{{- define "harbor.portal" -}} {{- end -}}
{{- printf "%s-portal" (include "harbor.fullname" .) -}}
{{- end -}} /*scheme://[:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForCache" -}}
{{- define "harbor.core" -}} {{- with .Values.redis }}
{{- printf "%s-core" (include "harbor.fullname" .) -}} {{- $index := ternary .internal.cacheLayerDatabaseIndex .external.cacheLayerDatabaseIndex (eq .type "internal") }}
{{- end -}} {{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- end }}
{{- define "harbor.redis" -}} {{- end -}}
{{- printf "%s-redis" (include "harbor.fullname" .) -}}
{{- end -}} {{- define "harbor.redis.dbForRegistry" -}}
{{- with .Values.redis }}
{{- define "harbor.jobservice" -}} {{- ternary .internal.registryDatabaseIndex .external.registryDatabaseIndex (eq .type "internal") }}
{{- printf "%s-jobservice" (include "harbor.fullname" .) -}} {{- end }}
{{- end -}} {{- end -}}
{{- define "harbor.registry" -}} {{- define "harbor.portal" -}}
{{- printf "%s-registry" (include "harbor.fullname" .) -}} {{- printf "%s-portal" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.chartmuseum" -}} {{- define "harbor.core" -}}
{{- printf "%s-chartmuseum" (include "harbor.fullname" .) -}} {{- printf "%s-core" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.database" -}} {{- define "harbor.redis" -}}
{{- printf "%s-database" (include "harbor.fullname" .) -}} {{- printf "%s-redis" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.clair" -}} {{- define "harbor.jobservice" -}}
{{- printf "%s-clair" (include "harbor.fullname" .) -}} {{- printf "%s-jobservice" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.trivy" -}} {{- define "harbor.registry" -}}
{{- printf "%s-trivy" (include "harbor.fullname" .) -}} {{- printf "%s-registry" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.notary-server" -}} {{- define "harbor.registryCtl" -}}
{{- printf "%s-notary-server" (include "harbor.fullname" .) -}} {{- printf "%s-registryctl" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.notary-signer" -}} {{- define "harbor.database" -}}
{{- printf "%s-notary-signer" (include "harbor.fullname" .) -}} {{- printf "%s-database" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.nginx" -}} {{- define "harbor.trivy" -}}
{{- printf "%s-nginx" (include "harbor.fullname" .) -}} {{- printf "%s-trivy" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.ingress" -}} {{- define "harbor.nginx" -}}
{{- printf "%s-ingress" (include "harbor.fullname" .) -}} {{- printf "%s-nginx" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.ingress-notary" -}} {{- define "harbor.exporter" -}}
{{- printf "%s-ingress-notary" (include "harbor.fullname" .) -}} {{- printf "%s-exporter" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.noProxy" -}} {{- define "harbor.ingress" -}}
{{- printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" (include "harbor.core" .) (include "harbor.jobservice" .) (include "harbor.database" .) (include "harbor.chartmuseum" .) (include "harbor.clair" .) (include "harbor.notary-server" .) (include "harbor.notary-signer" .) (include "harbor.registry" .) (include "harbor.portal" .) (include "harbor.trivy" .) .Values.proxy.noProxy -}} {{- printf "%s-ingress" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- define "harbor.caBundleVolume" -}} {{- define "harbor.noProxy" -}}
- name: ca-bundle-certs {{- printf "%s,%s,%s,%s,%s,%s,%s,%s" (include "harbor.core" .) (include "harbor.jobservice" .) (include "harbor.database" .) (include "harbor.registry" .) (include "harbor.portal" .) (include "harbor.trivy" .) (include "harbor.exporter" .) .Values.proxy.noProxy -}}
secret: {{- end -}}
secretName: {{ .Values.caBundleSecretName }}
{{- end -}} {{- define "harbor.caBundleVolume" -}}
- name: ca-bundle-certs
{{- define "harbor.caBundleVolumeMount" -}} secret:
- name: ca-bundle-certs secretName: {{ .Values.caBundleSecretName }}
mountPath: /harbor_cust_cert/custom-ca.crt {{- end -}}
subPath: ca.crt
{{- end -}} {{- define "harbor.caBundleVolumeMount" -}}
- name: ca-bundle-certs
{{/* scheme for all components except notary because it only support http mode */}} mountPath: /harbor_cust_cert/custom-ca.crt
{{- define "harbor.component.scheme" -}} subPath: ca.crt
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "https" -}}
{{- else -}} {{/* scheme for all components because it only support http mode */}}
{{- printf "http" -}} {{- define "harbor.component.scheme" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "https" -}}
{{- else -}}
{{/* chartmuseum component container port */}} {{- printf "http" -}}
{{- define "harbor.chartmuseum.containerPort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "9443" -}}
{{- else -}} {{/* core component container port */}}
{{- printf "9999" -}} {{- define "harbor.core.containerPort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "8443" -}}
{{- else -}}
{{/* chartmuseum component service port */}} {{- printf "8080" -}}
{{- define "harbor.chartmuseum.servicePort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "443" -}}
{{- else -}} {{/* core component service port */}}
{{- printf "80" -}} {{- define "harbor.core.servicePort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "443" -}}
{{- else -}}
{{/* clair adapter component container port */}} {{- printf "80" -}}
{{- define "harbor.clairAdapter.containerPort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "8443" -}}
{{- else -}} {{/* jobservice component container port */}}
{{- printf "8080" -}} {{- define "harbor.jobservice.containerPort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "8443" -}}
{{- else -}}
{{/* clair adapter component service port */}} {{- printf "8080" -}}
{{- define "harbor.clairAdapter.servicePort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "8443" -}}
{{- else -}} {{/* jobservice component service port */}}
{{- printf "8080" -}} {{- define "harbor.jobservice.servicePort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "443" -}}
{{- else -}}
{{/* core component container port */}} {{- printf "80" -}}
{{- define "harbor.core.containerPort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "8443" -}}
{{- else -}} {{/* portal component container port */}}
{{- printf "8080" -}} {{- define "harbor.portal.containerPort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "8443" -}}
{{- else -}}
{{/* core component service port */}} {{- printf "8080" -}}
{{- define "harbor.core.servicePort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "443" -}}
{{- else -}} {{/* portal component service port */}}
{{- printf "80" -}} {{- define "harbor.portal.servicePort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "443" -}}
{{- else -}}
{{/* jobservice component container port */}} {{- printf "80" -}}
{{- define "harbor.jobservice.containerPort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "8443" -}}
{{- else -}} {{/* registry component container port */}}
{{- printf "8080" -}} {{- define "harbor.registry.containerPort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "5443" -}}
{{- else -}}
{{/* jobservice component service port */}} {{- printf "5000" -}}
{{- define "harbor.jobservice.servicePort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "443" -}}
{{- else -}} {{/* registry component service port */}}
{{- printf "80" -}} {{- define "harbor.registry.servicePort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "5443" -}}
{{- else -}}
{{/* portal component container port */}} {{- printf "5000" -}}
{{- define "harbor.portal.containerPort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "8443" -}}
{{- else -}} {{/* registryctl component container port */}}
{{- printf "8080" -}} {{- define "harbor.registryctl.containerPort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "8443" -}}
{{- else -}}
{{/* portal component service port */}} {{- printf "8080" -}}
{{- define "harbor.portal.servicePort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "443" -}}
{{- else -}} {{/* registryctl component service port */}}
{{- printf "80" -}} {{- define "harbor.registryctl.servicePort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "8443" -}}
{{- else -}}
{{/* registry component container port */}} {{- printf "8080" -}}
{{- define "harbor.registry.containerPort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "5443" -}}
{{- else -}} {{/* trivy component container port */}}
{{- printf "5000" -}} {{- define "harbor.trivy.containerPort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "8443" -}}
{{- else -}}
{{/* registry component service port */}} {{- printf "8080" -}}
{{- define "harbor.registry.servicePort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "5443" -}}
{{- else -}} {{/* trivy component service port */}}
{{- printf "5000" -}} {{- define "harbor.trivy.servicePort" -}}
{{- end -}} {{- if .Values.internalTLS.enabled -}}
{{- end -}} {{- printf "8443" -}}
{{- else -}}
{{/* registryctl component container port */}} {{- printf "8080" -}}
{{- define "harbor.registryctl.containerPort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}} {{- end -}}
{{- printf "8443" -}}
{{- else -}} {{/* CORE_URL */}}
{{- printf "8080" -}} {{/* port is included in this url as a workaround for issue https://github.com/aquasecurity/harbor-scanner-trivy/issues/108 */}}
{{- end -}} {{- define "harbor.coreURL" -}}
{{- end -}} {{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.core" .) (include "harbor.core.servicePort" .) -}}
{{- end -}}
{{/* registryctl component service port */}}
{{- define "harbor.registryctl.servicePort" -}} {{/* JOBSERVICE_URL */}}
{{- if .Values.internalTLS.enabled -}} {{- define "harbor.jobserviceURL" -}}
{{- printf "8443" -}} {{- printf "%s://%s-jobservice" (include "harbor.component.scheme" .) (include "harbor.fullname" .) -}}
{{- else -}} {{- end -}}
{{- printf "8080" -}}
{{- end -}} {{/* PORTAL_URL */}}
{{- end -}} {{- define "harbor.portalURL" -}}
{{- printf "%s://%s" (include "harbor.component.scheme" .) (include "harbor.portal" .) -}}
{{/* trivy component container port */}} {{- end -}}
{{- define "harbor.trivy.containerPort" -}}
{{- if .Values.internalTLS.enabled -}} {{/* REGISTRY_URL */}}
{{- printf "8443" -}} {{- define "harbor.registryURL" -}}
{{- else -}} {{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.registry" .) (include "harbor.registry.servicePort" .) -}}
{{- printf "8080" -}} {{- end -}}
{{- end -}}
{{- end -}} {{/* REGISTRY_CONTROLLER_URL */}}
{{- define "harbor.registryControllerURL" -}}
{{/* trivy component service port */}} {{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.registry" .) (include "harbor.registryctl.servicePort" .) -}}
{{- define "harbor.trivy.servicePort" -}} {{- end -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}} {{/* TOKEN_SERVICE_URL */}}
{{- else -}} {{- define "harbor.tokenServiceURL" -}}
{{- printf "8080" -}} {{- printf "%s/service/token" (include "harbor.coreURL" .) -}}
{{- end -}} {{- end -}}
{{- end -}}
{{/* TRIVY_ADAPTER_URL */}}
{{/* CLAIR_ADAPTER_URL */}} {{- define "harbor.trivyAdapterURL" -}}
{{- define "harbor.clairAdapterURL" -}} {{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.trivy" .) (include "harbor.trivy.servicePort" .) -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.clair" .) (include "harbor.clairAdapter.servicePort" .) -}} {{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.core.secretName" -}}
{{/* CORE_URL */}} {{- if eq .Values.internalTLS.certSource "secret" -}}
{{/* port is included in this url as a workaround for issue https://github.com/aquasecurity/harbor-scanner-trivy/issues/108 */}} {{- .Values.internalTLS.core.secretName -}}
{{- define "harbor.coreURL" -}} {{- else -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.core" .) (include "harbor.core.servicePort" .) -}} {{- printf "%s-core-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}} {{- end -}}
{{- end -}}
{{/* JOBSERVICE_URL */}}
{{- define "harbor.jobserviceURL" -}} {{- define "harbor.internalTLS.jobservice.secretName" -}}
{{- printf "%s://%s-jobservice" (include "harbor.component.scheme" .) (include "harbor.fullname" .) -}} {{- if eq .Values.internalTLS.certSource "secret" -}}
{{- end -}} {{- .Values.internalTLS.jobservice.secretName -}}
{{- else -}}
{{/* PORTAL_URL */}} {{- printf "%s-jobservice-internal-tls" (include "harbor.fullname" .) -}}
{{- define "harbor.portalURL" -}} {{- end -}}
{{- printf "%s://%s" (include "harbor.component.scheme" .) (include "harbor.portal" .) -}} {{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.portal.secretName" -}}
{{/* REGISTRY_URL */}} {{- if eq .Values.internalTLS.certSource "secret" -}}
{{- define "harbor.registryURL" -}} {{- .Values.internalTLS.portal.secretName -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.registry" .) (include "harbor.registry.servicePort" .) -}} {{- else -}}
{{- end -}} {{- printf "%s-portal-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{/* REGISTRY_CONTROLLER_URL */}} {{- end -}}
{{- define "harbor.registryControllerURL" -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.registry" .) (include "harbor.registryctl.servicePort" .) -}} {{- define "harbor.internalTLS.registry.secretName" -}}
{{- end -}} {{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.registry.secretName -}}
{{/* TOKEN_SERVICE_URL */}} {{- else -}}
{{- define "harbor.tokenServiceURL" -}} {{- printf "%s-registry-internal-tls" (include "harbor.fullname" .) -}}
{{- printf "%s/service/token" (include "harbor.coreURL" .) -}} {{- end -}}
{{- end -}} {{- end -}}
{{/* TRIVY_ADAPTER_URL */}} {{- define "harbor.internalTLS.trivy.secretName" -}}
{{- define "harbor.trivyAdapterURL" -}} {{- if eq .Values.internalTLS.certSource "secret" -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.trivy" .) (include "harbor.trivy.servicePort" .) -}} {{- .Values.internalTLS.trivy.secretName -}}
{{- end -}} {{- else -}}
{{- printf "%s-trivy-internal-tls" (include "harbor.fullname" .) -}}
{{- define "harbor.internalTLS.chartmuseum.secretName" -}} {{- end -}}
{{- if eq .Values.internalTLS.certSource "secret" -}} {{- end -}}
{{- .Values.internalTLS.chartmuseum.secretName -}}
{{- else -}} {{- define "harbor.tlsCoreSecretForIngress" -}}
{{- printf "%s-chartmuseum-internal-tls" (include "harbor.fullname" .) -}} {{- if eq .Values.expose.tls.certSource "none" -}}
{{- end -}} {{- printf "" -}}
{{- end -}} {{- else if eq .Values.expose.tls.certSource "secret" -}}
{{- .Values.expose.tls.secret.secretName -}}
{{- define "harbor.internalTLS.clair.secretName" -}} {{- else -}}
{{- if eq .Values.internalTLS.certSource "secret" -}} {{- include "harbor.ingress" . -}}
{{- .Values.internalTLS.clair.secretName -}} {{- end -}}
{{- else -}} {{- end -}}
{{- printf "%s-clair-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}} {{- define "harbor.tlsSecretForNginx" -}}
{{- end -}} {{- if eq .Values.expose.tls.certSource "secret" -}}
{{- .Values.expose.tls.secret.secretName -}}
{{- define "harbor.internalTLS.core.secretName" -}} {{- else -}}
{{- if eq .Values.internalTLS.certSource "secret" -}} {{- include "harbor.nginx" . -}}
{{- .Values.internalTLS.core.secretName -}} {{- end -}}
{{- else -}} {{- end -}}
{{- printf "%s-core-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}} {{- define "harbor.metricsPortName" -}}
{{- end -}} {{- if .Values.internalTLS.enabled }}
{{- printf "https-metrics" -}}
{{- define "harbor.internalTLS.jobservice.secretName" -}} {{- else -}}
{{- if eq .Values.internalTLS.certSource "secret" -}} {{- printf "http-metrics" -}}
{{- .Values.internalTLS.jobservice.secretName -}} {{- end -}}
{{- else -}} {{- end -}}
{{- printf "%s-jobservice-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}} {{- define "harbor.traceEnvs" -}}
{{- end -}} TRACE_ENABLED: "{{ .Values.trace.enabled }}"
TRACE_SAMPLE_RATE: "{{ .Values.trace.sample_rate }}"
{{- define "harbor.internalTLS.portal.secretName" -}} TRACE_NAMESPACE: "{{ .Values.trace.namespace }}"
{{- if eq .Values.internalTLS.certSource "secret" -}} {{- if .Values.trace.attributes }}
{{- .Values.internalTLS.portal.secretName -}} TRACE_ATTRIBUTES: {{ .Values.trace.attributes | toJson | squote }}
{{- else -}} {{- end }}
{{- printf "%s-portal-internal-tls" (include "harbor.fullname" .) -}} {{- if eq .Values.trace.provider "jaeger" }}
{{- end -}} TRACE_JAEGER_ENDPOINT: "{{ .Values.trace.jaeger.endpoint }}"
{{- end -}} TRACE_JAEGER_USERNAME: "{{ .Values.trace.jaeger.username }}"
TRACE_JAEGER_AGENT_HOSTNAME: "{{ .Values.trace.jaeger.agent_host }}"
{{- define "harbor.internalTLS.registry.secretName" -}} TRACE_JAEGER_AGENT_PORT: "{{ .Values.trace.jaeger.agent_port }}"
{{- if eq .Values.internalTLS.certSource "secret" -}} {{- else }}
{{- .Values.internalTLS.registry.secretName -}} TRACE_OTEL_ENDPOINT: "{{ .Values.trace.otel.endpoint }}"
{{- else -}} TRACE_OTEL_URL_PATH: "{{ .Values.trace.otel.url_path }}"
{{- printf "%s-registry-internal-tls" (include "harbor.fullname" .) -}} TRACE_OTEL_COMPRESSION: "{{ .Values.trace.otel.compression }}"
{{- end -}} TRACE_OTEL_INSECURE: "{{ .Values.trace.otel.insecure }}"
{{- end -}} TRACE_OTEL_TIMEOUT: "{{ .Values.trace.otel.timeout }}"
{{- end }}
{{- define "harbor.internalTLS.trivy.secretName" -}} {{- end -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.trivy.secretName -}} {{- define "harbor.traceEnvsForCore" -}}
{{- else -}} {{- if .Values.trace.enabled }}
{{- printf "%s-trivy-internal-tls" (include "harbor.fullname" .) -}} TRACE_SERVICE_NAME: "harbor-core"
{{- end -}} {{ include "harbor.traceEnvs" . }}
{{- end -}} {{- end }}
{{- end -}}
{{- define "harbor.tlsCoreSecretForIngress" -}}
{{- if eq .Values.expose.tls.certSource "none" -}} {{- define "harbor.traceEnvsForJobservice" -}}
{{- printf "" -}} {{- if .Values.trace.enabled }}
{{- else if eq .Values.expose.tls.certSource "secret" -}} TRACE_SERVICE_NAME: "harbor-jobservice"
{{- .Values.expose.tls.secret.secretName -}} {{ include "harbor.traceEnvs" . }}
{{- else -}} {{- end }}
{{- include "harbor.ingress" . -}} {{- end -}}
{{- end -}}
{{- end -}} {{- define "harbor.traceEnvsForRegistryCtl" -}}
{{- if .Values.trace.enabled }}
{{- define "harbor.tlsNotarySecretForIngress" -}} TRACE_SERVICE_NAME: "harbor-registryctl"
{{- if eq .Values.expose.tls.certSource "none" -}} {{ include "harbor.traceEnvs" . }}
{{- printf "" -}} {{- end }}
{{- else if eq .Values.expose.tls.certSource "secret" -}} {{- end -}}
{{- .Values.expose.tls.secret.notarySecretName -}}
{{- else -}} {{- define "harbor.traceJaegerPassword" -}}
{{- include "harbor.ingress" . -}} {{- if and .Values.trace.enabled (eq .Values.trace.provider "jaeger") }}
{{- end -}} TRACE_JAEGER_PASSWORD: "{{ .Values.trace.jaeger.password | default "" | b64enc }}"
{{- end -}} {{- end }}
{{- end -}}
{{- define "harbor.tlsSecretForNginx" -}}
{{- if eq .Values.expose.tls.certSource "secret" -}} {{/* Allow KubeVersion to be overridden. */}}
{{- .Values.expose.tls.secret.secretName -}} {{- define "harbor.ingress.kubeVersion" -}}
{{- else -}} {{- default .Capabilities.KubeVersion.Version .Values.expose.ingress.kubeVersionOverride -}}
{{- include "harbor.nginx" . -}} {{- end -}}
{{- end -}}
{{- end -}}
{{- if .Values.chartmuseum.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
PORT: "{{ template "harbor.chartmuseum.containerPort" . }}"
{{- if .Values.internalTLS.enabled }}
TLS_CERT: "/etc/harbor/ssl/chartmuseum/tls.crt"
TLS_KEY: "/etc/harbor/ssl/chartmuseum/tls.key"
{{- end }}
{{- if eq "redis" (include "harbor.redis.scheme" .) }}
CACHE: "redis"
{{- else }}
CACHE: "redis_sentinel"
CACHE_REDIS_MASTERNAME: "{{ template "harbor.redis.masterSet" . }}"
{{- end }}
CACHE_REDIS_ADDR: "{{ template "harbor.redis.addr" . }}"
CACHE_REDIS_DB: "{{ template "harbor.redis.dbForChartmuseum" . }}"
BASIC_AUTH_USER: "chart_controller"
{{- if .Values.chartmuseum.absoluteUrl }}
CHART_URL: {{ .Values.externalURL }}.{{ $.Values.global.host }}/chartrepo
{{- end }}
DEPTH: "1"
{{- if eq .Values.logLevel "debug" }}
DEBUG: "true"
{{- else }}
DEBUG: "false"
{{- end }}
LOG_JSON: "true"
DISABLE_METRICS: "false"
DISABLE_API: "false"
DISABLE_STATEFILES: "false"
ALLOW_OVERWRITE: "true"
AUTH_ANONYMOUS_GET: "false"
CONTEXT_PATH: ""
INDEX_LIMIT: "0"
MAX_STORAGE_OBJECTS: "0"
MAX_UPLOAD_SIZE: "20971520"
CHART_POST_FORM_FIELD_NAME: "chart"
PROV_POST_FORM_FIELD_NAME: "prov"
{{- $storage := .Values.persistence.imageChartStorage }}
{{- $storageType := $storage.type }}
{{- if eq $storageType "filesystem" }}
STORAGE: "local"
STORAGE_LOCAL_ROOTDIR: "/chart_storage"
{{- else if eq $storageType "azure" }}
STORAGE: "microsoft"
STORAGE_MICROSOFT_CONTAINER: {{ $storage.azure.container }}
AZURE_STORAGE_ACCOUNT: {{ $storage.azure.accountname }}
AZURE_BASE_URL: {{ $storage.azure.realm }}
STORAGE_MICROSOFT_PREFIX: "/azure/harbor/charts"
{{- else if eq $storageType "gcs" }}
STORAGE: "google"
STORAGE_GOOGLE_BUCKET: {{ $storage.gcs.bucket }}
GOOGLE_APPLICATION_CREDENTIALS: /etc/chartmuseum/gcs-key.json
{{- if $storage.gcs.rootdirectory }}
STORAGE_GOOGLE_PREFIX: {{ $storage.gcs.rootdirectory }}
{{- end }}
{{- else if eq $storageType "s3" }}
STORAGE: "amazon"
STORAGE_AMAZON_BUCKET: {{ $storage.s3.bucket }}
{{- if $storage.s3.rootdirectory }}
STORAGE_AMAZON_PREFIX: {{ $storage.s3.rootdirectory }}
{{- end }}
STORAGE_AMAZON_REGION: {{ $storage.s3.region }}
{{- if $storage.s3.regionendpoint }}
STORAGE_AMAZON_ENDPOINT: {{ $storage.s3.regionendpoint }}
{{- end }}
{{- if $storage.s3.accesskey }}
AWS_ACCESS_KEY_ID: {{ $storage.s3.accesskey }}
{{- end }}
{{- if $storage.s3.keyid }}
STORAGE_AMAZON_SSE: aws:kms
{{- end }}
{{- else if eq $storageType "swift" }}
STORAGE: "openstack"
STORAGE_OPENSTACK_CONTAINER: {{ $storage.swift.container }}
{{- if $storage.swift.prefix }}
STORAGE_OPENSTACK_PREFIX: {{ $storage.swift.prefix }}
{{- end }}
{{- if $storage.swift.region }}
STORAGE_OPENSTACK_REGION: {{ $storage.swift.region }}
{{- end }}
OS_AUTH_URL: {{ $storage.swift.authurl }}
OS_USERNAME: {{ $storage.swift.username }}
{{- if $storage.swift.tenantid }}
OS_PROJECT_ID: {{ $storage.swift.tenantid }}
{{- end }}
{{- if $storage.swift.tenant }}
OS_PROJECT_NAME: {{ $storage.swift.tenant }}
{{- end }}
{{- if $storage.swift.domainid }}
OS_DOMAIN_ID: {{ $storage.swift.domainid }}
{{- end }}
{{- if $storage.swift.domain }}
OS_DOMAIN_NAME: {{ $storage.swift.domain }}
{{- end }}
{{- else if eq $storageType "oss" }}
STORAGE: "alibaba"
STORAGE_ALIBABA_BUCKET: {{ $storage.oss.bucket }}
{{- if $storage.oss.rootdirectory }}
STORAGE_ALIBABA_PREFIX: {{ $storage.oss.rootdirectory }}
{{- end }}
{{- if $storage.oss.endpoint }}
STORAGE_ALIBABA_ENDPOINT: {{ $storage.oss.endpoint }}
{{- end }}
ALIBABA_CLOUD_ACCESS_KEY_ID: {{ $storage.oss.accesskeyid }}
{{- end }}
STORAGE_TIMESTAMP_TOLERANCE: 1s
{{- end }}
{{- if .Values.chartmuseum.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
component: chartmuseum
spec:
replicas: {{ .Values.chartmuseum.replicas }}
strategy:
type: {{ .Values.updateStrategy.type }}
{{- if eq .Values.updateStrategy.type "Recreate" }}
rollingUpdate: null
{{- end }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: chartmuseum
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: chartmuseum
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/chartmuseum/chartmuseum-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/chartmuseum/chartmuseum-secret.yaml") . | sha256sum }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
checksum/tls: {{ include (print $.Template.BasePath "/chartmuseum/chartmuseum-tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.chartmuseum.podAnnotations }}
{{ toYaml .Values.chartmuseum.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
fsGroup: 10000
{{- if .Values.chartmuseum.serviceAccountName }}
serviceAccountName: {{ .Values.chartmuseum.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: chartmuseum
{{- if contains "/" .Values.chartmuseum.image.repository }}
image: "{{ .Values.chartmuseum.image.repository }}"
{{- else }}
image: "{{ .Values.chartmuseum.image.hub | default .Values.global.hub }}/{{ .Values.chartmuseum.image.repository }}:{{ .Values.chartmuseum.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}"
{{- end }}
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}"
livenessProbe:
httpGet:
path: /health
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.chartmuseum.containerPort" . }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.chartmuseum.containerPort" . }}
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.chartmuseum.resources }}
resources:
{{ toYaml .Values.chartmuseum.resources | indent 10 }}
{{- end }}
envFrom:
- configMapRef:
name: "{{ template "harbor.chartmuseum" . }}"
- secretRef:
name: "{{ template "harbor.chartmuseum" . }}"
env:
{{- if has "chartmuseum" .Values.proxy.components }}
- name: HTTP_PROXY
value: "{{ .Values.proxy.httpProxy }}"
- name: HTTPS_PROXY
value: "{{ .Values.proxy.httpsProxy }}"
- name: NO_PROXY
value: "{{ template "harbor.noProxy" . }}"
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: INTERNAL_TLS_ENABLED
value: "true"
- name: INTERNAL_TLS_KEY_PATH
value: /etc/harbor/ssl/chartmuseum/tls.key
- name: INTERNAL_TLS_CERT_PATH
value: /etc/harbor/ssl/chartmuseum/tls.crt
- name: INTERNAL_TLS_TRUST_CA_PATH
value: /etc/harbor/ssl/chartmuseum/ca.crt
{{- end }}
- name: BASIC_AUTH_PASS
valueFrom:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
- # Needed to make AWS' client connect correctly (see https://github.com/helm/chartmuseum/issues/280)
name: AWS_SDK_LOAD_CONFIG
value: "1"
ports:
- containerPort: {{ template "harbor.chartmuseum.containerPort" . }}
volumeMounts:
- name: chartmuseum-data
mountPath: /chart_storage
subPath: {{ .Values.persistence.persistentVolumeClaim.chartmuseum.subPath }}
{{- if .Values.internalTLS.enabled }}
- name: chart-internal-certs
mountPath: /etc/harbor/ssl/chartmuseum
{{- end }}
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs") }}
- name: gcs-key
mountPath: /etc/chartmuseum/gcs-key.json
subPath: gcs-key.json
{{- end }}
{{- if .Values.persistence.imageChartStorage.caBundleSecretName }}
- name: storage-service-ca
mountPath: /harbor_cust_cert/custom-ca-bundle.crt
subPath: ca.crt
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
volumes:
- name: chartmuseum-data
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "filesystem") }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.persistentVolumeClaim.chartmuseum.existingClaim | default (include "harbor.chartmuseum" .) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: chart-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.chartmuseum.secretName" . }}
{{- end }}
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs") }}
- name: gcs-key
secret:
secretName: {{ template "harbor.registry" . }}
items:
- key: GCS_KEY_DATA
path: gcs-key.json
{{- end }}
{{- if .Values.persistence.imageChartStorage.caBundleSecretName }}
- name: storage-service-ca
secret:
secretName: {{ .Values.persistence.imageChartStorage.caBundleSecretName }}
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- with .Values.chartmuseum.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.chartmuseum.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.chartmuseum.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}
{{- if .Values.chartmuseum.enabled }}
{{- $persistence := .Values.persistence -}}
{{- if $persistence.enabled }}
{{- $chartmuseum := $persistence.persistentVolumeClaim.chartmuseum -}}
{{- if and (not $chartmuseum.existingClaim) (eq $persistence.imageChartStorage.type "filesystem") }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: {{ template "harbor.chartmuseum" . }}
{{- if eq $persistence.resourcePolicy "keep" }}
annotations:
helm.sh/resource-policy: keep
{{- end }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: chartmuseum
spec:
accessModes:
- {{ $chartmuseum.accessMode }}
resources:
requests:
storage: {{ $chartmuseum.size }}
{{- if $chartmuseum.storageClass }}
{{- if eq "-" $chartmuseum.storageClass }}
storageClassName: ""
{{- else }}
storageClassName: {{ $chartmuseum.storageClass }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- if .Values.chartmuseum.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
CACHE_REDIS_PASSWORD: {{ include "harbor.redis.password" . | b64enc | quote }}
{{- $storage := .Values.persistence.imageChartStorage }}
{{- $storageType := $storage.type }}
{{- if eq $storageType "azure" }}
AZURE_STORAGE_ACCESS_KEY: {{ $storage.azure.accountkey | b64enc | quote }}
{{- else if eq $storageType "gcs" }}
# TODO support the keyfile of gcs
{{- else if eq $storageType "s3" }}
{{- if $storage.s3.secretkey }}
AWS_SECRET_ACCESS_KEY: {{ $storage.s3.secretkey | b64enc | quote }}
{{- end }}
{{- else if eq $storageType "swift" }}
OS_PASSWORD: {{ $storage.swift.password | b64enc | quote }}
{{- else if eq $storageType "oss" }}
ALIBABA_CLOUD_ACCESS_KEY_SECRET: {{ $storage.oss.accesskeysecret | b64enc | quote }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- if .Values.chartmuseum.enabled }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: {{ template "harbor.chartmuseum.servicePort" . }}
targetPort: {{ template "harbor.chartmuseum.containerPort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: chartmuseum
{{- end }}
\ No newline at end of file
{{- if and .Values.chartmuseum.enabled .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.chartmuseum.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
tls.ca: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.crt: {{ (required "The \"internalTLS.chartmuseum.crt\" is required!" .Values.internalTLS.chartmuseum.crt) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.chartmuseum.key\" is required!" .Values.internalTLS.chartmuseum.key) | b64enc | quote }}
{{- end }}
{{- end }}
{{ if .Values.clair.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.clair" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: clair
spec:
replicas: {{ .Values.clair.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: clair
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: clair
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/clair/clair-secret.yaml") . | sha256sum }}
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
checksum/tls: {{ include (print $.Template.BasePath "/clair/clair-tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.clair.podAnnotations }}
{{ toYaml .Values.clair.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
fsGroup: 10000
{{- if .Values.clair.serviceAccountName }}
serviceAccountName: {{ .Values.clair.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: clair
{{- if contains "/" .Values.clair.clair.image.repository }}
image: "{{ .Values.clair.clair.image.repository }}"
{{- else }}
image: "{{ .Values.clair.clair.image.hub | default .Values.global.hub }}/{{ .Values.clair.clair.image.repository }}:{{ .Values.clair.clair.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}"
{{- end }}
imagePullPolicy: "{{ .Values.global.imagePullPolicy }}"
livenessProbe:
httpGet:
path: /health
port: 6061
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 6061
initialDelaySeconds: 30
periodSeconds: 10
args: ["-log-level", "{{ .Values.logLevel }}"]
env:
{{- if has "clair" .Values.proxy.components }}
- name: HTTP_PROXY
value: "{{ .Values.proxy.httpProxy }}"
- name: HTTPS_PROXY
value: "{{ .Values.proxy.httpsProxy }}"
- name: NO_PROXY
value: "{{ template "harbor.noProxy" . }}"
{{- end }}
{{- if .Values.clair.clair.resources }}
resources:
{{ toYaml .Values.clair.clair.resources | indent 10 }}
{{- end }}
ports:
- containerPort: 6060
volumeMounts:
- name: config
mountPath: /etc/clair/config.yaml
subPath: config.yaml
{{- if .Values.internalTLS.enabled }}
- name: clair-internal-certs
mountPath: /etc/harbor/ssl/clair
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
- name: adapter
{{- if contains "/" .Values.clair.adapter.image.repository }}
image: "{{ .Values.clair.adapter.image.repository }}"
{{- else }}
image: "{{ .Values.clair.adapter.image.hub | default .Values.global.hub }}/{{ .Values.clair.adapter.image.repository }}:{{ .Values.clair.adapter.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}"
{{- end }}
imagePullPolicy: "{{ .Values.global.imagePullPolicy }}"
livenessProbe:
httpGet:
path: /probe/healthy
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.clairAdapter.containerPort" . }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /probe/ready
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.clairAdapter.containerPort" . }}
initialDelaySeconds: 30
periodSeconds: 10
env:
- name: SCANNER_CLAIR_URL
# To avoid a pod cannot reach itself via service IP when the clusters disable hairpin
value: "http://127.0.0.1:6060"
- name: SCANNER_STORE_REDIS_URL
valueFrom:
secretKeyRef:
name: {{ template "harbor.clair" . }}
key: redis
- name: SCANNER_CLAIR_DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ template "harbor.clair" . }}
key: database
{{- if .Values.internalTLS.enabled }}
- name: INTERNAL_TLS_ENABLED
value: "true"
- name: SCANNER_API_SERVER_ADDR
value: ":8443"
- name: SCANNER_API_SERVER_TLS_KEY
value: /etc/harbor/ssl/clair/tls.key
- name: SCANNER_API_SERVER_TLS_CERTIFICATE
value: /etc/harbor/ssl/clair/tls.crt
{{- end }}
- name: SCANNER_LOG_LEVEL
value: "{{ .Values.logLevel }}"
{{- if .Values.clair.adapter.resources }}
resources:
{{ toYaml .Values.clair.adapter.resources | indent 10 }}
{{- end }}
ports:
- containerPort: {{ template "harbor.clairAdapter.containerPort" . }}
{{- if or .Values.internalTLS.enabled .Values.caBundleSecretName }}
volumeMounts:
{{- if .Values.internalTLS.enabled }}
- name: clair-internal-certs
mountPath: /etc/harbor/ssl/clair
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
{{- end }}
volumes:
- name: config
secret:
secretName: "{{ template "harbor.clair" . }}"
{{- if .Values.internalTLS.enabled }}
- name: clair-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.clair.secretName" . }}
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- with .Values.clair.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.clair.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.clair.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{ end }}
{{- if .Values.clair.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "harbor.clair" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
config.yaml: {{ tpl (.Files.Get "conf/clair.yaml") . | b64enc }}
redis: {{ include "harbor.redis.urlForClair" . | b64enc }}
database: {{ include "harbor.database.clair" . | b64enc }}
{{- end }}
\ No newline at end of file
{{- if and .Values.clair.enabled .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.clair.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.crt: {{ (required "The \"internalTLS.clair.crt\" is required!" .Values.internalTLS.clair.crt) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.clair.key\" is required!" .Values.internalTLS.clair.key) | b64enc | quote }}
{{- end }}
{{- end }}
\ No newline at end of file
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: {{ template "harbor.core" . }} name: {{ template "harbor.core" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
data: {{ include "harbor.labels" . | indent 4 }}
app.conf: |+ data:
appname = Harbor app.conf: |+
runmode = prod appname = Harbor
enablegzip = true runmode = prod
enablegzip = true
[prod]
httpport = {{ ternary "8443" "8080" .Values.internalTLS.enabled }} [prod]
PORT: "{{ ternary "8443" "8080" .Values.internalTLS.enabled }}" httpport = {{ ternary "8443" "8080" .Values.internalTLS.enabled }}
DATABASE_TYPE: "postgresql" PORT: "{{ ternary "8443" "8080" .Values.internalTLS.enabled }}"
POSTGRESQL_HOST: "{{ template "harbor.database.host" . }}" DATABASE_TYPE: "postgresql"
POSTGRESQL_PORT: "{{ template "harbor.database.port" . }}" POSTGRESQL_HOST: "{{ template "harbor.database.host" . }}"
POSTGRESQL_USERNAME: "{{ template "harbor.database.username" . }}" POSTGRESQL_PORT: "{{ template "harbor.database.port" . }}"
POSTGRESQL_DATABASE: "{{ template "harbor.database.coreDatabase" . }}" POSTGRESQL_USERNAME: "{{ template "harbor.database.username" . }}"
POSTGRESQL_SSLMODE: "{{ template "harbor.database.sslmode" . }}" POSTGRESQL_DATABASE: "{{ template "harbor.database.coreDatabase" . }}"
POSTGRESQL_MAX_IDLE_CONNS: "{{ .Values.database.maxIdleConns }}" POSTGRESQL_SSLMODE: "{{ template "harbor.database.sslmode" . }}"
POSTGRESQL_MAX_OPEN_CONNS: "{{ .Values.database.maxOpenConns }}" POSTGRESQL_MAX_IDLE_CONNS: "{{ .Values.database.maxIdleConns }}"
EXT_ENDPOINT: "{{ .Values.externalURL }}.{{ $.Values.global.host }}" POSTGRESQL_MAX_OPEN_CONNS: "{{ .Values.database.maxOpenConns }}"
CORE_URL: "{{ template "harbor.coreURL" . }}" EXT_ENDPOINT: "{{ .Values.externalURL }}"
JOBSERVICE_URL: "{{ template "harbor.jobserviceURL" . }}" CORE_URL: "{{ template "harbor.coreURL" . }}"
REGISTRY_URL: "{{ template "harbor.registryURL" . }}" JOBSERVICE_URL: "{{ template "harbor.jobserviceURL" . }}"
TOKEN_SERVICE_URL: "{{ template "harbor.tokenServiceURL" . }}" REGISTRY_URL: "{{ template "harbor.registryURL" . }}"
WITH_NOTARY: "{{ .Values.notary.enabled }}" TOKEN_SERVICE_URL: "{{ template "harbor.tokenServiceURL" . }}"
NOTARY_URL: "http://{{ template "harbor.notary-server" . }}:4443" CORE_LOCAL_URL: "{{ ternary "https://127.0.0.1:8443" "http://127.0.0.1:8080" .Values.internalTLS.enabled }}"
CORE_LOCAL_URL: "{{ ternary "https://127.0.0.1:8443" "http://127.0.0.1:8080" .Values.internalTLS.enabled }}" WITH_TRIVY: {{ .Values.trivy.enabled | quote }}
WITH_CLAIR: "{{ .Values.clair.enabled }}" TRIVY_ADAPTER_URL: "{{ template "harbor.trivyAdapterURL" . }}"
CLAIR_ADAPTER_URL: "{{ template "harbor.clairAdapterURL" . }}" REGISTRY_STORAGE_PROVIDER_NAME: "{{ .Values.persistence.imageChartStorage.type }}"
WITH_TRIVY: {{ .Values.trivy.enabled | quote }} LOG_LEVEL: "{{ .Values.logLevel }}"
TRIVY_ADAPTER_URL: "{{ template "harbor.trivyAdapterURL" . }}" CONFIG_PATH: "/etc/core/app.conf"
REGISTRY_STORAGE_PROVIDER_NAME: "{{ .Values.persistence.imageChartStorage.type }}" CHART_CACHE_DRIVER: "redis"
WITH_CHARTMUSEUM: "{{ .Values.chartmuseum.enabled }}" _REDIS_URL_CORE: "{{ template "harbor.redis.urlForCore" . }}"
CHART_REPOSITORY_URL: "{{ template "harbor.component.scheme" . }}://{{ template "harbor.chartmuseum" . }}" _REDIS_URL_REG: "{{ template "harbor.redis.urlForRegistry" . }}"
LOG_LEVEL: "{{ .Values.logLevel }}" {{- if or (and (eq .Values.redis.type "internal") .Values.redis.internal.harborDatabaseIndex) (and (eq .Values.redis.type "external") .Values.redis.external.harborDatabaseIndex) }}
CONFIG_PATH: "/etc/core/app.conf" _REDIS_URL_HARBOR: "{{ template "harbor.redis.urlForHarbor" . }}"
CHART_CACHE_DRIVER: "redis" {{- end }}
_REDIS_URL_CORE: "{{ template "harbor.redis.urlForCore" . }}" {{- if or (and (eq .Values.redis.type "internal") .Values.redis.internal.cacheLayerDatabaseIndex) (and (eq .Values.redis.type "external") .Values.redis.external.cacheLayerDatabaseIndex) }}
_REDIS_URL_REG: "{{ template "harbor.redis.urlForRegistry" . }}" _REDIS_URL_CACHE_LAYER: "{{ template "harbor.redis.urlForCache" . }}"
PORTAL_URL: "{{ template "harbor.portalURL" . }}" {{- end }}
REGISTRY_CONTROLLER_URL: "{{ template "harbor.registryControllerURL" . }}" PORTAL_URL: "{{ template "harbor.portalURL" . }}"
REGISTRY_CREDENTIAL_USERNAME: "{{ .Values.registry.credentials.username }}" REGISTRY_CONTROLLER_URL: "{{ template "harbor.registryControllerURL" . }}"
{{- if .Values.uaaSecretName }} REGISTRY_CREDENTIAL_USERNAME: "{{ .Values.registry.credentials.username }}"
UAA_CA_ROOT: "/etc/core/auth-ca/auth-ca.crt" {{- if .Values.uaaSecretName }}
{{- end }} UAA_CA_ROOT: "/etc/core/auth-ca/auth-ca.crt"
{{- if has "core" .Values.proxy.components }} {{- end }}
HTTP_PROXY: "{{ .Values.proxy.httpProxy }}" {{- if has "core" .Values.proxy.components }}
HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}" HTTP_PROXY: "{{ .Values.proxy.httpProxy }}"
NO_PROXY: "{{ template "harbor.noProxy" . }}" HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}"
{{- end }} NO_PROXY: "{{ template "harbor.noProxy" . }}"
PERMITTED_REGISTRY_TYPES_FOR_PROXY_CACHE: "docker-hub,harbor" {{- end }}
{{- if hasKey .Values.core "gcTimeWindowHours" }} PERMITTED_REGISTRY_TYPES_FOR_PROXY_CACHE: "docker-hub,harbor,azure-acr,aws-ecr,google-gcr,quay,docker-registry,github-ghcr,jfrog-artifactory"
#make the GC time window configurable for testing {{- if .Values.metrics.enabled}}
GC_TIME_WINDOW_HOURS: "{{ .Values.core.gcTimeWindowHours }}" METRIC_ENABLE: "true"
{{- end }} METRIC_PATH: "{{ .Values.metrics.core.path }}"
\ No newline at end of file METRIC_PORT: "{{ .Values.metrics.core.port }}"
METRIC_NAMESPACE: harbor
METRIC_SUBSYSTEM: core
{{- end }}
{{- if hasKey .Values.core "gcTimeWindowHours" }}
#make the GC time window configurable for testing
GC_TIME_WINDOW_HOURS: "{{ .Values.core.gcTimeWindowHours }}"
{{- end }}
{{- template "harbor.traceEnvsForCore" . }}
{{- if .Values.core.artifactPullAsyncFlushDuration }}
ARTIFACT_PULL_ASYNC_FLUSH_DURATION: {{ .Values.core.artifactPullAsyncFlushDuration | quote }}
{{- end }}
{{- if .Values.core.gdpr}}
{{- if .Values.core.gdpr.deleteUser}}
GDPR_DELETE_USER: "true"
{{- end }}
{{- if .Values.core.gdpr.auditLogsCompliant}}
GDPR_AUDIT_LOGS: "true"
{{- end }}
{{- end }}
{{- if .Values.cache.enabled }}
CACHE_ENABLED: "true"
CACHE_EXPIRE_HOURS: "{{ .Values.cache.expireHours }}"
{{- end }}
{{- if .Values.core.quotaUpdateProvider }}
QUOTA_UPDATE_PROVIDER: "{{ .Values.core.quotaUpdateProvider }}"
{{- end }}
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ template "harbor.core" . }} name: {{ template "harbor.core" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
component: core {{ include "harbor.labels" . | indent 4 }}
spec: component: core
replicas: {{ .Values.core.replicas }} app.kubernetes.io/component: core
selector: spec:
matchLabels: replicas: {{ .Values.core.replicas }}
{{ include "harbor.matchLabels" . | indent 6 }} revisionHistoryLimit: {{ .Values.core.revisionHistoryLimit }}
component: core selector:
template: matchLabels:
metadata: {{ include "harbor.matchLabels" . | indent 6 }}
labels: component: core
{{ include "harbor.labels" . | indent 8 }} template:
component: core metadata:
annotations: labels:
checksum/configmap: {{ include (print $.Template.BasePath "/core/core-cm.yaml") . | sha256sum }} {{ include "harbor.labels" . | indent 8 }}
checksum/secret: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }} component: core
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }} app.kubernetes.io/component: core
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }} {{- if .Values.core.podLabels }}
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }} {{ toYaml .Values.core.podLabels | indent 8 }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }} {{- end }}
checksum/tls: {{ include (print $.Template.BasePath "/core/core-tls.yaml") . | sha256sum }} annotations:
{{- end }} checksum/configmap: {{ include (print $.Template.BasePath "/core/core-cm.yaml") . | sha256sum }}
{{- if .Values.core.podAnnotations }} checksum/secret: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{ toYaml .Values.core.podAnnotations | indent 8 }} checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
{{- end }} {{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
spec: checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- with .Values.global.imagePullSecrets }} {{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
imagePullSecrets: checksum/tls: {{ include (print $.Template.BasePath "/core/core-tls.yaml") . | sha256sum }}
{{- toYaml . | nindent 8 }} {{- end }}
{{- end }} {{- if .Values.core.podAnnotations }}
securityContext: {{ toYaml .Values.core.podAnnotations | indent 8 }}
fsGroup: 10000 {{- end }}
{{- if .Values.core.serviceAccountName }} spec:
serviceAccountName: {{ .Values.core.serviceAccountName }} securityContext:
{{- end -}} runAsUser: 10000
{{- with .Values.imagePullSecrets }} fsGroup: 10000
imagePullSecrets: {{- if .Values.core.serviceAccountName }}
{{- toYaml . | nindent 8 }} serviceAccountName: {{ .Values.core.serviceAccountName }}
{{- end }} {{- end -}}
containers: {{- with .Values.imagePullSecrets }}
- name: core imagePullSecrets:
{{- if contains "/" .Values.core.image.repository }} {{- toYaml . | nindent 8 }}
image: "{{ .Values.core.image.repository }}" {{- end }}
{{- else }} automountServiceAccountToken: {{ .Values.core.automountServiceAccountToken | default false }}
image: "{{ .Values.core.image.hub | default .Values.global.hub }}/{{ .Values.core.image.repository }}:{{ .Values.core.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" terminationGracePeriodSeconds: 120
{{- end }} {{- with .Values.core.topologySpreadConstraints}}
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" topologySpreadConstraints:
{{- if .Values.core.startupProbe.enabled }} {{- range . }}
startupProbe: - {{ . | toYaml | indent 8 | trim }}
httpGet: labelSelector:
path: /api/v2.0/ping matchLabels:
scheme: {{ include "harbor.component.scheme" . | upper }} {{ include "harbor.matchLabels" $ | indent 12 }}
port: {{ template "harbor.core.containerPort" . }} component: core
failureThreshold: 360 {{- end }}
initialDelaySeconds: {{ .Values.core.startupProbe.initialDelaySeconds }} {{- end }}
periodSeconds: 10 {{- with .Values.core.initContainers }}
{{- end }} initContainers:
livenessProbe: {{- toYaml . | nindent 8 }}
httpGet: {{- end }}
path: /api/v2.0/ping containers:
scheme: {{ include "harbor.component.scheme" . | upper }} - name: core
port: {{ template "harbor.core.containerPort" . }} image: {{ .Values.core.image.repository }}:{{ .Values.core.image.tag }}
failureThreshold: 2 imagePullPolicy: {{ .Values.imagePullPolicy }}
periodSeconds: 10 {{- if .Values.core.startupProbe.enabled }}
readinessProbe: startupProbe:
httpGet: httpGet:
path: /api/v2.0/ping path: /api/v2.0/ping
scheme: {{ include "harbor.component.scheme" . | upper }} scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.core.containerPort" . }} port: {{ template "harbor.core.containerPort" . }}
failureThreshold: 2 failureThreshold: 360
periodSeconds: 10 initialDelaySeconds: {{ .Values.core.startupProbe.initialDelaySeconds }}
envFrom: periodSeconds: 10
- configMapRef: {{- end }}
name: "{{ template "harbor.core" . }}" livenessProbe:
- secretRef: httpGet:
name: "{{ template "harbor.core" . }}" path: /api/v2.0/ping
env: scheme: {{ include "harbor.component.scheme" . | upper }}
- name: CORE_SECRET port: {{ template "harbor.core.containerPort" . }}
valueFrom: failureThreshold: 2
secretKeyRef: periodSeconds: 10
name: {{ template "harbor.core" . }} readinessProbe:
key: secret httpGet:
- name: JOBSERVICE_SECRET path: /api/v2.0/ping
valueFrom: scheme: {{ include "harbor.component.scheme" . | upper }}
secretKeyRef: port: {{ template "harbor.core.containerPort" . }}
name: "{{ template "harbor.jobservice" . }}" failureThreshold: 2
key: JOBSERVICE_SECRET periodSeconds: 10
{{- if .Values.internalTLS.enabled }} envFrom:
- name: INTERNAL_TLS_ENABLED - configMapRef:
value: "true" name: "{{ template "harbor.core" . }}"
- name: INTERNAL_TLS_KEY_PATH - secretRef:
value: /etc/harbor/ssl/core/tls.key name: "{{ template "harbor.core" . }}"
- name: INTERNAL_TLS_CERT_PATH env:
value: /etc/harbor/ssl/core/tls.crt - name: CORE_SECRET
- name: INTERNAL_TLS_TRUST_CA_PATH valueFrom:
value: /etc/harbor/ssl/core/ca.crt secretKeyRef:
{{- end }} name: {{ default (include "harbor.core" .) .Values.core.existingSecret }}
ports: key: secret
- containerPort: {{ template "harbor.core.containerPort" . }} - name: JOBSERVICE_SECRET
volumeMounts: valueFrom:
- name: config secretKeyRef:
mountPath: /etc/core/app.conf name: {{ default (include "harbor.jobservice" .) .Values.jobservice.existingSecret }}
subPath: app.conf {{- if .Values.jobservice.existingSecret }}
- name: secret-key key: {{ .Values.jobservice.existingSecretKey }}
mountPath: /etc/core/key {{- else }}
subPath: key key: JOBSERVICE_SECRET
- name: token-service-private-key {{- end }}
mountPath: /etc/core/private_key.pem {{- if .Values.existingSecretAdminPassword }}
subPath: tls.key - name: HARBOR_ADMIN_PASSWORD
{{- if .Values.expose.tls.enabled }} valueFrom:
- name: ca-download secretKeyRef:
mountPath: /etc/core/ca name: {{ .Values.existingSecretAdminPassword }}
{{- end }} key: {{ .Values.existingSecretAdminPasswordKey }}
{{- if .Values.uaaSecretName }} {{- end }}
- name: auth-ca-cert {{- if .Values.internalTLS.enabled }}
mountPath: /etc/core/auth-ca/auth-ca.crt - name: INTERNAL_TLS_ENABLED
subPath: auth-ca.crt value: "true"
{{- end }} - name: INTERNAL_TLS_KEY_PATH
{{- if .Values.internalTLS.enabled }} value: /etc/harbor/ssl/core/tls.key
- name: core-internal-certs - name: INTERNAL_TLS_CERT_PATH
mountPath: /etc/harbor/ssl/core value: /etc/harbor/ssl/core/tls.crt
{{- end }} - name: INTERNAL_TLS_TRUST_CA_PATH
- name: psc value: /etc/harbor/ssl/core/ca.crt
mountPath: /etc/core/token {{- end }}
{{- if .Values.caBundleSecretName }} {{- if .Values.database.external.existingSecret }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }} - name: POSTGRESQL_PASSWORD
{{- end }} valueFrom:
{{- if .Values.core.resources }} secretKeyRef:
resources: name: {{ .Values.database.external.existingSecret }}
{{ toYaml .Values.core.resources | indent 10 }} key: password
{{- end }} {{- end }}
volumes: {{- if .Values.registry.credentials.existingSecret }}
- name: config - name: REGISTRY_CREDENTIAL_PASSWORD
configMap: valueFrom:
name: {{ template "harbor.core" . }} secretKeyRef:
items: name: {{ .Values.registry.credentials.existingSecret }}
- key: app.conf key: REGISTRY_PASSWD
path: app.conf {{- end }}
- name: secret-key {{- if .Values.core.existingXsrfSecret }}
secret: - name: CSRF_KEY
secretName: {{ template "harbor.core" . }} valueFrom:
items: secretKeyRef:
- key: secretKey name: {{ .Values.core.existingXsrfSecret }}
path: key key: {{ .Values.core.existingXsrfSecretKey }}
- name: token-service-private-key {{- end }}
secret: {{- with .Values.core.extraEnvVars }}
{{- if .Values.core.secretName }} {{- toYaml . | nindent 10 }}
secretName: {{ .Values.core.secretName }} {{- end }}
{{- else }} {{- if not (empty .Values.containerSecurityContext) }}
secretName: {{ template "harbor.core" . }} securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
{{- end }} {{- end }}
{{- if .Values.expose.tls.enabled }} ports:
- name: ca-download - containerPort: {{ template "harbor.core.containerPort" . }}
secret: volumeMounts:
{{- if .Values.caSecretName }} - name: config
secretName: {{ .Values.caSecretName }} mountPath: /etc/core/app.conf
{{- else if eq (include "harbor.autoGenCertForIngress" .) "true" }} subPath: app.conf
secretName: "{{ template "harbor.ingress" . }}" - name: secret-key
{{- else if eq (include "harbor.autoGenCertForNginx" .) "true" }} mountPath: /etc/core/key
secretName: {{ template "harbor.tlsSecretForNginx" . }} subPath: key
{{- end }} - name: token-service-private-key
{{- end }} mountPath: /etc/core/private_key.pem
{{- if .Values.uaaSecretName }} subPath: tls.key
- name: auth-ca-cert {{- if .Values.expose.tls.enabled }}
secret: - name: ca-download
secretName: {{ .Values.uaaSecretName }} mountPath: /etc/core/ca
items: {{- end }}
- key: ca.crt {{- if .Values.uaaSecretName }}
path: auth-ca.crt - name: auth-ca-cert
{{- end }} mountPath: /etc/core/auth-ca/auth-ca.crt
{{- if .Values.internalTLS.enabled }} subPath: auth-ca.crt
- name: core-internal-certs {{- end }}
secret: {{- if .Values.internalTLS.enabled }}
secretName: {{ template "harbor.internalTLS.core.secretName" . }} - name: core-internal-certs
{{- end }} mountPath: /etc/harbor/ssl/core
- name: psc {{- end }}
emptyDir: {} - name: psc
{{- if .Values.caBundleSecretName }} mountPath: /etc/core/token
{{ include "harbor.caBundleVolume" . | indent 6 }} {{- if .Values.caBundleSecretName }}
{{- end }} {{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- with .Values.core.nodeSelector }} {{- end }}
nodeSelector: {{- if .Values.core.resources }}
{{ toYaml . | indent 8 }} resources:
{{- end }} {{ toYaml .Values.core.resources | indent 10 }}
{{- with .Values.core.affinity }} {{- end }}
affinity: volumes:
{{ toYaml . | indent 8 }} - name: config
{{- end }} configMap:
{{- with .Values.core.tolerations }} name: {{ template "harbor.core" . }}
tolerations: items:
{{ toYaml . | indent 8 }} - key: app.conf
{{- end }} path: app.conf
- name: secret-key
secret:
{{- if .Values.existingSecretSecretKey }}
secretName: {{ .Values.existingSecretSecretKey }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
items:
- key: secretKey
path: key
- name: token-service-private-key
secret:
{{- if .Values.core.secretName }}
secretName: {{ .Values.core.secretName }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
{{- if .Values.expose.tls.enabled }}
- name: ca-download
secret:
{{- if .Values.caSecretName }}
secretName: {{ .Values.caSecretName }}
{{- else if eq (include "harbor.autoGenCertForIngress" .) "true" }}
secretName: "{{ template "harbor.ingress" . }}"
{{- else if eq (include "harbor.autoGenCertForNginx" .) "true" }}
secretName: {{ template "harbor.tlsSecretForNginx" . }}
{{- end }}
{{- end }}
{{- if .Values.uaaSecretName }}
- name: auth-ca-cert
secret:
secretName: {{ .Values.uaaSecretName }}
items:
- key: ca.crt
path: auth-ca.crt
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: core-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.core.secretName" . }}
{{- end }}
- name: psc
emptyDir: {}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- with .Values.core.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.core.priorityClassName }}
priorityClassName: {{ .Values.core.priorityClassName }}
{{- end }}
{{- if .Values.enableMigrateHelmHook }}
apiVersion: batch/v1
kind: Job
metadata:
name: migration-job
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: migrator
annotations:
# This is what defines this resource as a hook. Without this line, the
# job is considered part of the release.
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "-5"
spec:
template:
metadata:
labels:
{{ include "harbor.matchLabels" . | indent 8 }}
component: migrator
spec:
restartPolicy: Never
securityContext:
runAsUser: 10000
fsGroup: 10000
{{- if .Values.core.serviceAccountName }}
serviceAccountName: {{ .Values.core.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
terminationGracePeriodSeconds: 120
containers:
- name: core-job
image: {{ .Values.core.image.repository }}:{{ .Values.core.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["/harbor/harbor_core", "-mode=migrate"]
envFrom:
- configMapRef:
name: "{{ template "harbor.core" . }}"
- secretRef:
name: "{{ template "harbor.core" . }}"
{{- if .Values.database.external.existingSecret }}
env:
- name: POSTGRESQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.database.external.existingSecret }}
key: password
{{- end }}
{{- if not (empty .Values.containerSecurityContext) }}
securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
{{- end }}
volumeMounts:
- name: config
mountPath: /etc/core/app.conf
subPath: app.conf
volumes:
- name: config
configMap:
name: {{ template "harbor.core" . }}
items:
- key: app.conf
path: app.conf
{{- with .Values.core.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}
apiVersion: v1 {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (include "harbor.core" .) }}
kind: Secret apiVersion: v1
metadata: kind: Secret
name: {{ template "harbor.core" . }} metadata:
labels: name: {{ template "harbor.core" . }}
{{ include "harbor.labels" . | indent 4 }} namespace: {{ .Release.Namespace | quote }}
type: Opaque labels:
data: {{ include "harbor.labels" . | indent 4 }}
secretKey: {{ .Values.secretKey | b64enc | quote }} type: Opaque
secret: {{ .Values.core.secret | default (randAlphaNum 16) | b64enc | quote }} data:
{{- if not .Values.core.secretName }} {{- if not .Values.existingSecretSecretKey }}
tls.crt: {{ .Files.Get "cert/tls.crt" | b64enc }} secretKey: {{ .Values.secretKey | b64enc | quote }}
tls.key: {{ .Files.Get "cert/tls.key" | b64enc }} {{- end }}
{{- end }} {{- if not .Values.core.existingSecret }}
HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }} secret: {{ .Values.core.secret | default (include "harbor.secretKeyHelper" (dict "key" "secret" "data" $existingSecret.data)) | default (randAlphaNum 16) | b64enc | quote }}
POSTGRESQL_PASSWORD: {{ template "harbor.database.encryptedPassword" . }} {{- end }}
REGISTRY_CREDENTIAL_PASSWORD: {{ .Values.registry.credentials.password | b64enc | quote }} {{- if not .Values.core.secretName }}
CSRF_KEY: {{ .Values.core.xsrfKey | default (randAlphaNum 32) | b64enc | quote }} {{- $ca := genCA "harbor-token-ca" 365 }}
tls.key: {{ .Values.core.tokenKey | default $ca.Key | b64enc | quote }}
tls.crt: {{ .Values.core.tokenCert | default $ca.Cert | b64enc | quote }}
{{- end }}
{{- if not .Values.existingSecretAdminPassword }}
HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }}
{{- end }}
{{- if not .Values.database.external.existingSecret }}
POSTGRESQL_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{- end }}
{{- if not .Values.registry.credentials.existingSecret }}
REGISTRY_CREDENTIAL_PASSWORD: {{ .Values.registry.credentials.password | b64enc | quote }}
{{- end }}
{{- if not .Values.core.existingXsrfSecret }}
CSRF_KEY: {{ .Values.core.xsrfKey | default (include "harbor.secretKeyHelper" (dict "key" "CSRF_KEY" "data" $existingSecret.data)) | default (randAlphaNum 32) | b64enc | quote }}
{{- end }}
{{- if .Values.core.configureUserSettings }}
CONFIG_OVERWRITE_JSON: {{ .Values.core.configureUserSettings | b64enc | quote }}
{{- end }}
{{- template "harbor.traceJaegerPassword" . }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ template "harbor.core" . }} name: {{ template "harbor.core" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
{{- if (eq .Values.expose.ingress.controller "gce") }} {{- with .Values.core.serviceAnnotations }}
type: NodePort annotations:
{{- end }} {{- toYaml . | nindent 4 }}
ports: {{- end }}
- port: {{ template "harbor.core.servicePort" . }} spec:
targetPort: {{ template "harbor.core.containerPort" . }} {{- if or (eq .Values.expose.ingress.controller "gce") (eq .Values.expose.ingress.controller "alb") (eq .Values.expose.ingress.controller "f5-bigip") }}
selector: type: NodePort
{{ include "harbor.matchLabels" . | indent 4 }} {{- end }}
component: core ports:
- name: {{ ternary "https-web" "http-web" .Values.internalTLS.enabled }}
port: {{ template "harbor.core.servicePort" . }}
targetPort: {{ template "harbor.core.containerPort" . }}
{{- if .Values.metrics.enabled}}
- name: {{ template "harbor.metricsPortName" . }}
port: {{ .Values.metrics.core.port }}
{{- end }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: core
{{- if and .Values.internalTLS.enabled }} {{- if and .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }} {{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.internalTLS.core.secretName" . }}" name: "{{ template "harbor.internalTLS.core.secretName" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: kubernetes.io/tls {{ include "harbor.labels" . | indent 4 }}
data: type: kubernetes.io/tls
ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }} data:
tls.crt: {{ (required "The \"internalTLS.core.crt\" is required!" .Values.internalTLS.core.crt) | b64enc | quote }} ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.core.key\" is required!" .Values.internalTLS.core.key) | b64enc | quote }} tls.crt: {{ (required "The \"internalTLS.core.crt\" is required!" .Values.internalTLS.core.crt) | b64enc | quote }}
{{- end }} tls.key: {{ (required "The \"internalTLS.core.key\" is required!" .Values.internalTLS.core.key) | b64enc | quote }}
{{- end }} {{- end }}
\ No newline at end of file {{- end }}
{{- if eq .Values.database.type "internal" -}} {{- if eq .Values.database.type "internal" -}}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.database" . }}" name: "{{ template "harbor.database" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: Opaque {{ include "harbor.labels" . | indent 4 }}
data: type: Opaque
POSTGRES_PASSWORD: {{ template "harbor.database.encryptedPassword" . }} data:
{{- end -}} POSTGRES_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{- end -}}
{{- if eq .Values.database.type "internal" -}} {{- if eq .Values.database.type "internal" -}}
{{- $database := .Values.persistence.persistentVolumeClaim.database -}} {{- $database := .Values.persistence.persistentVolumeClaim.database -}}
apiVersion: apps/v1 apiVersion: apps/v1
kind: StatefulSet kind: StatefulSet
metadata: metadata:
name: "{{ template "harbor.database" . }}" name: "{{ template "harbor.database" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
component: database {{ include "harbor.labels" . | indent 4 }}
spec: component: database
replicas: 1 app.kubernetes.io/component: database
serviceName: "{{ template "harbor.database" . }}" spec:
selector: replicas: 1
matchLabels: serviceName: "{{ template "harbor.database" . }}"
{{ include "harbor.matchLabels" . | indent 6 }} selector:
component: database matchLabels:
template: {{ include "harbor.matchLabels" . | indent 6 }}
metadata: component: database
labels: template:
{{ include "harbor.labels" . | indent 8 }} metadata:
component: database labels:
annotations: {{ include "harbor.labels" . | indent 8 }}
checksum/secret: {{ include (print $.Template.BasePath "/database/database-secret.yaml") . | sha256sum }} component: database
{{- if .Values.database.podAnnotations }} app.kubernetes.io/component: database
{{ toYaml .Values.database.podAnnotations | indent 8 }} {{- if .Values.database.podLabels }}
{{- end }} {{ toYaml .Values.database.podLabels | indent 8 }}
spec: {{- end }}
{{- with .Values.global.imagePullSecrets }} annotations:
imagePullSecrets: checksum/secret: {{ include (print $.Template.BasePath "/database/database-secret.yaml") . | sha256sum }}
{{- toYaml . | nindent 8 }} {{- if .Values.database.podAnnotations }}
{{- end }} {{ toYaml .Values.database.podAnnotations | indent 8 }}
{{- if .Values.database.internal.serviceAccountName }} {{- end }}
serviceAccountName: {{ .Values.database.internal.serviceAccountName }} spec:
{{- end -}} securityContext:
{{- with .Values.imagePullSecrets }} runAsUser: 999
imagePullSecrets: fsGroup: 999
{{- toYaml . | nindent 8 }} {{- if .Values.database.internal.serviceAccountName }}
{{- end }} serviceAccountName: {{ .Values.database.internal.serviceAccountName }}
initContainers: {{- end -}}
- name: "change-permission-of-directory" {{- with .Values.imagePullSecrets }}
securityContext: imagePullSecrets:
runAsUser: 0 {{- toYaml . | nindent 8 }}
{{- if contains "/" .Values.database.internal.image.repository }} {{- end }}
image: "{{ .Values.database.internal.image.repository }}" automountServiceAccountToken: {{ .Values.database.internal.automountServiceAccountToken | default false }}
{{- else }} terminationGracePeriodSeconds: 120
image: "{{ .Values.database.internal.image.hub | default .Values.global.hub }}/{{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" initContainers:
{{- end }} # with "fsGroup" set, each time a volume is mounted, Kubernetes must recursively chown() and chmod() all the files and directories inside the volume
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" # this causes the postgresql reports the "data directory /var/lib/postgresql/data/pgdata has group or world access" issue when using some CSIs e.g. Ceph
command: ["/bin/sh"] # use this init container to correct the permission
args: ["-c", "chown -R postgres:postgres /var/lib/postgresql/data"] # as "fsGroup" applied before the init container running, the container has enough permission to execute the command
volumeMounts: - name: "data-permissions-ensurer"
- name: database-data image: {{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
mountPath: /var/lib/postgresql/data imagePullPolicy: {{ .Values.imagePullPolicy }}
subPath: {{ $database.subPath }} {{- if not (empty .Values.containerSecurityContext) }}
- name: "remove-lost-found" securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
{{- if contains "/" .Values.database.internal.image.repository }} {{- end }}
image: "{{ .Values.database.internal.image.repository }}" command: ["/bin/sh"]
{{- else }} args: ["-c", "chmod -R 700 /var/lib/postgresql/data/pgdata || true"]
image: "{{ .Values.database.internal.image.hub | default .Values.global.hub }}/{{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" {{- if .Values.database.internal.initContainer.permissions.resources }}
{{- end }} resources:
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" {{ toYaml .Values.database.internal.initContainer.permissions.resources | indent 10 }}
command: ["rm", "-Rf", "/var/lib/postgresql/data/lost+found"] {{- end }}
volumeMounts: volumeMounts:
- name: database-data - name: database-data
mountPath: /var/lib/postgresql/data mountPath: /var/lib/postgresql/data
subPath: {{ $database.subPath }} subPath: {{ $database.subPath }}
containers: {{- with .Values.database.internal.extrInitContainers }}
- name: database {{- toYaml . | nindent 6 }}
{{- if contains "/" .Values.database.internal.image.repository }} {{- end }}
image: "{{ .Values.database.internal.image.repository }}" containers:
{{- else }} - name: database
image: "{{ .Values.database.internal.image.hub | default .Values.global.hub }}/{{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" image: {{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
{{- end }} imagePullPolicy: {{ .Values.imagePullPolicy }}
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" {{- if not (empty .Values.containerSecurityContext) }}
livenessProbe: securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
exec: {{- end }}
command: livenessProbe:
- /docker-healthcheck.sh exec:
initialDelaySeconds: 300 command:
periodSeconds: 10 - /docker-healthcheck.sh
readinessProbe: initialDelaySeconds: 300
exec: periodSeconds: 10
command: timeoutSeconds: {{ .Values.database.internal.livenessProbe.timeoutSeconds }}
- /docker-healthcheck.sh readinessProbe:
initialDelaySeconds: 1 exec:
periodSeconds: 10 command:
{{- if .Values.database.internal.resources }} - /docker-healthcheck.sh
resources: initialDelaySeconds: 1
{{ toYaml .Values.database.internal.resources | indent 10 }} periodSeconds: 10
{{- end }} timeoutSeconds: {{ .Values.database.internal.readinessProbe.timeoutSeconds }}
envFrom: {{- if .Values.database.internal.resources }}
- secretRef: resources:
name: "{{ template "harbor.database" . }}" {{ toYaml .Values.database.internal.resources | indent 10 }}
volumeMounts: {{- end }}
- name: database-data envFrom:
mountPath: /var/lib/postgresql/data - secretRef:
subPath: {{ $database.subPath }} name: "{{ template "harbor.database" . }}"
{{- if not .Values.persistence.enabled }} env:
volumes: # put the data into a sub directory to avoid the permission issue in k8s with restricted psp enabled
- name: "database-data" # more detail refer to https://github.com/goharbor/harbor-helm/issues/756
emptyDir: {} - name: PGDATA
{{- else if $database.existingClaim }} value: "/var/lib/postgresql/data/pgdata"
volumes: {{- with .Values.database.internal.extraEnvVars }}
- name: "database-data" {{- toYaml . | nindent 10 }}
persistentVolumeClaim: {{- end }}
claimName: {{ $database.existingClaim }} volumeMounts:
{{- end -}} - name: database-data
{{- with .Values.database.internal.nodeSelector }} mountPath: /var/lib/postgresql/data
nodeSelector: subPath: {{ $database.subPath }}
{{ toYaml . | indent 8 }} - name: shm-volume
{{- end }} mountPath: /dev/shm
{{- with .Values.database.internal.affinity }} volumes:
affinity: - name: shm-volume
{{ toYaml . | indent 8 }} emptyDir:
{{- end }} medium: Memory
{{- with .Values.database.internal.tolerations }} sizeLimit: {{ .Values.database.internal.shmSizeLimit }}
tolerations: {{- if not .Values.persistence.enabled }}
{{ toYaml . | indent 8 }} - name: "database-data"
{{- end }} emptyDir: {}
{{- if and .Values.persistence.enabled (not $database.existingClaim) }} {{- else if $database.existingClaim }}
volumeClaimTemplates: - name: "database-data"
- metadata: persistentVolumeClaim:
name: "database-data" claimName: {{ $database.existingClaim }}
labels: {{- end -}}
{{ include "harbor.labels" . | indent 8 }} {{- with .Values.database.internal.nodeSelector }}
spec: nodeSelector:
accessModes: [{{ $database.accessMode | quote }}] {{ toYaml . | indent 8 }}
{{- if $database.storageClass }} {{- end }}
{{- if (eq "-" $database.storageClass) }} {{- with .Values.database.internal.affinity }}
storageClassName: "" affinity:
{{- else }} {{ toYaml . | indent 8 }}
storageClassName: "{{ $database.storageClass }}" {{- end }}
{{- end }} {{- with .Values.database.internal.tolerations }}
{{- end }} tolerations:
resources: {{ toYaml . | indent 8 }}
requests: {{- end }}
storage: {{ $database.size | quote }} {{- if .Values.database.internal.priorityClassName }}
{{- end -}} priorityClassName: {{ .Values.database.internal.priorityClassName }}
{{- end -}} {{- end }}
{{- if and .Values.persistence.enabled (not $database.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: "database-data"
labels:
{{ include "harbor.legacy.labels" . | indent 8 }}
annotations:
{{- range $key, $value := $database.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
accessModes: [{{ $database.accessMode | quote }}]
{{- if $database.storageClass }}
{{- if (eq "-" $database.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ $database.storageClass }}"
{{- end }}
{{- end }}
resources:
requests:
storage: {{ $database.size | quote }}
{{- end -}}
{{- end -}}
{{- if eq .Values.database.type "internal" -}} {{- if eq .Values.database.type "internal" -}}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: "{{ template "harbor.database" . }}" name: "{{ template "harbor.database" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
ports: spec:
- port: 5432 ports:
selector: - port: 5432
{{ include "harbor.matchLabels" . | indent 4 }} selector:
component: database {{ include "harbor.matchLabels" . | indent 4 }}
{{- end -}} component: database
\ No newline at end of file {{- end -}}
{{- if .Values.metrics.enabled}}
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.exporter" . }}-env"
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
{{- if has "jobservice" .Values.proxy.components }}
HTTP_PROXY: "{{ .Values.proxy.httpProxy }}"
HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}"
NO_PROXY: "{{ template "harbor.noProxy" . }}"
{{- end }}
LOG_LEVEL: "{{ .Values.logLevel }}"
HARBOR_EXPORTER_PORT: "{{ .Values.metrics.exporter.port }}"
HARBOR_EXPORTER_METRICS_PATH: "{{ .Values.metrics.exporter.path }}"
HARBOR_EXPORTER_METRICS_ENABLED: "{{ .Values.metrics.enabled }}"
HARBOR_EXPORTER_CACHE_TIME: "{{ .Values.exporter.cacheDuration }}"
HARBOR_EXPORTER_CACHE_CLEAN_INTERVAL: "{{ .Values.exporter.cacheCleanInterval }}"
HARBOR_METRIC_NAMESPACE: harbor
HARBOR_METRIC_SUBSYSTEM: exporter
HARBOR_REDIS_URL: "{{ template "harbor.redis.urlForJobservice" . }}"
HARBOR_REDIS_NAMESPACE: harbor_job_service_namespace
HARBOR_REDIS_TIMEOUT: "3600"
HARBOR_SERVICE_SCHEME: "{{ template "harbor.component.scheme" . }}"
HARBOR_SERVICE_HOST: "{{ template "harbor.core" . }}"
HARBOR_SERVICE_PORT: "{{ template "harbor.core.servicePort" . }}"
HARBOR_DATABASE_HOST: "{{ template "harbor.database.host" . }}"
HARBOR_DATABASE_PORT: "{{ template "harbor.database.port" . }}"
HARBOR_DATABASE_USERNAME: "{{ template "harbor.database.username" . }}"
HARBOR_DATABASE_DBNAME: "{{ template "harbor.database.coreDatabase" . }}"
HARBOR_DATABASE_SSLMODE: "{{ template "harbor.database.sslmode" . }}"
HARBOR_DATABASE_MAX_IDLE_CONNS: "{{ .Values.database.maxIdleConns }}"
HARBOR_DATABASE_MAX_OPEN_CONNS: "{{ .Values.database.maxOpenConns }}"
{{- end}}
{{- if .Values.metrics.enabled}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.exporter" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: exporter
app.kubernetes.io/component: exporter
spec:
replicas: {{ .Values.exporter.replicas }}
revisionHistoryLimit: {{ .Values.exporter.revisionHistoryLimit }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: exporter
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: exporter
app.kubernetes.io/component: exporter
{{- if .Values.exporter.podLabels }}
{{ toYaml .Values.exporter.podLabels | indent 8 }}
{{- end }}
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/exporter/exporter-cm-env.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/exporter/exporter-secret.yaml") . | sha256sum }}
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
checksum/tls: {{ include (print $.Template.BasePath "/core/core-tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.exporter.podAnnotations }}
{{ toYaml .Values.exporter.podAnnotations | indent 8 }}
{{- end }}
spec:
securityContext:
runAsUser: 10000
fsGroup: 10000
{{- if .Values.exporter.serviceAccountName }}
serviceAccountName: {{ .Values.exporter.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
automountServiceAccountToken: {{ .Values.exporter.automountServiceAccountToken | default false }}
{{- with .Values.exporter.topologySpreadConstraints }}
topologySpreadConstraints:
{{- range . }}
- {{ . | toYaml | indent 8 | trim }}
labelSelector:
matchLabels:
{{ include "harbor.matchLabels" $ | indent 12 }}
component: exporter
{{- end }}
{{- end }}
containers:
- name: exporter
image: {{ .Values.exporter.image.repository }}:{{ .Values.exporter.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /
port: {{ .Values.metrics.exporter.port }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: {{ .Values.metrics.exporter.port }}
initialDelaySeconds: 30
periodSeconds: 10
args: ["-log-level", "{{ .Values.logLevel }}"]
envFrom:
- configMapRef:
name: "{{ template "harbor.exporter" . }}-env"
- secretRef:
name: "{{ template "harbor.exporter" . }}"
env:
{{- if .Values.database.external.existingSecret }}
- name: HARBOR_DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.database.external.existingSecret }}
key: password
{{- end }}
{{- if .Values.existingSecretAdminPassword }}
- name: HARBOR_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.existingSecretAdminPassword }}
key: {{ .Values.existingSecretAdminPasswordKey }}
{{- end }}
{{- if .Values.exporter.resources }}
resources:
{{ toYaml .Values.exporter.resources | indent 10 }}
{{- end }}
{{- with .Values.exporter.extraEnvVars }}
env:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- if not (empty .Values.containerSecurityContext) }}
securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
{{- end }}
ports:
- containerPort: {{ .Values.metrics.exporter.port }}
volumeMounts:
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: core-internal-certs
mountPath: /etc/harbor/ssl/core
# There are some metric data are collectd from harbor core.
# When internal TLS is enabled, the Exporter need the CA file to collect these data.
{{- end }}
volumes:
- name: config
secret:
secretName: "{{ template "harbor.exporter" . }}"
{{- if .Values.internalTLS.enabled }}
- name: core-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.core.secretName" . }}
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- with .Values.exporter.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.exporter.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.exporter.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.exporter.priorityClassName }}
priorityClassName: {{ .Values.exporter.priorityClassName }}
{{- end }}
{{ end }}
{{- if .Values.metrics.enabled}}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "harbor.exporter" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
{{- if not .Values.existingSecretAdminPassword }}
HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }}
{{- end }}
{{- if not .Values.database.external.existingSecret }}
HARBOR_DATABASE_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{- end }}
{{- end }}
{{ if .Values.clair.enabled }} {{- if .Values.metrics.enabled}}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: "{{ template "harbor.clair" . }}" name: "{{ template "harbor.exporter" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
ports: spec:
- name: adapter ports:
port: {{ include "harbor.clairAdapter.servicePort" . }} - name: {{ template "harbor.metricsPortName" . }}
selector: port: {{ .Values.metrics.exporter.port }}
{{ include "harbor.matchLabels" . | indent 4 }} selector:
component: clair {{ include "harbor.matchLabels" . | indent 4 }}
{{ end }} component: exporter
{{ end }}
{{- if eq .Values.expose.type "ingress" }} {{- if eq .Values.expose.type "ingress" }}
{{- $ingress := .Values.expose.ingress -}} {{- $ingress := .Values.expose.ingress -}}
{{- $tls := .Values.expose.tls -}} {{- $tls := .Values.expose.tls -}}
{{- if eq .Values.expose.ingress.controller "gce" }} {{- if eq .Values.expose.ingress.controller "gce" }}
{{- $_ := set . "portal_path" "/*" -}} {{- $_ := set . "path_type" "ImplementationSpecific" -}}
{{- $_ := set . "api_path" "/api/*" -}} {{- $_ := set . "portal_path" "/*" -}}
{{- $_ := set . "service_path" "/service/*" -}} {{- $_ := set . "api_path" "/api/*" -}}
{{- $_ := set . "v2_path" "/v2/*" -}} {{- $_ := set . "service_path" "/service/*" -}}
{{- $_ := set . "chartrepo_path" "/chartrepo/*" -}} {{- $_ := set . "v2_path" "/v2/*" -}}
{{- $_ := set . "controller_path" "/c/*" -}} {{- $_ := set . "controller_path" "/c/*" -}}
{{- $_ := set . "notary_path" "/" -}} {{- else if eq .Values.expose.ingress.controller "ncp" }}
{{- else if eq .Values.expose.ingress.controller "ncp" }} {{- $_ := set . "path_type" "Prefix" -}}
{{- $_ := set . "portal_path" "/.*" -}} {{- $_ := set . "portal_path" "/.*" -}}
{{- $_ := set . "api_path" "/api/.*" -}} {{- $_ := set . "api_path" "/api/.*" -}}
{{- $_ := set . "service_path" "/service/.*" -}} {{- $_ := set . "service_path" "/service/.*" -}}
{{- $_ := set . "v2_path" "/v2/.*" -}} {{- $_ := set . "v2_path" "/v2/.*" -}}
{{- $_ := set . "chartrepo_path" "/chartrepo/.*" -}} {{- $_ := set . "controller_path" "/c/.*" -}}
{{- $_ := set . "controller_path" "/c/.*" -}} {{- else }}
{{- $_ := set . "notary_path" "/.*" -}} {{- $_ := set . "path_type" "Prefix" -}}
{{- else }} {{- $_ := set . "portal_path" "/" -}}
{{- $_ := set . "portal_path" "/" -}} {{- $_ := set . "api_path" "/api/" -}}
{{- $_ := set . "api_path" "/api" -}} {{- $_ := set . "service_path" "/service/" -}}
{{- $_ := set . "service_path" "/service" -}} {{- $_ := set . "v2_path" "/v2/" -}}
{{- $_ := set . "v2_path" "/v2" -}} {{- $_ := set . "controller_path" "/c/" -}}
{{- $_ := set . "chartrepo_path" "/chartrepo" -}} {{- end }}
{{- $_ := set . "controller_path" "/c" -}}
{{- $_ := set . "notary_path" "/" -}} ---
{{- end }} {{- if semverCompare "<1.14-0" (include "harbor.ingress.kubeVersion" .) }}
apiVersion: extensions/v1beta1
--- {{- else if semverCompare "<1.19-0" (include "harbor.ingress.kubeVersion" .) }}
{{- if not (.Capabilities.APIVersions.Has "bcc.bd-apaas.com/v1alpha1") -}} apiVersion: networking.k8s.io/v1beta1
{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion }} {{- else }}
apiVersion: extensions/v1beta1 apiVersion: networking.k8s.io/v1
{{- else }} {{- end }}
apiVersion: networking.k8s.io/v1beta1 kind: Ingress
{{- end }} metadata:
kind: Ingress name: "{{ template "harbor.ingress" . }}"
metadata: namespace: {{ .Release.Namespace | quote }}
name: "{{ template "harbor.ingress" . }}" labels:
labels: {{ include "harbor.labels" . | indent 4 }}
{{ include "harbor.labels" . | indent 4 }} {{- if $ingress.labels }}
annotations: {{ toYaml $ingress.labels | indent 4 }}
{{ toYaml $ingress.annotations | indent 4 }} {{- end }}
{{- if .Values.internalTLS.enabled }} annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" {{ toYaml $ingress.annotations | indent 4 }}
{{- end }} {{- if .Values.internalTLS.enabled }}
{{- if eq .Values.expose.ingress.controller "ncp" }} nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
ncp/use-regex: "true" {{- end }}
{{- if $tls.enabled }} {{- if eq .Values.expose.ingress.controller "ncp" }}
ncp/http-redirect: "true" ncp/use-regex: "true"
{{- end }} {{- if $tls.enabled }}
{{- end }} ncp/http-redirect: "true"
spec: {{- end }}
{{- if $tls.enabled }} {{- end }}
tls: spec:
- secretName: {{ template "harbor.tlsCoreSecretForIngress" . }} {{- if $ingress.className }}
{{- if $ingress.hosts.core }} ingressClassName: {{ $ingress.className }}
hosts: {{- end }}
- {{ $ingress.hosts.core }}.{{ $.Values.global.host }} {{- if $tls.enabled }}
{{- end }} tls:
{{- end }} - secretName: {{ template "harbor.tlsCoreSecretForIngress" . }}
rules: {{- if $ingress.hosts.core }}
- http: hosts:
paths: - {{ $ingress.hosts.core }}
- path: {{ .portal_path }} {{- end }}
backend: {{- end }}
serviceName: {{ template "harbor.portal" . }} rules:
servicePort: {{ template "harbor.portal.servicePort" . }} - http:
- path: {{ .api_path }} paths:
backend: {{- if semverCompare "<1.19-0" (include "harbor.ingress.kubeVersion" .) }}
serviceName: {{ template "harbor.core" . }} - path: {{ .api_path }}
servicePort: {{ template "harbor.core.servicePort" . }} backend:
- path: {{ .service_path }} serviceName: {{ template "harbor.core" . }}
backend: servicePort: {{ template "harbor.core.servicePort" . }}
serviceName: {{ template "harbor.core" . }} - path: {{ .service_path }}
servicePort: {{ template "harbor.core.servicePort" . }} backend:
- path: {{ .v2_path }} serviceName: {{ template "harbor.core" . }}
backend: servicePort: {{ template "harbor.core.servicePort" . }}
serviceName: {{ template "harbor.core" . }} - path: {{ .v2_path }}
servicePort: {{ template "harbor.core.servicePort" . }} backend:
- path: {{ .chartrepo_path }} serviceName: {{ template "harbor.core" . }}
backend: servicePort: {{ template "harbor.core.servicePort" . }}
serviceName: {{ template "harbor.core" . }} - path: {{ .controller_path }}
servicePort: {{ template "harbor.core.servicePort" . }} backend:
- path: {{ .controller_path }} serviceName: {{ template "harbor.core" . }}
backend: servicePort: {{ template "harbor.core.servicePort" . }}
serviceName: {{ template "harbor.core" . }} - path: {{ .portal_path }}
servicePort: {{ template "harbor.core.servicePort" . }} backend:
{{- if $ingress.hosts.core }} serviceName: {{ template "harbor.portal" . }}
host: {{ $ingress.hosts.core }}.{{ $.Values.global.host }} servicePort: {{ template "harbor.portal.servicePort" . }}
{{- end }} {{- else }}
- path: {{ .api_path }}
{{- if .Values.notary.enabled }} pathType: {{ .path_type }}
--- backend:
{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion }} service:
apiVersion: extensions/v1beta1 name: {{ template "harbor.core" . }}
{{- else }} port:
apiVersion: networking.k8s.io/v1beta1 number: {{ template "harbor.core.servicePort" . }}
{{- end }} - path: {{ .service_path }}
kind: Ingress pathType: {{ .path_type }}
metadata: backend:
name: "{{ template "harbor.ingress-notary" . }}" service:
labels: name: {{ template "harbor.core" . }}
{{ include "harbor.labels" . | indent 4 }} port:
annotations: number: {{ template "harbor.core.servicePort" . }}
{{ toYaml $ingress.annotations | indent 4 }} - path: {{ .v2_path }}
{{- if eq .Values.expose.ingress.controller "ncp" }} pathType: {{ .path_type }}
ncp/use-regex: "true" backend:
{{- if $tls.enabled }} service:
ncp/http-redirect: "true" name: {{ template "harbor.core" . }}
{{- end }} port:
{{- end }} number: {{ template "harbor.core.servicePort" . }}
spec: - path: {{ .controller_path }}
{{- if $tls.enabled }} pathType: {{ .path_type }}
tls: backend:
- secretName: {{ template "harbor.tlsNotarySecretForIngress" . }} service:
{{- if $ingress.hosts.notary }} name: {{ template "harbor.core" . }}
hosts: port:
- {{ $ingress.hosts.notary }}.{{ $.Values.global.host }} number: {{ template "harbor.core.servicePort" . }}
{{- end }} - path: {{ .portal_path }}
{{- end }} pathType: {{ .path_type }}
rules: backend:
- http: service:
paths: name: {{ template "harbor.portal" . }}
- path: {{ .notary_path }} port:
backend: number: {{ template "harbor.portal.servicePort" . }}
serviceName: {{ template "harbor.notary-server" . }} {{- end }}
servicePort: 4443 {{- if $ingress.hosts.core }}
{{- if $ingress.hosts.notary }} host: {{ $ingress.hosts.core }}
host: {{ $ingress.hosts.notary }}.{{ $.Values.global.host }} {{- end }}
{{- end }}
{{- end }} {{- end }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- if eq (include "harbor.autoGenCertForIngress" .) "true" }} {{- if eq (include "harbor.autoGenCertForIngress" .) "true" }}
{{- $ca := genCA "harbor-ca" 365 }} {{- $ca := genCA "harbor-ca" 365 }}
{{- $cert := genSignedCert .Values.expose.ingress.hosts.core nil (list .Values.expose.ingress.hosts.core .Values.expose.ingress.hosts.notary) 365 $ca }} {{- $cert := genSignedCert .Values.expose.ingress.hosts.core nil (list .Values.expose.ingress.hosts.core) 365 $ca }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.ingress" . }}" name: "{{ template "harbor.ingress" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: kubernetes.io/tls {{ include "harbor.labels" . | indent 4 }}
data: type: kubernetes.io/tls
tls.crt: {{ $cert.Cert | b64enc | quote }} data:
tls.key: {{ $cert.Key | b64enc | quote }} tls.crt: {{ $cert.Cert | b64enc | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }} tls.key: {{ $cert.Key | b64enc | quote }}
{{- end }} ca.crt: {{ $ca.Cert | b64enc | quote }}
\ No newline at end of file {{- end }}
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }} {{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
{{- $ca := genCA "harbor-internal-ca" 365 }} {{- $ca := genCA "harbor-internal-ca" 365 }}
{{- $coreCN := (include "harbor.core" .) }} {{- $coreCN := (include "harbor.core" .) }}
{{- $coreCrt := genSignedCert $coreCN (list "127.0.0.1") (list "localhost" $coreCN) 365 $ca }} {{- $coreCrt := genSignedCert $coreCN (list "127.0.0.1") (list "localhost" $coreCN) 365 $ca }}
{{- $jsCN := (include "harbor.jobservice" .) }} {{- $jsCN := (include "harbor.jobservice" .) }}
{{- $jsCrt := genSignedCert $jsCN nil (list $jsCN) 365 $ca }} {{- $jsCrt := genSignedCert $jsCN nil (list $jsCN) 365 $ca }}
{{- $regCN := (include "harbor.registry" .) }} {{- $regCN := (include "harbor.registry" .) }}
{{- $regCrt := genSignedCert $regCN nil (list $regCN) 365 $ca }} {{- $regCrt := genSignedCert $regCN nil (list $regCN) 365 $ca }}
{{- $portalCN := (include "harbor.portal" .) }} {{- $portalCN := (include "harbor.portal" .) }}
{{- $portalCrt := genSignedCert $portalCN nil (list $portalCN) 365 $ca }} {{- $portalCrt := genSignedCert $portalCN nil (list $portalCN) 365 $ca }}
--- ---
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.internalTLS.core.secretName" . }}" name: "{{ template "harbor.internalTLS.core.secretName" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: kubernetes.io/tls {{ include "harbor.labels" . | indent 4 }}
data: type: kubernetes.io/tls
ca.crt: {{ $ca.Cert | b64enc | quote }} data:
tls.crt: {{ $coreCrt.Cert | b64enc | quote }} ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.key: {{ $coreCrt.Key | b64enc | quote }} tls.crt: {{ $coreCrt.Cert | b64enc | quote }}
tls.key: {{ $coreCrt.Key | b64enc | quote }}
---
apiVersion: v1 ---
kind: Secret apiVersion: v1
metadata: kind: Secret
name: "{{ template "harbor.internalTLS.jobservice.secretName" . }}" metadata:
labels: name: "{{ template "harbor.internalTLS.jobservice.secretName" . }}"
{{ include "harbor.labels" . | indent 4 }} namespace: {{ .Release.Namespace | quote }}
type: kubernetes.io/tls labels:
data: {{ include "harbor.labels" . | indent 4 }}
ca.crt: {{ $ca.Cert | b64enc | quote }} type: kubernetes.io/tls
tls.crt: {{ $jsCrt.Cert | b64enc | quote }} data:
tls.key: {{ $jsCrt.Key | b64enc | quote }} ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $jsCrt.Cert | b64enc | quote }}
--- tls.key: {{ $jsCrt.Key | b64enc | quote }}
apiVersion: v1
kind: Secret ---
metadata: apiVersion: v1
name: "{{ template "harbor.internalTLS.registry.secretName" . }}" kind: Secret
labels: metadata:
{{ include "harbor.labels" . | indent 4 }} name: "{{ template "harbor.internalTLS.registry.secretName" . }}"
type: kubernetes.io/tls namespace: {{ .Release.Namespace | quote }}
data: labels:
ca.crt: {{ $ca.Cert | b64enc | quote }} {{ include "harbor.labels" . | indent 4 }}
tls.crt: {{ $regCrt.Cert | b64enc | quote }} type: kubernetes.io/tls
tls.key: {{ $regCrt.Key | b64enc | quote }} data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
--- tls.crt: {{ $regCrt.Cert | b64enc | quote }}
apiVersion: v1 tls.key: {{ $regCrt.Key | b64enc | quote }}
kind: Secret
metadata: ---
name: "{{ template "harbor.internalTLS.portal.secretName" . }}" apiVersion: v1
labels: kind: Secret
{{ include "harbor.labels" . | indent 4 }} metadata:
type: kubernetes.io/tls name: "{{ template "harbor.internalTLS.portal.secretName" . }}"
data: namespace: {{ .Release.Namespace | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }} labels:
tls.crt: {{ $portalCrt.Cert | b64enc | quote }} {{ include "harbor.labels" . | indent 4 }}
tls.key: {{ $portalCrt.Key | b64enc | quote }} type: kubernetes.io/tls
data:
{{- if .Values.chartmuseum.enabled }} ca.crt: {{ $ca.Cert | b64enc | quote }}
--- tls.crt: {{ $portalCrt.Cert | b64enc | quote }}
{{- $chartCN := (include "harbor.chartmuseum" .) }} tls.key: {{ $portalCrt.Key | b64enc | quote }}
{{- $chartCrt := genSignedCert $chartCN nil (list $chartCN) 365 $ca }}
apiVersion: v1 {{- if and .Values.trivy.enabled}}
kind: Secret ---
metadata: {{- $trivyCN := (include "harbor.trivy" .) }}
name: "{{ template "harbor.internalTLS.chartmuseum.secretName" . }}" {{- $trivyCrt := genSignedCert $trivyCN nil (list $trivyCN) 365 $ca }}
labels: apiVersion: v1
{{ include "harbor.labels" . | indent 4 }} kind: Secret
type: kubernetes.io/tls metadata:
data: name: "{{ template "harbor.internalTLS.trivy.secretName" . }}"
ca.crt: {{ $ca.Cert | b64enc | quote }} namespace: {{ .Release.Namespace | quote }}
tls.crt: {{ $chartCrt.Cert | b64enc | quote }} labels:
tls.key: {{ $chartCrt.Key | b64enc | quote }} {{ include "harbor.labels" . | indent 4 }}
{{- end }} type: kubernetes.io/tls
data:
{{- if .Values.clair.enabled }} ca.crt: {{ $ca.Cert | b64enc | quote }}
--- tls.crt: {{ $trivyCrt.Cert | b64enc | quote }}
{{- $clairCN := (include "harbor.clair" .) }} tls.key: {{ $trivyCrt.Key | b64enc | quote }}
{{- $clairCrt := genSignedCert $clairCN nil (list $clairCN) 365 $ca }} {{- end }}
apiVersion: v1
kind: Secret {{- end }}
metadata:
name: "{{ template "harbor.internalTLS.clair.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $clairCrt.Cert | b64enc | quote }}
tls.key: {{ $clairCrt.Key | b64enc | quote }}
{{- end }}
{{- if and .Values.trivy.enabled}}
---
{{- $trivyCN := (include "harbor.trivy" .) }}
{{- $trivyCrt := genSignedCert $trivyCN nil (list $trivyCN) 365 $ca }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.trivy.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $trivyCrt.Cert | b64enc | quote }}
tls.key: {{ $trivyCrt.Key | b64enc | quote }}
{{- end }}
{{- end }}
\ No newline at end of file
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: "{{ template "harbor.jobservice" . }}-env" name: "{{ template "harbor.jobservice" . }}-env"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
data: {{ include "harbor.labels" . | indent 4 }}
CORE_URL: "{{ template "harbor.coreURL" . }}" data:
TOKEN_SERVICE_URL: "{{ template "harbor.tokenServiceURL" . }}" CORE_URL: "{{ template "harbor.coreURL" . }}"
REGISTRY_URL: "{{ template "harbor.registryURL" . }}" TOKEN_SERVICE_URL: "{{ template "harbor.tokenServiceURL" . }}"
REGISTRY_CONTROLLER_URL: "{{ template "harbor.registryControllerURL" . }}" REGISTRY_URL: "{{ template "harbor.registryURL" . }}"
REGISTRY_CREDENTIAL_USERNAME: "{{ .Values.registry.credentials.username }}" REGISTRY_CONTROLLER_URL: "{{ template "harbor.registryControllerURL" . }}"
{{- if has "jobservice" .Values.proxy.components }} REGISTRY_CREDENTIAL_USERNAME: "{{ .Values.registry.credentials.username }}"
HTTP_PROXY: "{{ .Values.proxy.httpProxy }}"
HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}" JOBSERVICE_WEBHOOK_JOB_MAX_RETRY: "{{ .Values.jobservice.notification.webhook_job_max_retry }}"
NO_PROXY: "{{ template "harbor.noProxy" . }}" JOBSERVICE_WEBHOOK_JOB_HTTP_CLIENT_TIMEOUT: "{{ .Values.jobservice.notification.webhook_job_http_client_timeout }}"
{{- end }}
LOG_LEVEL: "{{ .Values.logLevel }}"
{{- if has "jobservice" .Values.proxy.components }}
HTTP_PROXY: "{{ .Values.proxy.httpProxy }}"
HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}"
NO_PROXY: "{{ template "harbor.noProxy" . }}"
{{- end }}
{{- if .Values.metrics.enabled}}
METRIC_NAMESPACE: harbor
METRIC_SUBSYSTEM: jobservice
{{- end }}
{{- template "harbor.traceEnvsForJobservice" . }}
{{- if .Values.cache.enabled }}
_REDIS_URL_CORE: "{{ template "harbor.redis.urlForCore" . }}"
CACHE_ENABLED: "true"
CACHE_EXPIRE_HOURS: "{{ .Values.cache.expireHours }}"
{{- end }}
{{- if or (and (eq .Values.redis.type "internal") .Values.redis.internal.cacheLayerDatabaseIndex) (and (eq .Values.redis.type "external") .Values.redis.external.cacheLayerDatabaseIndex) }}
_REDIS_URL_CACHE_LAYER: "{{ template "harbor.redis.urlForCache" . }}"
{{- end }}
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: "{{ template "harbor.jobservice" . }}" name: "{{ template "harbor.jobservice" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
data: {{ include "harbor.labels" . | indent 4 }}
config.yml: |+ data:
#Server listening port config.yml: |+
protocol: "{{ template "harbor.component.scheme" . }}" #Server listening port
port: {{ template "harbor.jobservice.containerPort". }} protocol: "{{ template "harbor.component.scheme" . }}"
{{- if .Values.internalTLS.enabled }} port: {{ template "harbor.jobservice.containerPort". }}
https_config: {{- if .Values.internalTLS.enabled }}
cert: "/etc/harbor/ssl/jobservice/tls.crt" https_config:
key: "/etc/harbor/ssl/jobservice/tls.key" cert: "/etc/harbor/ssl/jobservice/tls.crt"
{{- end }} key: "/etc/harbor/ssl/jobservice/tls.key"
worker_pool: {{- end }}
workers: {{ .Values.jobservice.maxJobWorkers }} worker_pool:
backend: "redis" workers: {{ .Values.jobservice.maxJobWorkers }}
redis_pool: backend: "redis"
redis_url: "{{ template "harbor.redis.urlForJobservice" . }}" redis_pool:
namespace: "harbor_job_service_namespace" redis_url: "{{ template "harbor.redis.urlForJobservice" . }}"
idle_timeout_second: 3600 namespace: "harbor_job_service_namespace"
job_loggers: idle_timeout_second: 3600
{{- if eq .Values.jobservice.jobLogger "file" }} job_loggers:
- name: "FILE" {{- if has "file" .Values.jobservice.jobLoggers }}
level: {{ .Values.logLevel | upper }} - name: "FILE"
settings: # Customized settings of logger level: {{ .Values.logLevel | upper }}
base_dir: "/var/log/jobs" settings: # Customized settings of logger
sweeper: base_dir: "/var/log/jobs"
duration: 14 #days sweeper:
settings: # Customized settings of sweeper duration: {{ .Values.jobservice.loggerSweeperDuration }} #days
work_dir: "/var/log/jobs" settings: # Customized settings of sweeper
{{- else if eq .Values.jobservice.jobLogger "database" }} work_dir: "/var/log/jobs"
- name: "DB" {{- end }}
level: {{ .Values.logLevel | upper }} {{- if has "database" .Values.jobservice.jobLoggers }}
sweeper: - name: "DB"
duration: 14 #days level: {{ .Values.logLevel | upper }}
{{- else }} sweeper:
- name: "STD_OUTPUT" duration: {{ .Values.jobservice.loggerSweeperDuration }} #days
level: {{ .Values.logLevel | upper }} {{- end }}
{{- end }} {{- if has "stdout" .Values.jobservice.jobLoggers }}
#Loggers for the job service - name: "STD_OUTPUT"
loggers: level: {{ .Values.logLevel | upper }}
- name: "STD_OUTPUT" {{- end }}
level: {{ .Values.logLevel | upper }} metric:
\ No newline at end of file enabled: {{ .Values.metrics.enabled }}
path: {{ .Values.metrics.jobservice.path }}
port: {{ .Values.metrics.jobservice.port }}
#Loggers for the job service
loggers:
- name: "STD_OUTPUT"
level: {{ .Values.logLevel | upper }}
reaper:
# the max time to wait for a task to finish, if unfinished after max_update_hours, the task will be mark as error, but the task will continue to run, default value is 24
max_update_hours: {{ .Values.jobservice.reaper.max_update_hours }}
# the max time for execution in running state without new task created
max_dangling_hours: {{ .Values.jobservice.reaper.max_dangling_hours }}
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: "{{ template "harbor.jobservice" . }}" name: "{{ template "harbor.jobservice" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
component: jobservice {{ include "harbor.labels" . | indent 4 }}
spec: component: jobservice
replicas: {{ .Values.jobservice.replicas }} app.kubernetes.io/component: jobservice
strategy: spec:
type: {{ .Values.updateStrategy.type }} replicas: {{ .Values.jobservice.replicas }}
{{- if eq .Values.updateStrategy.type "Recreate" }} revisionHistoryLimit: {{ .Values.jobservice.revisionHistoryLimit }}
rollingUpdate: null strategy:
{{- end }} type: {{ .Values.updateStrategy.type }}
selector: {{- if eq .Values.updateStrategy.type "Recreate" }}
matchLabels: rollingUpdate: null
{{ include "harbor.matchLabels" . | indent 6 }} {{- end }}
component: jobservice selector:
template: matchLabels:
metadata: {{ include "harbor.matchLabels" . | indent 6 }}
labels: component: jobservice
{{ include "harbor.labels" . | indent 8 }} template:
component: jobservice metadata:
annotations: labels:
checksum/configmap: {{ include (print $.Template.BasePath "/jobservice/jobservice-cm.yaml") . | sha256sum }} {{ include "harbor.labels" . | indent 8 }}
checksum/configmap-env: {{ include (print $.Template.BasePath "/jobservice/jobservice-cm-env.yaml") . | sha256sum }} component: jobservice
checksum/secret: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }} app.kubernetes.io/component: jobservice
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }} {{- if .Values.jobservice.podLabels }}
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }} {{ toYaml .Values.jobservice.podLabels | indent 8 }}
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }} {{- end }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }} annotations:
checksum/tls: {{ include (print $.Template.BasePath "/jobservice/jobservice-tls.yaml") . | sha256sum }} checksum/configmap: {{ include (print $.Template.BasePath "/jobservice/jobservice-cm.yaml") . | sha256sum }}
{{- end }} checksum/configmap-env: {{ include (print $.Template.BasePath "/jobservice/jobservice-cm-env.yaml") . | sha256sum }}
{{- if .Values.jobservice.podAnnotations }} checksum/secret: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
{{ toYaml .Values.jobservice.podAnnotations | indent 8 }} checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- end }} {{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
spec: checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- with .Values.global.imagePullSecrets }} {{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
imagePullSecrets: checksum/tls: {{ include (print $.Template.BasePath "/jobservice/jobservice-tls.yaml") . | sha256sum }}
{{- toYaml . | nindent 8 }} {{- end }}
{{- end }} {{- if .Values.jobservice.podAnnotations }}
securityContext: {{ toYaml .Values.jobservice.podAnnotations | indent 8 }}
fsGroup: 10000 {{- end }}
{{- if .Values.jobservice.serviceAccountName }} spec:
serviceAccountName: {{ .Values.jobservice.serviceAccountName }} securityContext:
{{- end -}} runAsUser: 10000
{{- with .Values.imagePullSecrets }} fsGroup: 10000
imagePullSecrets: {{- if .Values.jobservice.serviceAccountName }}
{{- toYaml . | nindent 8 }} serviceAccountName: {{ .Values.jobservice.serviceAccountName }}
{{- end }} {{- end -}}
containers: {{- with .Values.imagePullSecrets }}
- name: jobservice imagePullSecrets:
{{- if contains "/" .Values.jobservice.image.repository }} {{- toYaml . | nindent 8 }}
image: "{{ .Values.jobservice.image.repository }}" {{- end }}
{{- else }} automountServiceAccountToken: {{ .Values.jobservice.automountServiceAccountToken | default false }}
image: "{{ .Values.jobservice.image.hub | default .Values.global.hub }}/{{ .Values.jobservice.image.repository }}:{{ .Values.jobservice.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" terminationGracePeriodSeconds: 120
{{- end }} {{- with .Values.jobservice.topologySpreadConstraints}}
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" topologySpreadConstraints:
livenessProbe: {{- range . }}
httpGet: - {{ . | toYaml | indent 8 | trim }}
path: /api/v1/stats labelSelector:
scheme: {{ include "harbor.component.scheme" . | upper }} matchLabels:
port: {{ template "harbor.jobservice.containerPort" . }} {{ include "harbor.matchLabels" $ | indent 12 }}
initialDelaySeconds: 300 component: jobservice
periodSeconds: 10 {{- end }}
readinessProbe: {{- end }}
httpGet: {{- with .Values.jobservice.initContainers }}
path: /api/v1/stats initContainers:
scheme: {{ include "harbor.component.scheme" . | upper }} {{- toYaml . | nindent 8 }}
port: {{ template "harbor.jobservice.containerPort" . }} {{- end }}
initialDelaySeconds: 20 containers:
periodSeconds: 10 - name: jobservice
{{- if .Values.jobservice.resources }} image: {{ .Values.jobservice.image.repository }}:{{ .Values.jobservice.image.tag }}
resources: imagePullPolicy: {{ .Values.imagePullPolicy }}
{{ toYaml .Values.jobservice.resources | indent 10 }} livenessProbe:
{{- end }} httpGet:
env: path: /api/v1/stats
- name: CORE_SECRET scheme: {{ include "harbor.component.scheme" . | upper }}
valueFrom: port: {{ template "harbor.jobservice.containerPort" . }}
secretKeyRef: initialDelaySeconds: 300
name: {{ template "harbor.core" . }} periodSeconds: 10
key: secret readinessProbe:
{{- if .Values.internalTLS.enabled }} httpGet:
- name: INTERNAL_TLS_ENABLED path: /api/v1/stats
value: "true" scheme: {{ include "harbor.component.scheme" . | upper }}
- name: INTERNAL_TLS_KEY_PATH port: {{ template "harbor.jobservice.containerPort" . }}
value: /etc/harbor/ssl/jobservice/tls.key initialDelaySeconds: 20
- name: INTERNAL_TLS_CERT_PATH periodSeconds: 10
value: /etc/harbor/ssl/jobservice/tls.crt {{- if .Values.jobservice.resources }}
- name: INTERNAL_TLS_TRUST_CA_PATH resources:
value: /etc/harbor/ssl/jobservice/ca.crt {{ toYaml .Values.jobservice.resources | indent 10 }}
{{- end }} {{- end }}
envFrom: env:
- configMapRef: - name: CORE_SECRET
name: "{{ template "harbor.jobservice" . }}-env" valueFrom:
- secretRef: secretKeyRef:
name: "{{ template "harbor.jobservice" . }}" name: {{ default (include "harbor.core" .) .Values.core.existingSecret }}
ports: key: secret
- containerPort: {{ template "harbor.jobservice.containerPort" . }} {{- if .Values.jobservice.existingSecret }}
volumeMounts: - name: JOBSERVICE_SECRET
- name: jobservice-config valueFrom:
mountPath: /etc/jobservice/config.yml secretKeyRef:
subPath: config.yml name: {{ .Values.jobservice.existingSecret }}
- name: job-logs key: {{ .Values.jobservice.existingSecretKey }}
mountPath: /var/log/jobs {{- end }}
subPath: {{ .Values.persistence.persistentVolumeClaim.jobservice.subPath }} {{- if .Values.internalTLS.enabled }}
{{- if .Values.internalTLS.enabled }} - name: INTERNAL_TLS_ENABLED
- name: jobservice-internal-certs value: "true"
mountPath: /etc/harbor/ssl/jobservice - name: INTERNAL_TLS_KEY_PATH
{{- end }} value: /etc/harbor/ssl/jobservice/tls.key
{{- if .Values.caBundleSecretName }} - name: INTERNAL_TLS_CERT_PATH
{{ include "harbor.caBundleVolumeMount" . | indent 8 }} value: /etc/harbor/ssl/jobservice/tls.crt
{{- end }} - name: INTERNAL_TLS_TRUST_CA_PATH
volumes: value: /etc/harbor/ssl/jobservice/ca.crt
- name: jobservice-config {{- end }}
configMap: {{- if .Values.registry.credentials.existingSecret }}
name: "{{ template "harbor.jobservice" . }}" - name: REGISTRY_CREDENTIAL_PASSWORD
- name: job-logs valueFrom:
{{- if and .Values.persistence.enabled (eq .Values.jobservice.jobLogger "file") }} secretKeyRef:
persistentVolumeClaim: name: {{ .Values.registry.credentials.existingSecret }}
claimName: {{ .Values.persistence.persistentVolumeClaim.jobservice.existingClaim | default (include "harbor.jobservice" .) }} key: REGISTRY_PASSWD
{{- else }} {{- end }}
emptyDir: {} {{- with .Values.jobservice.extraEnvVars }}
{{- end }} {{- toYaml . | nindent 10 }}
{{- if .Values.internalTLS.enabled }} {{- end }}
- name: jobservice-internal-certs {{- if not (empty .Values.containerSecurityContext) }}
secret: securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
secretName: {{ template "harbor.internalTLS.jobservice.secretName" . }} {{- end }}
{{- end }} envFrom:
{{- if .Values.caBundleSecretName }} - configMapRef:
{{ include "harbor.caBundleVolume" . | indent 6 }} name: "{{ template "harbor.jobservice" . }}-env"
{{- end }} - secretRef:
{{- with .Values.jobservice.nodeSelector }} name: "{{ template "harbor.jobservice" . }}"
nodeSelector: ports:
{{ toYaml . | indent 8 }} - containerPort: {{ template "harbor.jobservice.containerPort" . }}
{{- end }} volumeMounts:
{{- with .Values.jobservice.affinity }} - name: jobservice-config
affinity: mountPath: /etc/jobservice/config.yml
{{ toYaml . | indent 8 }} subPath: config.yml
{{- end }} - name: job-logs
{{- with .Values.jobservice.tolerations }} mountPath: /var/log/jobs
tolerations: subPath: {{ .Values.persistence.persistentVolumeClaim.jobservice.jobLog.subPath }}
{{ toYaml . | indent 8 }} {{- if .Values.internalTLS.enabled }}
{{- end }} - name: jobservice-internal-certs
mountPath: /etc/harbor/ssl/jobservice
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
volumes:
- name: jobservice-config
configMap:
name: "{{ template "harbor.jobservice" . }}"
- name: job-logs
{{- if and .Values.persistence.enabled (has "file" .Values.jobservice.jobLoggers) }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.persistentVolumeClaim.jobservice.jobLog.existingClaim | default (include "harbor.jobservice" .) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: jobservice-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.jobservice.secretName" . }}
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- with .Values.jobservice.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.jobservice.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.jobservice.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.jobservice.priorityClassName }}
priorityClassName: {{ .Values.jobservice.priorityClassName }}
{{- end }}
{{- $jobservice := .Values.persistence.persistentVolumeClaim.jobservice -}} {{- $jobLog := .Values.persistence.persistentVolumeClaim.jobservice.jobLog -}}
{{- if and .Values.persistence.enabled (not $jobservice.existingClaim) }} {{- if and .Values.persistence.enabled (not $jobLog.existingClaim) (has "file" .Values.jobservice.jobLoggers) }}
{{- if eq .Values.jobservice.jobLogger "file" }} kind: PersistentVolumeClaim
kind: PersistentVolumeClaim apiVersion: v1
apiVersion: v1 metadata:
metadata: name: {{ template "harbor.jobservice" . }}
name: {{ template "harbor.jobservice" . }} namespace: {{ .Release.Namespace | quote }}
{{- if eq .Values.persistence.resourcePolicy "keep" }} annotations:
annotations: {{- range $key, $value := $jobLog.annotations }}
helm.sh/resource-policy: keep {{ $key }}: {{ $value | quote }}
{{- end }} {{- end }}
labels: {{- if eq .Values.persistence.resourcePolicy "keep" }}
{{ include "harbor.labels" . | indent 4 }} helm.sh/resource-policy: keep
component: jobservice {{- end }}
spec: labels:
accessModes: {{ include "harbor.labels" . | indent 4 }}
- {{ $jobservice.accessMode }} component: jobservice
resources: app.kubernetes.io/component: jobservice
requests: spec:
storage: {{ $jobservice.size }} accessModes:
{{- if $jobservice.storageClass }} - {{ $jobLog.accessMode }}
{{- if eq "-" $jobservice.storageClass }} resources:
storageClassName: "" requests:
{{- else }} storage: {{ $jobLog.size }}
storageClassName: {{ $jobservice.storageClass }} {{- if $jobLog.storageClass }}
{{- end }} {{- if eq "-" $jobLog.storageClass }}
{{- end }} storageClassName: ""
{{- end }} {{- else }}
{{- end }} storageClassName: {{ $jobLog.storageClass }}
\ No newline at end of file {{- end }}
{{- end }}
{{- end }}
apiVersion: v1 {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (include "harbor.jobservice" .) }}
kind: Secret apiVersion: v1
metadata: kind: Secret
name: "{{ template "harbor.jobservice" . }}" metadata:
labels: name: "{{ template "harbor.jobservice" . }}"
{{ include "harbor.labels" . | indent 4 }} namespace: {{ .Release.Namespace | quote }}
type: Opaque labels:
data: {{ include "harbor.labels" . | indent 4 }}
JOBSERVICE_SECRET: {{ .Values.jobservice.secret | default (randAlphaNum 16) | b64enc | quote }} type: Opaque
REGISTRY_CREDENTIAL_PASSWORD: {{ .Values.registry.credentials.password | b64enc | quote }} data:
{{- if not .Values.jobservice.existingSecret }}
JOBSERVICE_SECRET: {{ .Values.jobservice.secret | default (include "harbor.secretKeyHelper" (dict "key" "JOBSERVICE_SECRET" "data" $existingSecret.data)) | default (randAlphaNum 16) | b64enc | quote }}
{{- end }}
{{- if not .Values.registry.credentials.existingSecret }}
REGISTRY_CREDENTIAL_PASSWORD: {{ .Values.registry.credentials.password | b64enc | quote }}
{{- end }}
{{- template "harbor.traceJaegerPassword" . }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: "{{ template "harbor.jobservice" . }}" name: "{{ template "harbor.jobservice" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
ports: spec:
- port: {{ template "harbor.jobservice.servicePort" . }} ports:
targetPort: {{ template "harbor.jobservice.containerPort" . }} - name: {{ ternary "https-jobservice" "http-jobservice" .Values.internalTLS.enabled }}
selector: port: {{ template "harbor.jobservice.servicePort" . }}
{{ include "harbor.matchLabels" . | indent 4 }} targetPort: {{ template "harbor.jobservice.containerPort" . }}
component: jobservice {{- if .Values.metrics.enabled }}
- name: {{ template "harbor.metricsPortName" . }}
port: {{ .Values.metrics.jobservice.port }}
{{- end }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: jobservice
{{- if and .Values.internalTLS.enabled }} {{- if and .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }} {{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.internalTLS.jobservice.secretName" . }}" name: "{{ template "harbor.internalTLS.jobservice.secretName" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: kubernetes.io/tls {{ include "harbor.labels" . | indent 4 }}
data: type: kubernetes.io/tls
ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }} data:
tls.crt: {{ (required "The \"internalTLS.jobservice.crt\" is required!" .Values.internalTLS.jobservice.crt) | b64enc | quote }} ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.jobservice.key\" is required!" .Values.internalTLS.jobservice.key) | b64enc | quote }} tls.crt: {{ (required "The \"internalTLS.jobservice.crt\" is required!" .Values.internalTLS.jobservice.crt) | b64enc | quote }}
{{- end }} tls.key: {{ (required "The \"internalTLS.jobservice.key\" is required!" .Values.internalTLS.jobservice.key) | b64enc | quote }}
{{- end }} {{- end }}
\ No newline at end of file {{- end }}
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ template "harbor.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels: {{ include "harbor.labels" . | nindent 4 }}
{{- if .Values.metrics.serviceMonitor.additionalLabels }}
{{ toYaml .Values.metrics.serviceMonitor.additionalLabels | indent 4 }}
{{- end }}
spec:
jobLabel: app.kubernetes.io/name
endpoints:
- port: {{ template "harbor.metricsPortName" . }}
{{- if .Values.metrics.serviceMonitor.interval }}
interval: {{ .Values.metrics.serviceMonitor.interval }}
{{- end }}
honorLabels: true
{{- if .Values.metrics.serviceMonitor.metricRelabelings }}
metricRelabelings:
{{ tpl (toYaml .Values.metrics.serviceMonitor.metricRelabelings | indent 4) . }}
{{- end }}
{{- if .Values.metrics.serviceMonitor.relabelings }}
relabelings:
{{ toYaml .Values.metrics.serviceMonitor.relabelings | indent 4 }}
{{- end }}
selector:
matchLabels: {{ include "harbor.matchLabels" . | nindent 6 }}
{{- end }}
{{- if and (ne .Values.expose.type "ingress") (not .Values.expose.tls.enabled) }} {{- if and (ne .Values.expose.type "ingress") (not .Values.expose.tls.enabled) }}
{{- $scheme := (include "harbor.component.scheme" .) -}} {{- $scheme := (include "harbor.component.scheme" .) -}}
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: {{ template "harbor.nginx" . }} name: {{ template "harbor.nginx" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
data: {{ include "harbor.labels" . | indent 4 }}
nginx.conf: |+ data:
worker_processes auto; nginx.conf: |+
pid /tmp/nginx.pid; worker_processes auto;
pid /tmp/nginx.pid;
events {
worker_connections 1024; events {
use epoll; worker_connections 3096;
multi_accept on; use epoll;
} multi_accept on;
}
http {
client_body_temp_path /tmp/client_body_temp; http {
proxy_temp_path /tmp/proxy_temp; client_body_temp_path /tmp/client_body_temp;
fastcgi_temp_path /tmp/fastcgi_temp; proxy_temp_path /tmp/proxy_temp;
uwsgi_temp_path /tmp/uwsgi_temp; fastcgi_temp_path /tmp/fastcgi_temp;
scgi_temp_path /tmp/scgi_temp; uwsgi_temp_path /tmp/uwsgi_temp;
tcp_nodelay on; scgi_temp_path /tmp/scgi_temp;
tcp_nodelay on;
# this is necessary for us to be able to disable request buffering in all cases
proxy_http_version 1.1; # this is necessary for us to be able to disable request buffering in all cases
proxy_http_version 1.1;
upstream core {
server "{{ template "harbor.core" . }}:{{ template "harbor.core.servicePort" . }}"; upstream core {
} server "{{ template "harbor.core" . }}:{{ template "harbor.core.servicePort" . }}";
}
upstream portal {
server {{ template "harbor.portal" . }}:{{ template "harbor.portal.servicePort" . }}; upstream portal {
} server {{ template "harbor.portal" . }}:{{ template "harbor.portal.servicePort" . }};
}
log_format timed_combined '[$time_local]:$remote_addr - '
'"$request" $status $body_bytes_sent ' log_format timed_combined '[$time_local]:$remote_addr - '
'"$http_referer" "$http_user_agent" ' '"$request" $status $body_bytes_sent '
'$request_time $upstream_response_time $pipe'; '"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time $pipe';
access_log /dev/stdout timed_combined;
access_log /dev/stdout timed_combined;
server {
listen 8080; map $http_x_forwarded_proto $x_forwarded_proto {
server_tokens off; default $http_x_forwarded_proto;
# disable any limits to avoid HTTP 413 for large image uploads "" $scheme;
client_max_body_size 0; }
# Add extra headers server {
add_header X-Frame-Options DENY; {{- if .Values.ipFamily.ipv4.enabled}}
add_header Content-Security-Policy "frame-ancestors 'none'"; listen 8080;
{{- end}}
location / { {{- if .Values.ipFamily.ipv6.enabled }}
proxy_pass {{ $scheme }}://portal/; listen [::]:8080;
proxy_set_header Host $host; {{- end }}
proxy_set_header X-Real-IP $remote_addr; server_tokens off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme; # Add extra headers
add_header X-Frame-Options DENY;
proxy_buffering off; add_header Content-Security-Policy "frame-ancestors 'none'";
proxy_request_buffering off;
} location / {
proxy_pass {{ $scheme }}://portal/;
location /api/ { proxy_set_header Host $host;
proxy_pass {{ $scheme }}://core/api/; proxy_set_header X-Real-IP $remote_addr;
{{- if and .Values.internalTLS.enabled }} proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_ssl_verify off; proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
proxy_ssl_session_reuse on;
{{- end }} proxy_buffering off;
proxy_set_header Host $host; proxy_request_buffering off;
proxy_set_header X-Real-IP $remote_addr; }
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /api/ {
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. proxy_pass {{ $scheme }}://core/api/;
proxy_set_header X-Forwarded-Proto $scheme; {{- if and .Values.internalTLS.enabled }}
proxy_ssl_verify off;
proxy_buffering off; proxy_ssl_session_reuse on;
proxy_request_buffering off; {{- end }}
} proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
location /chartrepo/ { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass {{ $scheme }}://core/chartrepo/; proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
{{- if and .Values.internalTLS.enabled }}
proxy_ssl_verify off; proxy_buffering off;
proxy_ssl_session_reuse on; proxy_request_buffering off;
{{- end }} }
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; location /c/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass {{ $scheme }}://core/c/;
proxy_set_header Host $host;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
proxy_buffering off;
proxy_request_buffering off; proxy_buffering off;
} proxy_request_buffering off;
}
location /c/ {
proxy_pass {{ $scheme }}://core/c/; location /v1/ {
proxy_set_header Host $host; return 404;
proxy_set_header X-Real-IP $remote_addr; }
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /v2/ {
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. proxy_pass {{ $scheme }}://core/v2/;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_request_buffering off; proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
} proxy_buffering off;
proxy_request_buffering off;
location /v1/ { proxy_send_timeout 900;
return 404; proxy_read_timeout 900;
} }
location /v2/ { location /service/ {
proxy_pass {{ $scheme }}://core/v2/; proxy_pass {{ $scheme }}://core/service/;
proxy_set_header Host $http_host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off;
proxy_buffering off; proxy_request_buffering off;
proxy_request_buffering off; }
}
location /service/notifications {
location /service/ { return 404;
proxy_pass {{ $scheme }}://core/service/; }
proxy_set_header Host $host; }
proxy_set_header X-Real-IP $remote_addr; }
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; {{- end }}
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
location /service/notifications {
return 404;
}
}
}
{{- end }}
{{- if and (ne .Values.expose.type "ingress") .Values.expose.tls.enabled }} {{- if and (ne .Values.expose.type "ingress") .Values.expose.tls.enabled }}
{{- $scheme := (include "harbor.component.scheme" .) -}} {{- $scheme := (include "harbor.component.scheme" .) -}}
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: {{ template "harbor.nginx" . }} name: {{ template "harbor.nginx" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
data: {{ include "harbor.labels" . | indent 4 }}
nginx.conf: |+ data:
worker_processes auto; nginx.conf: |+
pid /tmp/nginx.pid; worker_processes auto;
pid /tmp/nginx.pid;
events {
worker_connections 1024; events {
use epoll; worker_connections 3096;
multi_accept on; use epoll;
} multi_accept on;
}
http {
client_body_temp_path /tmp/client_body_temp; http {
proxy_temp_path /tmp/proxy_temp; client_body_temp_path /tmp/client_body_temp;
fastcgi_temp_path /tmp/fastcgi_temp; proxy_temp_path /tmp/proxy_temp;
uwsgi_temp_path /tmp/uwsgi_temp; fastcgi_temp_path /tmp/fastcgi_temp;
scgi_temp_path /tmp/scgi_temp; uwsgi_temp_path /tmp/uwsgi_temp;
tcp_nodelay on; scgi_temp_path /tmp/scgi_temp;
tcp_nodelay on;
# this is necessary for us to be able to disable request buffering in all cases
proxy_http_version 1.1; # this is necessary for us to be able to disable request buffering in all cases
proxy_http_version 1.1;
upstream core {
server "{{ template "harbor.core" . }}:{{ template "harbor.core.servicePort" . }}"; upstream core {
} server "{{ template "harbor.core" . }}:{{ template "harbor.core.servicePort" . }}";
}
upstream portal {
server "{{ template "harbor.portal" . }}:{{ template "harbor.portal.servicePort" . }}"; upstream portal {
} server "{{ template "harbor.portal" . }}:{{ template "harbor.portal.servicePort" . }}";
}
{{- if .Values.notary.enabled }}
upstream notary-server { log_format timed_combined '[$time_local]:$remote_addr - '
server {{ template "harbor.notary-server" . }}:4443; '"$request" $status $body_bytes_sent '
} '"$http_referer" "$http_user_agent" '
{{- end }} '$request_time $upstream_response_time $pipe';
log_format timed_combined '[$time_local]:$remote_addr - ' access_log /dev/stdout timed_combined;
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" ' map $http_x_forwarded_proto $x_forwarded_proto {
'$request_time $upstream_response_time $pipe'; default $http_x_forwarded_proto;
"" $scheme;
access_log /dev/stdout timed_combined; }
{{- if .Values.notary.enabled }} server {
server { {{- if .Values.ipFamily.ipv4.enabled }}
listen 4443 ssl; listen 8443 ssl;
server_tokens off; {{- end}}
# ssl {{- if .Values.ipFamily.ipv6.enabled }}
ssl_certificate /etc/nginx/cert/tls.crt; listen [::]:8443 ssl;
ssl_certificate_key /etc/nginx/cert/tls.key; {{- end }}
# server_name harbordomain.com;
# recommendations from https://raymii.org/s/tutorials/strong_ssl_security_on_nginx.html server_tokens off;
ssl_protocols tlsv1.1 tlsv1.2; # SSL
ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:'; ssl_certificate /etc/nginx/cert/tls.crt;
ssl_prefer_server_ciphers on; ssl_certificate_key /etc/nginx/cert/tls.key;
ssl_session_cache shared:ssl:10m;
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
# disable any limits to avoid http 413 for large image uploads ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 0; {{- if .Values.internalTLS.strong_ssl_ciphers }}
ssl_ciphers ECDHE+AESGCM:DHE+AESGCM:ECDHE+RSA+SHA256:DHE+RSA+SHA256:!AES128;
# required to avoid http 411: see issue #1486 (https://github.com/docker/docker/issues/1486) {{ else }}
chunked_transfer_encoding on; ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
{{- end }}
location /v2/ { ssl_prefer_server_ciphers on;
proxy_pass http://notary-server/v2/; ssl_session_cache shared:SSL:10m;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr; # disable any limits to avoid HTTP 413 for large image uploads
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 0;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
proxy_set_header X-Forwarded-Proto $scheme; chunked_transfer_encoding on;
proxy_buffering off; # Add extra headers
proxy_request_buffering off; add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
} add_header X-Frame-Options DENY;
} add_header Content-Security-Policy "frame-ancestors 'none'";
{{- end }}
location / {
server { proxy_pass {{ $scheme }}://portal/;
listen 8443 ssl; proxy_set_header Host $http_host;
# server_name harbordomain.com; proxy_set_header X-Real-IP $remote_addr;
server_tokens off; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# SSL proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
ssl_certificate /etc/nginx/cert/tls.crt;
ssl_certificate_key /etc/nginx/cert/tls.key; proxy_cookie_path / "/; HttpOnly; Secure";
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html proxy_buffering off;
ssl_protocols TLSv1.1 TLSv1.2; proxy_request_buffering off;
ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:'; }
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m; location /api/ {
proxy_pass {{ $scheme }}://core/api/;
# disable any limits to avoid HTTP 413 for large image uploads {{- if and .Values.internalTLS.enabled }}
client_max_body_size 0; proxy_ssl_verify off;
proxy_ssl_session_reuse on;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486) {{- end }}
chunked_transfer_encoding on; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Add extra headers proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
add_header X-Frame-Options DENY;
add_header Content-Security-Policy "frame-ancestors 'none'"; proxy_cookie_path / "/; Secure";
location / { proxy_buffering off;
proxy_pass {{ $scheme }}://portal/; proxy_request_buffering off;
proxy_set_header Host $http_host; }
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location /c/ {
proxy_pass {{ $scheme }}://core/c/;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cookie_path / "/; HttpOnly; Secure"; proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
proxy_buffering off; proxy_cookie_path / "/; Secure";
proxy_request_buffering off;
} proxy_buffering off;
proxy_request_buffering off;
location /api/ { }
proxy_pass {{ $scheme }}://core/api/;
{{- if and .Values.internalTLS.enabled }} location /v1/ {
proxy_ssl_verify off; return 404;
proxy_ssl_session_reuse on; }
{{- end }}
proxy_set_header Host $host; location /v2/ {
proxy_set_header X-Real-IP $remote_addr; proxy_pass {{ $scheme }}://core/v2/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
proxy_buffering off;
proxy_cookie_path / "/; Secure"; proxy_request_buffering off;
}
proxy_buffering off;
proxy_request_buffering off; location /service/ {
} proxy_pass {{ $scheme }}://core/service/;
proxy_set_header Host $http_host;
location /chartrepo/ { proxy_set_header X-Real-IP $remote_addr;
proxy_pass {{ $scheme }}://core/chartrepo/; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
{{- if and .Values.internalTLS.enabled }} proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
proxy_ssl_verify off;
proxy_ssl_session_reuse on; proxy_cookie_path / "/; Secure";
{{- end }}
proxy_set_header Host $host; proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr; proxy_request_buffering off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. location /service/notifications {
proxy_set_header X-Forwarded-Proto $scheme; return 404;
}
proxy_cookie_path / "/; Secure"; }
server {
proxy_buffering off; {{- if .Values.ipFamily.ipv4.enabled }}
proxy_request_buffering off; listen 8080;
} {{- end}}
{{- if .Values.ipFamily.ipv6.enabled }}
location /c/ { listen [::]:8080;
proxy_pass {{ $scheme }}://core/c/; {{- end}}
proxy_set_header Host $host; #server_name harbordomain.com;
proxy_set_header X-Real-IP $remote_addr; return 301 https://$host$request_uri;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
}
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings. {{- end }}
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cookie_path / "/; Secure";
proxy_buffering off;
proxy_request_buffering off;
}
location /v1/ {
return 404;
}
location /v2/ {
proxy_pass {{ $scheme }}://core/v2/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
location /service/ {
proxy_pass {{ $scheme }}://core/service/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# When setting up Harbor behind other proxy, such as an Nginx instance, remove the below line if the proxy already has similar settings.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cookie_path / "/; Secure";
proxy_buffering off;
proxy_request_buffering off;
}
location /service/notifications {
return 404;
}
}
server {
listen 8080;
#server_name harbordomain.com;
return 301 https://$host$request_uri;
}
}
{{- end }}
{{- if ne .Values.expose.type "ingress" }} {{- if ne .Values.expose.type "ingress" }}
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ template "harbor.nginx" . }} name: {{ template "harbor.nginx" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
component: nginx {{ include "harbor.labels" . | indent 4 }}
spec: component: nginx
replicas: {{ .Values.nginx.replicas }} app.kubernetes.io/component: nginx
selector: spec:
matchLabels: replicas: {{ .Values.nginx.replicas }}
{{ include "harbor.matchLabels" . | indent 6 }} revisionHistoryLimit: {{ .Values.nginx.revisionHistoryLimit }}
component: nginx selector:
template: matchLabels:
metadata: {{ include "harbor.matchLabels" . | indent 6 }}
labels: component: nginx
{{ include "harbor.labels" . | indent 8 }} template:
component: nginx metadata:
annotations: labels:
{{- if not .Values.expose.tls.enabled }} {{ include "harbor.labels" . | indent 8 }}
checksum/configmap: {{ include (print $.Template.BasePath "/nginx/configmap-http.yaml") . | sha256sum }} component: nginx
{{- else }} app.kubernetes.io/component: nginx
checksum/configmap: {{ include (print $.Template.BasePath "/nginx/configmap-https.yaml") . | sha256sum }} {{- if .Values.nginx.podLabels }}
{{- end }} {{ toYaml .Values.nginx.podLabels | indent 8 }}
{{- if eq (include "harbor.autoGenCertForNginx" .) "true" }} {{- end }}
checksum/secret: {{ include (print $.Template.BasePath "/nginx/secret.yaml") . | sha256sum }} annotations:
{{- end }} {{- if not .Values.expose.tls.enabled }}
{{- if .Values.nginx.podAnnotations }} checksum/configmap: {{ include (print $.Template.BasePath "/nginx/configmap-http.yaml") . | sha256sum }}
{{ toYaml .Values.nginx.podAnnotations | indent 8 }} {{- else }}
{{- end }} checksum/configmap: {{ include (print $.Template.BasePath "/nginx/configmap-https.yaml") . | sha256sum }}
spec: {{- end }}
{{- with .Values.global.imagePullSecrets }} {{- if eq (include "harbor.autoGenCertForNginx" .) "true" }}
imagePullSecrets: checksum/secret: {{ include (print $.Template.BasePath "/nginx/secret.yaml") . | sha256sum }}
{{- toYaml . | nindent 8 }} {{- end }}
{{- end }} {{- if .Values.nginx.podAnnotations }}
{{- if .Values.nginx.serviceAccountName }} {{ toYaml .Values.nginx.podAnnotations | indent 8 }}
serviceAccountName: {{ .Values.nginx.serviceAccountName }} {{- end }}
{{- end }} spec:
securityContext: {{- if .Values.nginx.serviceAccountName }}
fsGroup: 10000 serviceAccountName: {{ .Values.nginx.serviceAccountName }}
{{- with .Values.imagePullSecrets }} {{- end }}
imagePullSecrets: securityContext:
{{- toYaml . | nindent 8 }} runAsUser: 10000
{{- end }} fsGroup: 10000
containers: {{- with .Values.imagePullSecrets }}
- name: nginx imagePullSecrets:
{{- if contains "/" .Values.nginx.image.repository }} {{- toYaml . | nindent 8 }}
image: "{{ .Values.nginx.image.repository }}" {{- end }}
{{- else }} automountServiceAccountToken: {{ .Values.nginx.automountServiceAccountToken | default false }}
image: "{{ .Values.nginx.image.hub | default .Values.global.hub }}/{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" {{- with .Values.nginx.topologySpreadConstraints}}
{{- end }} topologySpreadConstraints:
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" {{- range . }}
{{- $_ := set . "scheme" "HTTP" -}} - {{ . | toYaml | indent 8 | trim }}
{{- $_ := set . "port" "8080" -}} labelSelector:
{{- if .Values.expose.tls.enabled }} matchLabels:
{{- $_ := set . "scheme" "HTTPS" -}} {{ include "harbor.matchLabels" $ | indent 12 }}
{{- $_ := set . "port" "8443" -}} component: nginx
{{- end }} {{- end }}
livenessProbe: {{- end }}
httpGet: containers:
scheme: {{ .scheme }} - name: nginx
path: / image: "{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.tag }}"
port: {{ .port }} imagePullPolicy: "{{ .Values.imagePullPolicy }}"
initialDelaySeconds: 300 {{- $_ := set . "scheme" "HTTP" -}}
periodSeconds: 10 {{- $_ := set . "port" "8080" -}}
readinessProbe: {{- if .Values.expose.tls.enabled }}
httpGet: {{- $_ := set . "scheme" "HTTPS" -}}
scheme: {{ .scheme }} {{- $_ := set . "port" "8443" -}}
path: / {{- end }}
port: {{ .port }} livenessProbe:
initialDelaySeconds: 1 httpGet:
periodSeconds: 10 scheme: {{ .scheme }}
{{- if .Values.nginx.resources }} path: /
resources: port: {{ .port }}
{{ toYaml .Values.nginx.resources | indent 10 }} initialDelaySeconds: 300
{{- end }} periodSeconds: 10
ports: readinessProbe:
- containerPort: 8080 httpGet:
- containerPort: 8443 scheme: {{ .scheme }}
- containerPort: 4443 path: /
volumeMounts: port: {{ .port }}
- name: config initialDelaySeconds: 1
mountPath: /etc/nginx/nginx.conf periodSeconds: 10
subPath: nginx.conf {{- if .Values.nginx.resources }}
{{- if .Values.expose.tls.enabled }} resources:
- name: certificate {{ toYaml .Values.nginx.resources | indent 10 }}
mountPath: /etc/nginx/cert {{- end }}
{{- end }} {{- with .Values.nginx.extraEnvVars }}
volumes: env:
- name: config {{- toYaml . | nindent 10 }}
configMap: {{- end }}
name: {{ template "harbor.nginx" . }} {{- if not (empty .Values.containerSecurityContext) }}
{{- if .Values.expose.tls.enabled }} securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
- name: certificate {{- end }}
secret: ports:
secretName: {{ template "harbor.tlsSecretForNginx" . }} - containerPort: 8080
{{- end }} {{- if .Values.expose.tls.enabled }}
{{- with .Values.nginx.nodeSelector }} - containerPort: 8443
nodeSelector: {{- end }}
{{ toYaml . | indent 8 }} volumeMounts:
{{- end }} - name: config
{{- with .Values.nginx.affinity }} mountPath: /etc/nginx/nginx.conf
affinity: subPath: nginx.conf
{{ toYaml . | indent 8 }} {{- if .Values.expose.tls.enabled }}
{{- end }} - name: certificate
{{- with .Values.nginx.tolerations }} mountPath: /etc/nginx/cert
tolerations: {{- end }}
{{ toYaml . | indent 8 }} volumes:
{{- end }} - name: config
{{- end }} configMap:
name: {{ template "harbor.nginx" . }}
{{- if .Values.expose.tls.enabled }}
- name: certificate
secret:
secretName: {{ template "harbor.tlsSecretForNginx" . }}
{{- end }}
{{- with .Values.nginx.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.nginx.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.nginx.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.nginx.priorityClassName }}
priorityClassName: {{ .Values.nginx.priorityClassName }}
{{- end }}
{{- end }}
{{- if eq (include "harbor.autoGenCertForNginx" .) "true" }} {{- if eq (include "harbor.autoGenCertForNginx" .) "true" }}
{{- $ca := genCA "harbor-ca" 365 }} {{- $ca := genCA "harbor-ca" 365 }}
{{- $cn := (required "The \"expose.tls.auto.commonName\" is required!" .Values.expose.tls.auto.commonName) }} {{- $cn := (required "The \"expose.tls.auto.commonName\" is required!" .Values.expose.tls.auto.commonName) }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: {{ template "harbor.nginx" . }} name: {{ template "harbor.nginx" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: Opaque {{ include "harbor.labels" . | indent 4 }}
data: type: Opaque
{{- if regexMatch `^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$` $cn }} data:
{{- $cert := genSignedCert $cn (list $cn) nil 365 $ca }} {{- if regexMatch `^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$` $cn }}
tls.crt: {{ $cert.Cert | b64enc | quote }} {{- $cert := genSignedCert $cn (list $cn) nil 365 $ca }}
tls.key: {{ $cert.Key | b64enc | quote }} tls.crt: {{ $cert.Cert | b64enc | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }} tls.key: {{ $cert.Key | b64enc | quote }}
{{- else }} ca.crt: {{ $ca.Cert | b64enc | quote }}
{{- $cert := genSignedCert $cn nil (list $cn) 365 $ca }} {{- else }}
tls.crt: {{ $cert.Cert | b64enc | quote }} {{- $cert := genSignedCert $cn nil (list $cn) 365 $ca }}
tls.key: {{ $cert.Key | b64enc | quote }} tls.crt: {{ $cert.Cert | b64enc | quote }}
ca.crt: {{ $ca.Cert | b64enc | quote }} tls.key: {{ $cert.Key | b64enc | quote }}
{{- end }} ca.crt: {{ $ca.Cert | b64enc | quote }}
{{- end }} {{- end }}
\ No newline at end of file {{- end }}
{{- if or (eq .Values.expose.type "clusterIP") (eq .Values.expose.type "nodePort") (eq .Values.expose.type "loadBalancer") }} {{- if or (eq .Values.expose.type "clusterIP") (eq .Values.expose.type "nodePort") (eq .Values.expose.type "loadBalancer") }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
{{- if eq .Values.expose.type "clusterIP" }} {{- if eq .Values.expose.type "clusterIP" }}
{{- $clusterIP := .Values.expose.clusterIP }} {{- $clusterIP := .Values.expose.clusterIP }}
name: {{ $clusterIP.name }} name: {{ $clusterIP.name }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
type: ClusterIP {{- if .Values.expose.clusterIP.labels }}
ports: {{ toYaml $clusterIP.labels | indent 4 }}
- name: http {{- end }}
port: {{ $clusterIP.ports.httpPort }} {{- with $clusterIP.annotations }}
targetPort: 8080 annotations:
{{- if .Values.expose.tls.enabled }} {{- toYaml . | nindent 4 }}
- name: https {{- end }}
port: {{ $clusterIP.ports.httpsPort }} spec:
targetPort: 8443 type: ClusterIP
{{- end }} {{- if .Values.expose.clusterIP.staticClusterIP }}
{{- if .Values.notary.enabled }} clusterIP: {{ .Values.expose.clusterIP.staticClusterIP }}
- name: notary {{- end }}
port: {{ $clusterIP.ports.notaryPort }} ports:
targetPort: 4443 - name: http
{{- end }} port: {{ $clusterIP.ports.httpPort }}
{{- else if eq .Values.expose.type "nodePort" }} targetPort: 8080
{{- $nodePort := .Values.expose.nodePort }} {{- if .Values.expose.tls.enabled }}
name: {{ $nodePort.name }} - name: https
labels: port: {{ $clusterIP.ports.httpsPort }}
{{ include "harbor.labels" . | indent 4 }} targetPort: 8443
spec: {{- end }}
type: NodePort {{- else if eq .Values.expose.type "nodePort" }}
ports: {{- $nodePort := .Values.expose.nodePort }}
- name: http name: {{ $nodePort.name }}
port: {{ $nodePort.ports.http.port }} labels:
targetPort: 8080 {{ include "harbor.labels" . | indent 4 }}
{{- if $nodePort.ports.http.nodePort }} {{- if .Values.expose.nodePort.labels }}
nodePort: {{ $nodePort.ports.http.nodePort }} {{ toYaml $nodePort.labels | indent 4 }}
{{- end }} {{- end }}
{{- if .Values.expose.tls.enabled }} {{- with $nodePort.annotations }}
- name: https annotations:
port: {{ $nodePort.ports.https.port }} {{- toYaml . | nindent 4 }}
targetPort: 8443 {{- end }}
{{- if $nodePort.ports.https.nodePort }} spec:
nodePort: {{ $nodePort.ports.https.nodePort }} type: NodePort
{{- end }} ports:
{{- end }} - name: http
{{- if .Values.notary.enabled }} port: {{ $nodePort.ports.http.port }}
- name: notary targetPort: 8080
port: {{ $nodePort.ports.notary.port }} {{- if $nodePort.ports.http.nodePort }}
targetPort: 4443 nodePort: {{ $nodePort.ports.http.nodePort }}
{{- if $nodePort.ports.notary.nodePort }} {{- end }}
nodePort: {{ $nodePort.ports.notary.nodePort }} {{- if .Values.expose.tls.enabled }}
{{- end }} - name: https
{{- end }} port: {{ $nodePort.ports.https.port }}
{{- else if eq .Values.expose.type "loadBalancer" }} targetPort: 8443
{{- $loadBalancer := .Values.expose.loadBalancer }} {{- if $nodePort.ports.https.nodePort }}
name: {{ $loadBalancer.name }} nodePort: {{ $nodePort.ports.https.nodePort }}
labels: {{- end }}
{{ include "harbor.labels" . | indent 4 }} {{- end }}
{{- with $loadBalancer.annotations }} {{- else if eq .Values.expose.type "loadBalancer" }}
annotations: {{- $loadBalancer := .Values.expose.loadBalancer }}
{{- toYaml . | nindent 4 }} name: {{ $loadBalancer.name }}
{{- end }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
type: LoadBalancer {{- if .Values.expose.loadBalancer.labels }}
{{- with $loadBalancer.sourceRanges }} {{ toYaml $loadBalancer.labels | indent 4 }}
loadBalancerSourceRanges: {{- end }}
{{- toYaml . | nindent 4 }} {{- with $loadBalancer.annotations }}
{{- end }} annotations:
{{- if $loadBalancer.IP }} {{- toYaml . | nindent 4 }}
loadBalancerIP: {{ $loadBalancer.IP }} {{- end }}
{{- end }} spec:
ports: type: LoadBalancer
- name: http {{- with $loadBalancer.sourceRanges }}
port: {{ $loadBalancer.ports.httpPort }} loadBalancerSourceRanges:
targetPort: 8080 {{- toYaml . | nindent 4 }}
{{- if .Values.expose.tls.enabled }} {{- end }}
- name: https {{- if $loadBalancer.IP }}
port: {{ $loadBalancer.ports.httpsPort }} loadBalancerIP: {{ $loadBalancer.IP }}
targetPort: 8443 {{- end }}
{{- end }} ports:
{{- if .Values.notary.enabled }} - name: http
- name: notary port: {{ $loadBalancer.ports.httpPort }}
port: {{ $loadBalancer.ports.notaryPort }} targetPort: 8080
targetPort: 4443 {{- if .Values.expose.tls.enabled }}
{{- end }} - name: https
{{- end }} port: {{ $loadBalancer.ports.httpsPort }}
selector: targetPort: 8443
{{ include "harbor.matchLabels" . | indent 4 }} {{- end }}
component: nginx {{- end }}
{{- end }} selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: nginx
{{- end }}
{{- if and .Values.notary.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: notary
type: Opaque
data:
{{- if not .Values.notary.secretName }}
{{- $ca := genCA "harbor-notary-ca" 365 }}
{{- $cert := genSignedCert (include "harbor.notary-signer" .) nil nil 365 $ca }}
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $cert.Cert | b64enc | quote }}
tls.key: {{ $cert.Key | b64enc | quote }}
{{- end }}
server.json: {{ tpl (.Files.Get "conf/notary-server.json") . | b64enc }}
signer.json: {{ tpl (.Files.Get "conf/notary-signer.json") . | b64enc }}
{{- end }}
{{ if .Values.notary.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: notary-server
spec:
replicas: {{ .Values.notary.server.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: notary-server
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: notary-server
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/notary/notary-secret.yaml") . | sha256sum }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- if .Values.notary.podAnnotations }}
{{ toYaml .Values.notary.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
fsGroup: 10000
{{- if .Values.notary.server.serviceAccountName }}
serviceAccountName: {{ .Values.notary.server.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: notary-server
{{- if contains "/" .Values.notary.server.image.repository }}
image: "{{ .Values.notary.server.image.repository }}"
{{- else }}
image: "{{ .Values.notary.server.image.hub | default .Values.global.hub }}/{{ .Values.notary.server.image.repository }}:{{ .Values.notary.server.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}"
{{- end }}
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}"
{{- if .Values.notary.server.resources }}
resources:
{{ toYaml .Values.notary.server.resources | indent 10 }}
{{- end }}
env:
- name: MIGRATIONS_PATH
value: migrations/server/postgresql
- name: DB_URL
value: {{ template "harbor.database.notaryServer" . }}
volumeMounts:
- name: config
mountPath: /etc/notary/server-config.postgres.json
subPath: server.json
- name: token-service-certificate
mountPath: /root.crt
subPath: tls.crt
- name: signer-certificate
mountPath: /etc/ssl/notary/ca.crt
subPath: ca.crt
volumes:
- name: config
secret:
secretName: "{{ template "harbor.notary-server" . }}"
- name: token-service-certificate
secret:
{{- if .Values.core.secretName }}
secretName: {{ .Values.core.secretName }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
- name: signer-certificate
secret:
{{- if .Values.notary.secretName }}
secretName: {{ .Values.notary.secretName }}
{{- else }}
secretName: {{ template "harbor.notary-server" . }}
{{- end }}
{{- with .Values.notary.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{ end }}
{{ if .Values.notary.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.notary-signer" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: notary-signer
spec:
replicas: {{ .Values.notary.signer.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: notary-signer
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: notary-signer
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/notary/notary-secret.yaml") . | sha256sum }}
spec:
securityContext:
fsGroup: 10000
{{- if .Values.notary.signer.serviceAccountName }}
serviceAccountName: {{ .Values.notary.signer.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: notary-signer
{{- if contains "/" .Values.notary.signer.image.repository }}
image: "{{ .Values.notary.signer.image.repository }}"
{{- else }}
image: "{{ .Values.notary.signer.image.hub | default .Values.global.hub }}/{{ .Values.notary.signer.image.repository }}:{{ .Values.notary.signer.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}"
{{- end }}
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}"
{{- if .Values.notary.signer.resources }}
resources:
{{ toYaml .Values.notary.signer.resources | indent 10 }}
{{- end }}
env:
- name: MIGRATIONS_PATH
value: migrations/signer/postgresql
- name: DB_URL
value: {{ template "harbor.database.notarySigner" . }}
- name: NOTARY_SIGNER_DEFAULTALIAS
value: defaultalias
volumeMounts:
- name: config
mountPath: /etc/notary/signer-config.postgres.json
subPath: signer.json
- name: signer-certificate
mountPath: /etc/ssl/notary/tls.crt
subPath: tls.crt
- name: signer-certificate
mountPath: /etc/ssl/notary/tls.key
subPath: tls.key
volumes:
- name: config
secret:
secretName: "{{ template "harbor.notary-server" . }}"
- name: signer-certificate
secret:
{{- if .Values.notary.secretName }}
secretName: {{ .Values.notary.secretName }}
{{- else }}
secretName: {{ template "harbor.notary-server" . }}
{{- end }}
{{- with .Values.notary.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.notary.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{ end }}
{{ if .Values.notary.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
{{- if (eq .Values.expose.ingress.controller "gce") }}
type: NodePort
{{- end }}
ports:
- port: 4443
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: notary-server
---
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.notary-signer" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 7899
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: notary-signer
{{ end }}
\ No newline at end of file
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: "{{ template "harbor.portal" . }}" name: "{{ template "harbor.portal" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
data: {{ include "harbor.labels" . | indent 4 }}
nginx.conf: |+ data:
worker_processes auto; nginx.conf: |+
pid /tmp/nginx.pid; worker_processes auto;
events { pid /tmp/nginx.pid;
worker_connections 1024; events {
} worker_connections 1024;
http { }
client_body_temp_path /tmp/client_body_temp; http {
proxy_temp_path /tmp/proxy_temp; client_body_temp_path /tmp/client_body_temp;
fastcgi_temp_path /tmp/fastcgi_temp; proxy_temp_path /tmp/proxy_temp;
uwsgi_temp_path /tmp/uwsgi_temp; fastcgi_temp_path /tmp/fastcgi_temp;
scgi_temp_path /tmp/scgi_temp; uwsgi_temp_path /tmp/uwsgi_temp;
server { scgi_temp_path /tmp/scgi_temp;
{{- if .Values.internalTLS.enabled }} server {
listen {{ template "harbor.portal.containerPort" . }} ssl; {{- if .Values.internalTLS.enabled }}
# SSL {{- if .Values.ipFamily.ipv4.enabled}}
ssl_certificate /etc/harbor/ssl/portal/tls.crt; listen {{ template "harbor.portal.containerPort" . }} ssl;
ssl_certificate_key /etc/harbor/ssl/portal/tls.key; {{- end }}
{{- if .Values.ipFamily.ipv6.enabled}}
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html listen [::]:{{ template "harbor.portal.containerPort" . }} ssl;
ssl_protocols TLSv1.2; {{- end }}
ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:'; # SSL
ssl_prefer_server_ciphers on; ssl_certificate /etc/harbor/ssl/portal/tls.crt;
ssl_session_cache shared:SSL:10m; ssl_certificate_key /etc/harbor/ssl/portal/tls.key;
{{- else }}
listen {{ template "harbor.portal.containerPort" . }}; # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
{{- end }} ssl_protocols TLSv1.2 TLSv1.3;
server_name localhost; {{- if .Values.internalTLS.strong_ssl_ciphers }}
root /usr/share/nginx/html; ssl_ciphers ECDHE+AESGCM:DHE+AESGCM:ECDHE+RSA+SHA256:DHE+RSA+SHA256:!AES128;
index index.html index.htm; {{ else }}
include /etc/nginx/mime.types; ssl_ciphers '!aNULL:kECDH+AESGCM:ECDH+AESGCM:RSA+AESGCM:kECDH+AES:ECDH+AES:RSA+AES:';
gzip on; {{- end }}
gzip_min_length 1000; ssl_prefer_server_ciphers on;
gzip_proxied expired no-cache no-store private auth; ssl_session_cache shared:SSL:10m;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; {{- else }}
location / { {{- if .Values.ipFamily.ipv4.enabled }}
try_files $uri $uri/ /index.html; listen {{ template "harbor.portal.containerPort" . }};
} {{- end }}
location = /index.html { {{- if .Values.ipFamily.ipv6.enabled}}
add_header Cache-Control "no-store, no-cache, must-revalidate"; listen [::]:{{ template "harbor.portal.containerPort" . }};
} {{- end }}
} {{- end }}
} server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm;
include /etc/nginx/mime.types;
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
location /devcenter-api-2.0 {
try_files $uri $uri/ /swagger-ui-index.html;
}
location / {
try_files $uri $uri/ /index.html;
}
location = /index.html {
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
}
}
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: "{{ template "harbor.portal" . }}" name: "{{ template "harbor.portal" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
component: portal {{ include "harbor.labels" . | indent 4 }}
spec: component: portal
replicas: {{ .Values.portal.replicas }} app.kubernetes.io/component: portal
selector: spec:
matchLabels: replicas: {{ .Values.portal.replicas }}
{{ include "harbor.matchLabels" . | indent 6 }} revisionHistoryLimit: {{ .Values.portal.revisionHistoryLimit }}
component: portal selector:
template: matchLabels:
metadata: {{ include "harbor.matchLabels" . | indent 6 }}
labels: component: portal
{{ include "harbor.labels" . | indent 8 }} template:
component: portal metadata:
annotations: labels:
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }} {{ include "harbor.labels" . | indent 8 }}
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }} component: portal
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }} app.kubernetes.io/component: portal
checksum/tls: {{ include (print $.Template.BasePath "/portal/tls.yaml") . | sha256sum }} {{- if .Values.portal.podLabels }}
{{- end }} {{ toYaml .Values.portal.podLabels | indent 8 }}
{{- if .Values.portal.podAnnotations }} {{- end }}
{{ toYaml .Values.portal.podAnnotations | indent 8 }} annotations:
{{- end }} {{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
spec: checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- with .Values.global.imagePullSecrets }} {{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
imagePullSecrets: checksum/tls: {{ include (print $.Template.BasePath "/portal/tls.yaml") . | sha256sum }}
{{- toYaml . | nindent 8 }} {{- end }}
{{- end }} checksum/configmap: {{ include (print $.Template.BasePath "/portal/configmap.yaml") . | sha256sum }}
{{- with .Values.imagePullSecrets }} {{- if .Values.portal.podAnnotations }}
imagePullSecrets: {{ toYaml .Values.portal.podAnnotations | indent 8 }}
{{- toYaml . | nindent 8 }} {{- end }}
{{- end }} spec:
{{- if .Values.portal.serviceAccountName }} securityContext:
serviceAccountName: {{ .Values.portal.serviceAccountName }} runAsUser: 10000
{{- end }} fsGroup: 10000
containers: {{- with .Values.imagePullSecrets }}
- name: portal imagePullSecrets:
{{- if contains "/" .Values.portal.image.repository }} {{- toYaml . | nindent 8 }}
image: "{{ .Values.portal.image.repository }}" {{- end }}
{{- else }} {{- if .Values.portal.serviceAccountName }}
image: "{{ .Values.portal.image.hub | default .Values.global.hub }}/{{ .Values.portal.image.repository }}:{{ .Values.portal.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" serviceAccountName: {{ .Values.portal.serviceAccountName }}
{{- end }} {{- end }}
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" automountServiceAccountToken: {{ .Values.portal.automountServiceAccountToken | default false }}
{{- if .Values.portal.resources }} {{- with .Values.portal.topologySpreadConstraints}}
resources: topologySpreadConstraints:
{{ toYaml .Values.portal.resources | indent 10 }} {{- range . }}
{{- end }} - {{ . | toYaml | indent 8 | trim }}
livenessProbe: labelSelector:
httpGet: matchLabels:
path: / {{ include "harbor.matchLabels" $ | indent 12 }}
scheme: {{ include "harbor.component.scheme" . | upper }} component: portal
port: {{ template "harbor.portal.containerPort" . }} {{- end }}
initialDelaySeconds: 300 {{- end }}
periodSeconds: 10 {{- with .Values.portal.initContainers }}
readinessProbe: initContainers:
httpGet: {{- toYaml . | nindent 8 }}
path: / {{- end }}
scheme: {{ include "harbor.component.scheme" . | upper }} containers:
port: {{ template "harbor.portal.containerPort" . }} - name: portal
initialDelaySeconds: 1 image: {{ .Values.portal.image.repository }}:{{ .Values.portal.image.tag }}
periodSeconds: 10 imagePullPolicy: {{ .Values.imagePullPolicy }}
ports: {{- if .Values.portal.resources }}
- containerPort: {{ template "harbor.portal.containerPort" . }} resources:
volumeMounts: {{ toYaml .Values.portal.resources | indent 10 }}
- name: portal-config {{- end }}
mountPath: /etc/nginx/nginx.conf {{- with .Values.portal.extraEnvVars }}
subPath: nginx.conf env:
{{- if .Values.internalTLS.enabled }} {{- toYaml . | nindent 10 }}
- name: portal-internal-certs {{- end }}
mountPath: /etc/harbor/ssl/portal {{- if not (empty .Values.containerSecurityContext) }}
{{- end }} securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
volumes: {{- end }}
- name: portal-config livenessProbe:
configMap: httpGet:
name: "{{ template "harbor.portal" . }}" path: /
{{- if .Values.internalTLS.enabled }} scheme: {{ include "harbor.component.scheme" . | upper }}
- name: portal-internal-certs port: {{ template "harbor.portal.containerPort" . }}
secret: initialDelaySeconds: 300
secretName: {{ template "harbor.internalTLS.portal.secretName" . }} periodSeconds: 10
{{- end }} readinessProbe:
{{- with .Values.portal.nodeSelector }} httpGet:
nodeSelector: path: /
{{ toYaml . | indent 8 }} scheme: {{ include "harbor.component.scheme" . | upper }}
{{- end }} port: {{ template "harbor.portal.containerPort" . }}
{{- with .Values.portal.affinity }} initialDelaySeconds: 1
affinity: periodSeconds: 10
{{ toYaml . | indent 8 }} ports:
{{- end }} - containerPort: {{ template "harbor.portal.containerPort" . }}
{{- with .Values.portal.tolerations }} volumeMounts:
tolerations: - name: portal-config
{{ toYaml . | indent 8 }} mountPath: /etc/nginx/nginx.conf
{{- end }} subPath: nginx.conf
{{- if .Values.internalTLS.enabled }}
- name: portal-internal-certs
mountPath: /etc/harbor/ssl/portal
{{- end }}
volumes:
- name: portal-config
configMap:
name: "{{ template "harbor.portal" . }}"
{{- if .Values.internalTLS.enabled }}
- name: portal-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.portal.secretName" . }}
{{- end }}
{{- with .Values.portal.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.portal.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.portal.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.portal.priorityClassName }}
priorityClassName: {{ .Values.portal.priorityClassName }}
{{- end }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: "{{ template "harbor.portal" . }}" name: "{{ template "harbor.portal" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
ports: {{- with .Values.portal.serviceAnnotations }}
- port: {{ template "harbor.portal.servicePort" . }} annotations:
targetPort: {{ template "harbor.portal.containerPort" . }} {{- toYaml . | nindent 4 }}
selector: {{- end }}
{{ include "harbor.matchLabels" . | indent 4 }} spec:
component: portal {{- if or (eq .Values.expose.ingress.controller "gce") (eq .Values.expose.ingress.controller "alb") (eq .Values.expose.ingress.controller "f5-bigip") }}
type: NodePort
{{- end }}
ports:
- port: {{ template "harbor.portal.servicePort" . }}
targetPort: {{ template "harbor.portal.containerPort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: portal
{{- if and .Values.internalTLS.enabled }} {{- if and .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }} {{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.internalTLS.portal.secretName" . }}" name: "{{ template "harbor.internalTLS.portal.secretName" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: kubernetes.io/tls {{ include "harbor.labels" . | indent 4 }}
data: type: kubernetes.io/tls
ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }} data:
tls.crt: {{ (required "The \"internalTLS.portal.crt\" is required!" .Values.internalTLS.portal.crt) | b64enc | quote }} ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.portal.key\" is required!" .Values.internalTLS.portal.key) | b64enc | quote }} tls.crt: {{ (required "The \"internalTLS.portal.crt\" is required!" .Values.internalTLS.portal.crt) | b64enc | quote }}
{{- end }} tls.key: {{ (required "The \"internalTLS.portal.key\" is required!" .Values.internalTLS.portal.key) | b64enc | quote }}
{{- end }} {{- end }}
{{- end }}
{{- if eq .Values.redis.type "internal" -}} {{- if eq .Values.redis.type "internal" -}}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: {{ template "harbor.redis" . }} name: {{ template "harbor.redis" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
ports: spec:
- port: 6379 ports:
selector: - port: 6379
{{ include "harbor.matchLabels" . | indent 4 }} selector:
component: redis {{ include "harbor.matchLabels" . | indent 4 }}
{{- end -}} component: redis
\ No newline at end of file {{- end -}}
{{- if eq .Values.redis.type "internal" -}} {{- if eq .Values.redis.type "internal" -}}
{{- $redis := .Values.persistence.persistentVolumeClaim.redis -}} {{- $redis := .Values.persistence.persistentVolumeClaim.redis -}}
apiVersion: apps/v1 apiVersion: apps/v1
kind: StatefulSet kind: StatefulSet
metadata: metadata:
name: {{ template "harbor.redis" . }} name: {{ template "harbor.redis" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
component: redis {{ include "harbor.labels" . | indent 4 }}
spec: component: redis
replicas: 1 app.kubernetes.io/component: redis
serviceName: {{ template "harbor.redis" . }} spec:
selector: replicas: 1
matchLabels: serviceName: {{ template "harbor.redis" . }}
{{ include "harbor.matchLabels" . | indent 6 }} selector:
component: redis matchLabels:
template: {{ include "harbor.matchLabels" . | indent 6 }}
metadata: component: redis
labels: template:
{{ include "harbor.labels" . | indent 8 }} metadata:
component: redis labels:
{{- if .Values.redis.podAnnotations }} {{ include "harbor.labels" . | indent 8 }}
annotations: component: redis
{{ toYaml .Values.redis.podAnnotations | indent 8 }} app.kubernetes.io/component: redis
{{- end }} {{- if .Values.redis.podLabels }}
spec: {{ toYaml .Values.redis.podLabels | indent 8 }}
{{- with .Values.global.imagePullSecrets }} {{- end }}
imagePullSecrets: {{- if .Values.redis.podAnnotations }}
{{- toYaml . | nindent 8 }} annotations:
{{- end }} {{ toYaml .Values.redis.podAnnotations | indent 8 }}
securityContext: {{- end }}
fsGroup: 999 spec:
{{- if .Values.redis.internal.serviceAccountName }} securityContext:
serviceAccountName: {{ .Values.redis.internal.serviceAccountName }} runAsUser: 999
{{- end -}} fsGroup: 999
{{- with .Values.imagePullSecrets }} {{- if .Values.redis.internal.serviceAccountName }}
imagePullSecrets: serviceAccountName: {{ .Values.redis.internal.serviceAccountName }}
{{- toYaml . | nindent 8 }} {{- end -}}
{{- end }} {{- with .Values.imagePullSecrets }}
containers: imagePullSecrets:
- name: redis {{- toYaml . | nindent 8 }}
{{- if contains "/" .Values.redis.internal.image.repository }} {{- end }}
image: "{{ .Values.redis.internal.image.repository }}" automountServiceAccountToken: {{ .Values.redis.internal.automountServiceAccountToken | default false }}
{{- else }} terminationGracePeriodSeconds: 120
image: "{{ .Values.redis.internal.image.hub | default .Values.global.hub }}/{{ .Values.redis.internal.image.repository }}:{{ .Values.redis.internal.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" {{- with .Values.redis.internal.initContainers }}
{{- end }} initContainers:
imagePullPolicy: "{{ .Values.global.imagePullPolicy }}" {{- toYaml . | nindent 8 }}
livenessProbe: {{- end }}
tcpSocket: containers:
port: 6379 - name: redis
initialDelaySeconds: 300 image: {{ .Values.redis.internal.image.repository }}:{{ .Values.redis.internal.image.tag }}
periodSeconds: 10 imagePullPolicy: {{ .Values.imagePullPolicy }}
readinessProbe: {{- if not (empty .Values.containerSecurityContext) }}
tcpSocket: securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
port: 6379 {{- end }}
initialDelaySeconds: 1 livenessProbe:
periodSeconds: 10 tcpSocket:
{{- if .Values.redis.internal.resources }} port: 6379
resources: initialDelaySeconds: 300
{{ toYaml .Values.redis.internal.resources | indent 10 }} periodSeconds: 10
{{- end }} readinessProbe:
volumeMounts: tcpSocket:
- name: data port: 6379
mountPath: /var/lib/redis initialDelaySeconds: 1
subPath: {{ $redis.subPath }} periodSeconds: 10
{{- if not .Values.persistence.enabled }} {{- if .Values.redis.internal.resources }}
volumes: resources:
- name: data {{ toYaml .Values.redis.internal.resources | indent 10 }}
emptyDir: {} {{- end }}
{{- else if $redis.existingClaim }} {{- with .Values.redis.internal.extraEnvVars }}
volumes: env:
- name: data {{- toYaml . | nindent 10 }}
persistentVolumeClaim: {{- end }}
claimName: {{ $redis.existingClaim }} volumeMounts:
{{- end -}} - name: data
{{- with .Values.redis.internal.nodeSelector }} mountPath: /var/lib/redis
nodeSelector: subPath: {{ $redis.subPath }}
{{ toYaml . | indent 8 }} {{- if not .Values.persistence.enabled }}
{{- end }} volumes:
{{- with .Values.redis.internal.affinity }} - name: data
affinity: emptyDir: {}
{{ toYaml . | indent 8 }} {{- else if $redis.existingClaim }}
{{- end }} volumes:
{{- with .Values.redis.internal.tolerations }} - name: data
tolerations: persistentVolumeClaim:
{{ toYaml . | indent 8 }} claimName: {{ $redis.existingClaim }}
{{- end }} {{- end -}}
{{- if and .Values.persistence.enabled (not $redis.existingClaim) }} {{- with .Values.redis.internal.nodeSelector }}
volumeClaimTemplates: nodeSelector:
- metadata: {{ toYaml . | indent 8 }}
name: data {{- end }}
labels: {{- with .Values.redis.internal.affinity }}
{{ include "harbor.labels" . | indent 8 }} affinity:
spec: {{ toYaml . | indent 8 }}
accessModes: [{{ $redis.accessMode | quote }}] {{- end }}
{{- if $redis.storageClass }} {{- with .Values.redis.internal.tolerations }}
{{- if (eq "-" $redis.storageClass) }} tolerations:
storageClassName: "" {{ toYaml . | indent 8 }}
{{- else }} {{- end }}
storageClassName: "{{ $redis.storageClass }}" {{- if .Values.redis.internal.priorityClassName }}
{{- end }} priorityClassName: {{ .Values.redis.internal.priorityClassName }}
{{- end }} {{- end }}
resources: {{- if and .Values.persistence.enabled (not $redis.existingClaim) }}
requests: volumeClaimTemplates:
storage: {{ $redis.size | quote }} - metadata:
{{- end -}} name: data
{{- end -}} labels:
{{ include "harbor.legacy.labels" . | indent 8 }}
annotations:
{{- range $key, $value := $redis.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
accessModes: [{{ $redis.accessMode | quote }}]
{{- if $redis.storageClass }}
{{- if (eq "-" $redis.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ $redis.storageClass }}"
{{- end }}
{{- end }}
resources:
requests:
storage: {{ $redis.size | quote }}
{{- end -}}
{{- end -}}
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: "{{ template "harbor.registry" . }}" name: "{{ template "harbor.registry" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
data: {{ include "harbor.labels" . | indent 4 }}
config.yml: |+ data:
version: 0.1 config.yml: |+
log: version: 0.1
{{- if eq .Values.logLevel "warning" }} log:
level: warn {{- if eq .Values.logLevel "warning" }}
{{- else if eq .Values.logLevel "fatal" }} level: warn
level: error {{- else if eq .Values.logLevel "fatal" }}
{{- else }} level: error
level: {{ .Values.logLevel }} {{- else }}
{{- end }} level: {{ .Values.logLevel }}
fields: {{- end }}
service: registry fields:
storage: service: registry
{{- $storage := .Values.persistence.imageChartStorage }} storage:
{{- $type := $storage.type }} {{- $storage := .Values.persistence.imageChartStorage }}
{{- if eq $type "filesystem" }} {{- $type := $storage.type }}
filesystem: {{- if eq $type "filesystem" }}
rootdirectory: {{ $storage.filesystem.rootdirectory }} filesystem:
{{- if $storage.filesystem.maxthreads }} rootdirectory: {{ $storage.filesystem.rootdirectory }}
maxthreads: {{ $storage.filesystem.maxthreads }} {{- if $storage.filesystem.maxthreads }}
{{- end }} maxthreads: {{ $storage.filesystem.maxthreads }}
{{- else if eq $type "azure" }} {{- end }}
azure: {{- else if eq $type "azure" }}
accountname: {{ $storage.azure.accountname }} azure:
container: {{ $storage.azure.container }} accountname: {{ $storage.azure.accountname }}
{{- if $storage.azure.realm }} container: {{ $storage.azure.container }}
realm: {{ $storage.azure.realm }} {{- if $storage.azure.realm }}
{{- end }} realm: {{ $storage.azure.realm }}
{{- else if eq $type "gcs" }} {{- end }}
gcs: {{- else if eq $type "gcs" }}
bucket: {{ $storage.gcs.bucket }} gcs:
keyfile: /etc/registry/gcs-key.json bucket: {{ $storage.gcs.bucket }}
{{- if $storage.gcs.rootdirectory }} {{- if not .Values.persistence.imageChartStorage.gcs.useWorkloadIdentity }}
rootdirectory: {{ $storage.gcs.rootdirectory }} keyfile: /etc/registry/gcs-key.json
{{- end }} {{- end }}
{{- if $storage.gcs.chunksize }} {{- if $storage.gcs.rootdirectory }}
chunksize: {{ $storage.gcs.chunksize }} rootdirectory: {{ $storage.gcs.rootdirectory }}
{{- end }} {{- end }}
{{- else if eq $type "s3" }} {{- if $storage.gcs.chunksize }}
s3: chunksize: {{ $storage.gcs.chunksize }}
region: {{ $storage.s3.region }} {{- end }}
bucket: {{ $storage.s3.bucket }} {{- else if eq $type "s3" }}
{{- if $storage.s3.regionendpoint }} s3:
regionendpoint: {{ $storage.s3.regionendpoint }} region: {{ $storage.s3.region }}
{{- end }} bucket: {{ $storage.s3.bucket }}
{{- if $storage.s3.encrypt }} {{- if $storage.s3.regionendpoint }}
encrypt: {{ $storage.s3.encrypt }} regionendpoint: {{ $storage.s3.regionendpoint }}
{{- end }} {{- end }}
{{- if $storage.s3.keyid }} {{- if $storage.s3.encrypt }}
keyid: {{ $storage.s3.keyid }} encrypt: {{ $storage.s3.encrypt }}
{{- end }} {{- end }}
{{- if $storage.s3.secure }} {{- if $storage.s3.keyid }}
secure: {{ $storage.s3.secure }} keyid: {{ $storage.s3.keyid }}
{{- end }} {{- end }}
{{- if and $storage.s3.secure $storage.s3.skipverify }} {{- if $storage.s3.secure }}
skipverify: {{ $storage.s3.skipverify }} secure: {{ $storage.s3.secure }}
{{- end }} {{- end }}
{{- if $storage.s3.v4auth }} {{- if and $storage.s3.secure $storage.s3.skipverify }}
v4auth: {{ $storage.s3.v4auth }} skipverify: {{ $storage.s3.skipverify }}
{{- end }} {{- end }}
{{- if $storage.s3.chunksize }} {{- if $storage.s3.v4auth }}
chunksize: {{ $storage.s3.chunksize }} v4auth: {{ $storage.s3.v4auth }}
{{- end }} {{- end }}
{{- if $storage.s3.rootdirectory }} {{- if $storage.s3.chunksize }}
rootdirectory: {{ $storage.s3.rootdirectory }} chunksize: {{ $storage.s3.chunksize }}
{{- end }} {{- end }}
{{- if $storage.s3.storageclass }} {{- if $storage.s3.rootdirectory }}
storageclass: {{ $storage.s3.storageclass }} rootdirectory: {{ $storage.s3.rootdirectory }}
{{- end }} {{- end }}
{{- if $storage.s3.multipartcopychunksize }} {{- if $storage.s3.storageclass }}
multipartcopychunksize: {{ $storage.s3.multipartcopychunksize }} storageclass: {{ $storage.s3.storageclass }}
{{- end }} {{- end }}
{{- if $storage.s3.multipartcopymaxconcurrency }} {{- if $storage.s3.multipartcopychunksize }}
multipartcopymaxconcurrency: {{ $storage.s3.multipartcopymaxconcurrency }} multipartcopychunksize: {{ $storage.s3.multipartcopychunksize }}
{{- end }} {{- end }}
{{- if $storage.s3.multipartcopythresholdsize }} {{- if $storage.s3.multipartcopymaxconcurrency }}
multipartcopythresholdsize: {{ $storage.s3.multipartcopythresholdsize }} multipartcopymaxconcurrency: {{ $storage.s3.multipartcopymaxconcurrency }}
{{- end }} {{- end }}
{{- else if eq $type "swift" }} {{- if $storage.s3.multipartcopythresholdsize }}
swift: multipartcopythresholdsize: {{ $storage.s3.multipartcopythresholdsize }}
authurl: {{ $storage.swift.authurl }} {{- end }}
username: {{ $storage.swift.username }} {{- else if eq $type "swift" }}
container: {{ $storage.swift.container }} swift:
{{- if $storage.swift.region }} authurl: {{ $storage.swift.authurl }}
region: {{ $storage.swift.region }} username: {{ $storage.swift.username }}
{{- end }} container: {{ $storage.swift.container }}
{{- if $storage.swift.tenant }} {{- if $storage.swift.region }}
tenant: {{ $storage.swift.tenant }} region: {{ $storage.swift.region }}
{{- end }} {{- end }}
{{- if $storage.swift.tenantid }} {{- if $storage.swift.tenant }}
tenantid: {{ $storage.swift.tenantid }} tenant: {{ $storage.swift.tenant }}
{{- end }} {{- end }}
{{- if $storage.swift.domain }} {{- if $storage.swift.tenantid }}
domain: {{ $storage.swift.domain }} tenantid: {{ $storage.swift.tenantid }}
{{- end }} {{- end }}
{{- if $storage.swift.domainid }} {{- if $storage.swift.domain }}
domainid: {{ $storage.swift.domainid }} domain: {{ $storage.swift.domain }}
{{- end }} {{- end }}
{{- if $storage.swift.trustid }} {{- if $storage.swift.domainid }}
trustid: {{ $storage.swift.trustid }} domainid: {{ $storage.swift.domainid }}
{{- end }} {{- end }}
{{- if $storage.swift.insecureskipverify }} {{- if $storage.swift.trustid }}
insecureskipverify: {{ $storage.swift.insecureskipverify }} trustid: {{ $storage.swift.trustid }}
{{- end }} {{- end }}
{{- if $storage.swift.chunksize }} {{- if $storage.swift.insecureskipverify }}
chunksize: {{ $storage.swift.chunksize }} insecureskipverify: {{ $storage.swift.insecureskipverify }}
{{- end }} {{- end }}
{{- if $storage.swift.prefix }} {{- if $storage.swift.chunksize }}
prefix: {{ $storage.swift.prefix }} chunksize: {{ $storage.swift.chunksize }}
{{- end }} {{- end }}
{{- if $storage.swift.authversion }} {{- if $storage.swift.prefix }}
authversion: {{ $storage.swift.authversion }} prefix: {{ $storage.swift.prefix }}
{{- end }} {{- end }}
{{- if $storage.swift.endpointtype }} {{- if $storage.swift.authversion }}
endpointtype: {{ $storage.swift.endpointtype }} authversion: {{ $storage.swift.authversion }}
{{- end }} {{- end }}
{{- if $storage.swift.tempurlcontainerkey }} {{- if $storage.swift.endpointtype }}
tempurlcontainerkey: {{ $storage.swift.tempurlcontainerkey }} endpointtype: {{ $storage.swift.endpointtype }}
{{- end }} {{- end }}
{{- if $storage.swift.tempurlmethods }} {{- if $storage.swift.tempurlcontainerkey }}
tempurlmethods: {{ $storage.swift.tempurlmethods }} tempurlcontainerkey: {{ $storage.swift.tempurlcontainerkey }}
{{- end }} {{- end }}
{{- else if eq $type "oss" }} {{- if $storage.swift.tempurlmethods }}
oss: tempurlmethods: {{ $storage.swift.tempurlmethods }}
accesskeyid: {{ $storage.oss.accesskeyid }} {{- end }}
region: {{ $storage.oss.region }} {{- else if eq $type "oss" }}
bucket: {{ $storage.oss.bucket }} oss:
{{- if $storage.oss.endpoint }} accesskeyid: {{ $storage.oss.accesskeyid }}
endpoint: {{ $storage.oss.endpoint }} region: {{ $storage.oss.region }}
{{- end }} bucket: {{ $storage.oss.bucket }}
{{- if $storage.oss.internal }} {{- if $storage.oss.endpoint }}
internal: {{ $storage.oss.internal }} endpoint: {{ $storage.oss.bucket }}.{{ $storage.oss.endpoint }}
{{- end }} {{- end }}
{{- if $storage.oss.encrypt }} {{- if $storage.oss.internal }}
encrypt: {{ $storage.oss.encrypt }} internal: {{ $storage.oss.internal }}
{{- end }} {{- end }}
{{- if $storage.oss.secure }} {{- if $storage.oss.encrypt }}
secure: {{ $storage.oss.secure }} encrypt: {{ $storage.oss.encrypt }}
{{- end }} {{- end }}
{{- if $storage.oss.chunksize }} {{- if $storage.oss.secure }}
chunksize: {{ $storage.oss.chunksize }} secure: {{ $storage.oss.secure }}
{{- end }} {{- end }}
{{- if $storage.oss.rootdirectory }} {{- if $storage.oss.chunksize }}
rootdirectory: {{ $storage.oss.rootdirectory }} chunksize: {{ $storage.oss.chunksize }}
{{- end }} {{- end }}
{{- end }} {{- if $storage.oss.rootdirectory }}
cache: rootdirectory: {{ $storage.oss.rootdirectory }}
layerinfo: redis {{- end }}
maintenance: {{- end }}
uploadpurging: cache:
enabled: false layerinfo: redis
delete: maintenance:
enabled: true uploadpurging:
redirect: {{- if .Values.registry.upload_purging.enabled }}
disable: {{ $storage.disableredirect }} enabled: true
redis: age: {{ .Values.registry.upload_purging.age }}
addr: {{ template "harbor.redis.addr" . }} interval: {{ .Values.registry.upload_purging.interval }}
{{- if eq "redis+sentinel" (include "harbor.redis.scheme" .) }} dryrun: {{ .Values.registry.upload_purging.dryrun }}
sentinelMasterSet: {{ template "harbor.redis.masterSet" . }} {{- else }}
{{- end }} enabled: false
db: {{ template "harbor.redis.dbForRegistry" . }} {{- end }}
password: {{ template "harbor.redis.password" . }} delete:
readtimeout: 10s enabled: true
writetimeout: 10s redirect:
dialtimeout: 10s disable: {{ $storage.disableredirect }}
http: redis:
addr: :{{ template "harbor.registry.containerPort" . }} addr: {{ template "harbor.redis.addr" . }}
relativeurls: {{ .Values.registry.relativeurls }} {{- if eq "redis+sentinel" (include "harbor.redis.scheme" .) }}
{{- if .Values.internalTLS.enabled }} sentinelMasterSet: {{ template "harbor.redis.masterSet" . }}
tls: {{- end }}
certificate: /etc/harbor/ssl/registry/tls.crt db: {{ template "harbor.redis.dbForRegistry" . }}
key: /etc/harbor/ssl/registry/tls.key {{- if not (eq (include "harbor.redis.password" .) "") }}
minimumtls: tls1.2 password: {{ template "harbor.redis.password" . }}
{{- end }} {{- end }}
# set via environment variable readtimeout: 10s
# secret: placeholder writetimeout: 10s
debug: dialtimeout: 10s
addr: localhost:5001 enableTLS: {{ template "harbor.redis.enableTLS" . }}
auth: pool:
htpasswd: maxidle: 100
realm: harbor-registry-basic-realm maxactive: 500
path: /etc/registry/passwd idletimeout: 60s
validation: http:
disabled: true addr: :{{ template "harbor.registry.containerPort" . }}
compatibility: relativeurls: {{ .Values.registry.relativeurls }}
schema1: {{- if .Values.internalTLS.enabled }}
enabled: true tls:
certificate: /etc/harbor/ssl/registry/tls.crt
{{- if .Values.registry.middleware.enabled }} key: /etc/harbor/ssl/registry/tls.key
{{- $middleware := .Values.registry.middleware }} minimumtls: tls1.2
{{- $middlewareType := $middleware.type }} {{- end }}
{{- if eq $middlewareType "cloudFront" }} # set via environment variable
middleware: # secret: placeholder
storage: debug:
- name: cloudfront {{- if .Values.metrics.enabled}}
options: addr: :{{ .Values.metrics.registry.port }}
baseurl: {{ $middleware.cloudFront.baseurl }} prometheus:
privatekey: /etc/registry/pk.pem enabled: true
keypairid: {{ $middleware.cloudFront.keypairid }} path: {{ .Values.metrics.registry.path }}
duration: {{ $middleware.cloudFront.duration }} {{- else }}
ipfilteredby: {{ $middleware.cloudFront.ipfilteredby }} addr: localhost:5001
{{- end }} {{- end }}
{{- end }} auth:
ctl-config.yml: |+ htpasswd:
--- realm: harbor-registry-basic-realm
{{- if .Values.internalTLS.enabled }} path: /etc/registry/passwd
protocol: "https" validation:
port: 8443 disabled: true
https_config: compatibility:
cert: "/etc/harbor/ssl/registry/tls.crt" schema1:
key: "/etc/harbor/ssl/registry/tls.key" enabled: true
{{- else }}
protocol: "http" {{- if .Values.registry.middleware.enabled }}
port: 8080 {{- $middleware := .Values.registry.middleware }}
{{- end }} {{- $middlewareType := $middleware.type }}
log_level: {{ .Values.logLevel }} {{- if eq $middlewareType "cloudFront" }}
registry_config: "/etc/registry/config.yml" middleware:
storage:
- name: cloudfront
options:
baseurl: {{ $middleware.cloudFront.baseurl }}
privatekey: /etc/registry/pk.pem
keypairid: {{ $middleware.cloudFront.keypairid }}
duration: {{ $middleware.cloudFront.duration }}
ipfilteredby: {{ $middleware.cloudFront.ipfilteredby }}
{{- end }}
{{- end }}
ctl-config.yml: |+
---
{{- if .Values.internalTLS.enabled }}
protocol: "https"
port: 8443
https_config:
cert: "/etc/harbor/ssl/registry/tls.crt"
key: "/etc/harbor/ssl/registry/tls.key"
{{- else }}
protocol: "http"
port: 8080
{{- end }}
log_level: {{ .Values.logLevel }}
registry_config: "/etc/registry/config.yml"
apiVersion: apps/v1 {{- $storage := .Values.persistence.imageChartStorage }}
kind: Deployment {{- $type := $storage.type }}
metadata: apiVersion: apps/v1
name: "{{ template "harbor.registry" . }}" kind: Deployment
labels: metadata:
{{ include "harbor.labels" . | indent 4 }} name: "{{ template "harbor.registry" . }}"
component: registry namespace: {{ .Release.Namespace | quote }}
spec: labels:
replicas: {{ .Values.registry.replicas }} {{ include "harbor.labels" . | indent 4 }}
strategy: component: registry
type: {{ .Values.updateStrategy.type }} app.kubernetes.io/component: registry
{{- if eq .Values.updateStrategy.type "Recreate" }} spec:
rollingUpdate: null replicas: {{ .Values.registry.replicas }}
{{- end }} revisionHistoryLimit: {{ .Values.registry.revisionHistoryLimit }}
selector: strategy:
matchLabels: type: {{ .Values.updateStrategy.type }}
{{ include "harbor.matchLabels" . | indent 6 }} {{- if eq .Values.updateStrategy.type "Recreate" }}
component: registry rollingUpdate: null
template: {{- end }}
metadata: selector:
labels: matchLabels:
{{ include "harbor.labels" . | indent 8 }} {{ include "harbor.matchLabels" . | indent 6 }}
component: registry component: registry
annotations: template:
checksum/configmap: {{ include (print $.Template.BasePath "/registry/registry-cm.yaml") . | sha256sum }} metadata:
checksum/secret: {{ include (print $.Template.BasePath "/registry/registry-secret.yaml") . | sha256sum }} labels:
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }} {{ include "harbor.labels" . | indent 8 }}
checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }} component: registry
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }} app.kubernetes.io/component: registry
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }} {{- if .Values.registry.podLabels }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }} {{ toYaml .Values.registry.podLabels | indent 8 }}
checksum/tls: {{ include (print $.Template.BasePath "/registry/registry-tls.yaml") . | sha256sum }} {{- end }}
{{- end }} annotations:
{{- if .Values.registry.podAnnotations }} checksum/configmap: {{ include (print $.Template.BasePath "/registry/registry-cm.yaml") . | sha256sum }}
{{ toYaml .Values.registry.podAnnotations | indent 8 }} checksum/secret: {{ include (print $.Template.BasePath "/registry/registry-secret.yaml") . | sha256sum }}
{{- end }} checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
spec: checksum/secret-core: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
{{- with .Values.global.imagePullSecrets }} {{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
imagePullSecrets: checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- toYaml . | nindent 8 }} {{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
{{- end }} checksum/tls: {{ include (print $.Template.BasePath "/registry/registry-tls.yaml") . | sha256sum }}
securityContext: {{- end }}
fsGroup: 10000 {{- if .Values.registry.podAnnotations }}
{{- if .Values.registry.serviceAccountName }} {{ toYaml .Values.registry.podAnnotations | indent 8 }}
serviceAccountName: {{ .Values.registry.serviceAccountName }} {{- end }}
{{- end -}} spec:
{{- with .Values.imagePullSecrets }} securityContext:
imagePullSecrets: runAsUser: 10000
{{- toYaml . | nindent 8 }} fsGroup: 10000
{{- end }} fsGroupChangePolicy: OnRootMismatch
containers: {{- if .Values.registry.serviceAccountName }}
- name: registry serviceAccountName: {{ .Values.registry.serviceAccountName }}
{{- if contains "/" .Values.registry.registry.image.repository }} {{- end -}}
image: "{{ .Values.registry.registry.image.repository }}" {{- with .Values.imagePullSecrets }}
{{- else }} imagePullSecrets:
image: "{{ .Values.registry.registry.image.hub | default .Values.global.hub }}/{{ .Values.registry.registry.image.repository }}:{{ .Values.registry.registry.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
imagePullPolicy: "{{ .Values.global.imagePullPolicy }}" automountServiceAccountToken: {{ .Values.registry.automountServiceAccountToken | default false }}
livenessProbe: terminationGracePeriodSeconds: 120
httpGet: {{- with .Values.registry.topologySpreadConstraints}}
path: / topologySpreadConstraints:
scheme: {{ include "harbor.component.scheme" . | upper }} {{- range . }}
port: {{ template "harbor.registry.containerPort" . }} - {{ . | toYaml | indent 8 | trim }}
initialDelaySeconds: 300 labelSelector:
periodSeconds: 10 matchLabels:
readinessProbe: {{ include "harbor.matchLabels" $ | indent 12 }}
httpGet: component: registry
path: / {{- end }}
scheme: {{ include "harbor.component.scheme" . | upper }} {{- end }}
port: {{ template "harbor.registry.containerPort" . }} {{- with .Values.registry.initContainers }}
initialDelaySeconds: 1 initContainers:
periodSeconds: 10 {{- toYaml . | nindent 8 }}
{{- if .Values.registry.registry.resources }} {{- end }}
resources: containers:
{{ toYaml .Values.registry.registry.resources | indent 10 }} - name: registry
{{- end }} image: {{ .Values.registry.registry.image.repository }}:{{ .Values.registry.registry.image.tag }}
args: ["serve", "/etc/registry/config.yml"] imagePullPolicy: {{ .Values.imagePullPolicy }}
envFrom: livenessProbe:
- secretRef: httpGet:
name: "{{ template "harbor.registry" . }}" path: /
env: scheme: {{ include "harbor.component.scheme" . | upper }}
{{- if has "registry" .Values.proxy.components }} port: {{ template "harbor.registry.containerPort" . }}
- name: HTTP_PROXY initialDelaySeconds: 300
value: "{{ .Values.proxy.httpProxy }}" periodSeconds: 10
- name: HTTPS_PROXY readinessProbe:
value: "{{ .Values.proxy.httpsProxy }}" httpGet:
- name: NO_PROXY path: /
value: "{{ template "harbor.noProxy" . }}" scheme: {{ include "harbor.component.scheme" . | upper }}
{{- end }} port: {{ template "harbor.registry.containerPort" . }}
{{- if .Values.internalTLS.enabled }} initialDelaySeconds: 1
- name: INTERNAL_TLS_ENABLED periodSeconds: 10
value: "true" {{- if .Values.registry.registry.resources }}
- name: INTERNAL_TLS_KEY_PATH resources:
value: /etc/harbor/ssl/registry/tls.key {{ toYaml .Values.registry.registry.resources | indent 10 }}
- name: INTERNAL_TLS_CERT_PATH {{- end }}
value: /etc/harbor/ssl/registry/tls.crt {{- if not (empty .Values.containerSecurityContext) }}
- name: INTERNAL_TLS_TRUST_CA_PATH securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
value: /etc/harbor/ssl/registry/ca.crt {{- end }}
{{- end }} envFrom:
ports: - secretRef:
- containerPort: {{ template "harbor.registry.containerPort" . }} name: "{{ template "harbor.registry" . }}"
- containerPort: 5001 {{- if .Values.persistence.imageChartStorage.s3.existingSecret }}
volumeMounts: - secretRef:
- name: registry-data name: {{ .Values.persistence.imageChartStorage.s3.existingSecret }}
mountPath: {{ .Values.persistence.imageChartStorage.filesystem.rootdirectory }} {{- end }}
subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }} env:
- name: registry-root-certificate {{- if .Values.registry.existingSecret }}
mountPath: /etc/registry/root.crt - name: REGISTRY_HTTP_SECRET
subPath: tls.crt valueFrom:
- name: registry-htpasswd secretKeyRef:
mountPath: /etc/registry/passwd name: {{ .Values.registry.existingSecret }}
subPath: passwd key: {{ .Values.registry.existingSecretKey }}
- name: registry-config {{- end }}
mountPath: /etc/registry/config.yml {{- if has "registry" .Values.proxy.components }}
subPath: config.yml - name: HTTP_PROXY
{{- if .Values.internalTLS.enabled }} value: "{{ .Values.proxy.httpProxy }}"
- name: registry-internal-certs - name: HTTPS_PROXY
mountPath: /etc/harbor/ssl/registry value: "{{ .Values.proxy.httpsProxy }}"
{{- end }} - name: NO_PROXY
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs") }} value: "{{ template "harbor.noProxy" . }}"
- name: gcs-key {{- end }}
mountPath: /etc/registry/gcs-key.json {{- if .Values.internalTLS.enabled }}
subPath: gcs-key.json - name: INTERNAL_TLS_ENABLED
{{- end }} value: "true"
{{- if .Values.persistence.imageChartStorage.caBundleSecretName }} - name: INTERNAL_TLS_KEY_PATH
- name: storage-service-ca value: /etc/harbor/ssl/registry/tls.key
mountPath: /harbor_cust_cert/custom-ca-bundle.crt - name: INTERNAL_TLS_CERT_PATH
subPath: ca.crt value: /etc/harbor/ssl/registry/tls.crt
{{- end }} - name: INTERNAL_TLS_TRUST_CA_PATH
{{- if .Values.registry.middleware.enabled }} value: /etc/harbor/ssl/registry/ca.crt
{{- if eq .Values.registry.middleware.type "cloudFront" }} {{- end }}
- name: cloudfront-key {{- if .Values.redis.external.existingSecret }}
mountPath: /etc/registry/pk.pem - name: REGISTRY_REDIS_PASSWORD
subPath: pk.pem valueFrom:
{{- end }} secretKeyRef:
{{- end }} name: {{ .Values.redis.external.existingSecret }}
{{- if .Values.caBundleSecretName }} key: REDIS_PASSWORD
{{ include "harbor.caBundleVolumeMount" . | indent 8 }} {{- end }}
{{- end }} {{- if .Values.persistence.imageChartStorage.azure.existingSecret }}
- name: registryctl - name: REGISTRY_STORAGE_AZURE_ACCOUNTKEY
{{- if contains "/" .Values.registry.controller.image.repository }} valueFrom:
image: "{{ .Values.registry.controller.image.repository }}" secretKeyRef:
{{- else }} name: {{ .Values.persistence.imageChartStorage.azure.existingSecret }}
image: "{{ .Values.registry.controller.image.hub | default .Values.global.hub }}/{{ .Values.registry.controller.image.repository }}:{{ .Values.registry.controller.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" key: AZURE_STORAGE_ACCESS_KEY
{{- end }} {{- end }}
imagePullPolicy: "{{ .Values.global.imagePullPolicy }}" {{- if .Values.persistence.imageChartStorage.swift.existingSecret }}
livenessProbe: - name: REGISTRY_STORAGE_SWIFT_PASSWORD
httpGet: valueFrom:
path: /api/health secretKeyRef:
scheme: {{ include "harbor.component.scheme" . | upper }} name: {{ .Values.persistence.imageChartStorage.swift.existingSecret }}
port: {{ template "harbor.registryctl.containerPort" . }} key: REGISTRY_STORAGE_SWIFT_PASSWORD
initialDelaySeconds: 300 - name: REGISTRY_STORAGE_SWIFT_SECRETKEY
periodSeconds: 10 valueFrom:
readinessProbe: secretKeyRef:
httpGet: name: {{ .Values.persistence.imageChartStorage.swift.existingSecret }}
path: /api/health key: REGISTRY_STORAGE_SWIFT_SECRETKEY
scheme: {{ include "harbor.component.scheme" . | upper }} optional: true
port: {{ template "harbor.registryctl.containerPort" . }} - name: REGISTRY_STORAGE_SWIFT_ACCESSKEY
initialDelaySeconds: 1 valueFrom:
periodSeconds: 10 secretKeyRef:
{{- if .Values.registry.controller.resources }} name: {{ .Values.persistence.imageChartStorage.swift.existingSecret }}
resources: key: REGISTRY_STORAGE_SWIFT_ACCESSKEY
{{ toYaml .Values.registry.controller.resources | indent 10 }} optional: true
{{- end }} {{- end }}
envFrom: {{- if .Values.persistence.imageChartStorage.oss.existingSecret }}
- secretRef: - name: REGISTRY_STORAGE_OSS_ACCESSKEYSECRET
name: "{{ template "harbor.registry" . }}" valueFrom:
env: secretKeyRef:
- name: CORE_SECRET name: {{ .Values.persistence.imageChartStorage.oss.existingSecret }}
valueFrom: key: REGISTRY_STORAGE_OSS_ACCESSKEYSECRET
secretKeyRef: optional: true
name: {{ template "harbor.core" . }} {{- end}}
key: secret {{- with .Values.registry.registry.extraEnvVars }}
- name: JOBSERVICE_SECRET {{- toYaml . | nindent 8 }}
valueFrom: {{- end }}
secretKeyRef: ports:
name: {{ template "harbor.jobservice" . }} - containerPort: {{ template "harbor.registry.containerPort" . }}
key: JOBSERVICE_SECRET - containerPort: {{ ternary .Values.metrics.registry.port 5001 .Values.metrics.enabled }}
{{- if .Values.internalTLS.enabled }} volumeMounts:
- name: INTERNAL_TLS_ENABLED - name: registry-data
value: "true" mountPath: {{ .Values.persistence.imageChartStorage.filesystem.rootdirectory }}
- name: INTERNAL_TLS_KEY_PATH subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }}
value: /etc/harbor/ssl/registry/tls.key - name: registry-htpasswd
- name: INTERNAL_TLS_CERT_PATH mountPath: /etc/registry/passwd
value: /etc/harbor/ssl/registry/tls.crt subPath: passwd
- name: INTERNAL_TLS_TRUST_CA_PATH - name: registry-config
value: /etc/harbor/ssl/registry/ca.crt mountPath: /etc/registry/config.yml
{{- end }} subPath: config.yml
ports: {{- if .Values.internalTLS.enabled }}
- containerPort: {{ template "harbor.registryctl.containerPort" . }} - name: registry-internal-certs
volumeMounts: mountPath: /etc/harbor/ssl/registry
- name: registry-data {{- end }}
mountPath: {{ .Values.persistence.imageChartStorage.filesystem.rootdirectory }} {{- if and (and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs")) (not .Values.persistence.imageChartStorage.gcs.useWorkloadIdentity) }}
subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }} - name: gcs-key
- name: registry-config mountPath: /etc/registry/gcs-key.json
mountPath: /etc/registry/config.yml subPath: gcs-key.json
subPath: config.yml {{- end }}
- name: registry-config {{- if .Values.persistence.imageChartStorage.caBundleSecretName }}
mountPath: /etc/registryctl/config.yml - name: storage-service-ca
subPath: ctl-config.yml mountPath: /harbor_cust_cert/custom-ca-bundle.crt
{{- if .Values.internalTLS.enabled }} subPath: ca.crt
- name: registry-internal-certs {{- end }}
mountPath: /etc/harbor/ssl/registry {{- if .Values.registry.middleware.enabled }}
{{- end }} {{- if eq .Values.registry.middleware.type "cloudFront" }}
{{- if .Values.persistence.imageChartStorage.caBundleSecretName }} - name: cloudfront-key
- name: storage-service-ca mountPath: /etc/registry/pk.pem
mountPath: /harbor_cust_cert/custom-ca-bundle.crt subPath: pk.pem
subPath: ca.crt {{- end }}
{{- end }} {{- end }}
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs") }} {{- if .Values.caBundleSecretName }}
- name: gcs-key {{ include "harbor.caBundleVolumeMount" . | indent 8 }}
mountPath: /etc/registry/gcs-key.json {{- end }}
subPath: gcs-key.json - name: registryctl
{{- end }} image: {{ .Values.registry.controller.image.repository }}:{{ .Values.registry.controller.image.tag }}
{{- if .Values.caBundleSecretName }} imagePullPolicy: {{ .Values.imagePullPolicy }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }} livenessProbe:
{{- end }} httpGet:
volumes: path: /api/health
- name: registry-htpasswd scheme: {{ include "harbor.component.scheme" . | upper }}
secret: port: {{ template "harbor.registryctl.containerPort" . }}
secretName: {{ template "harbor.registry" . }} initialDelaySeconds: 300
items: periodSeconds: 10
- key: REGISTRY_HTPASSWD readinessProbe:
path: passwd httpGet:
- name: registry-root-certificate path: /api/health
secret: scheme: {{ include "harbor.component.scheme" . | upper }}
{{- if .Values.core.secretName }} port: {{ template "harbor.registryctl.containerPort" . }}
secretName: {{ .Values.core.secretName }} initialDelaySeconds: 1
{{- else }} periodSeconds: 10
secretName: {{ template "harbor.core" . }} {{- if .Values.registry.controller.resources }}
{{- end }} resources:
- name: registry-config {{ toYaml .Values.registry.controller.resources | indent 10 }}
configMap: {{- end }}
name: "{{ template "harbor.registry" . }}" {{- if not (empty .Values.containerSecurityContext) }}
- name: registry-data securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "filesystem") }} {{- end }}
persistentVolumeClaim: envFrom:
claimName: {{ .Values.persistence.persistentVolumeClaim.registry.existingClaim | default (include "harbor.registry" .) }} - configMapRef:
{{- else }} name: "{{ template "harbor.registryCtl" . }}"
emptyDir: {} - secretRef:
{{- end }} name: "{{ template "harbor.registry" . }}"
{{- if .Values.internalTLS.enabled }} - secretRef:
- name: registry-internal-certs name: "{{ template "harbor.registryCtl" . }}"
secret: {{- if .Values.persistence.imageChartStorage.s3.existingSecret }}
secretName: {{ template "harbor.internalTLS.registry.secretName" . }} - secretRef:
{{- end }} name: {{ .Values.persistence.imageChartStorage.s3.existingSecret }}
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs") }} {{- end }}
- name: gcs-key env:
secret: {{- if .Values.registry.existingSecret }}
secretName: {{ template "harbor.registry" . }} - name: REGISTRY_HTTP_SECRET
items: valueFrom:
- key: GCS_KEY_DATA secretKeyRef:
path: gcs-key.json name: {{ .Values.registry.existingSecret }}
{{- end }} key: {{ .Values.registry.existingSecretKey }}
{{- if .Values.persistence.imageChartStorage.caBundleSecretName }} {{- end }}
- name: storage-service-ca - name: CORE_SECRET
secret: valueFrom:
secretName: {{ .Values.persistence.imageChartStorage.caBundleSecretName }} secretKeyRef:
{{- end }} name: {{ default (include "harbor.core" .) .Values.core.existingSecret }}
{{- if .Values.registry.middleware.enabled }} key: secret
{{- if eq .Values.registry.middleware.type "cloudFront" }} - name: JOBSERVICE_SECRET
- name: cloudfront-key valueFrom:
secret: secretKeyRef:
secretName: {{ .Values.registry.middleware.cloudFront.privateKeySecret }} name: {{ default (include "harbor.jobservice" .) .Values.jobservice.existingSecret }}
items: {{- if .Values.jobservice.existingSecret }}
- key: CLOUDFRONT_KEY_DATA key: {{ .Values.jobservice.existingSecretKey }}
path: pk.pem {{- else }}
{{- end }} key: JOBSERVICE_SECRET
{{- end }} {{- end }}
{{- if .Values.caBundleSecretName }} {{- if has "registry" .Values.proxy.components }}
{{ include "harbor.caBundleVolume" . | indent 6 }} - name: HTTP_PROXY
{{- end }} value: "{{ .Values.proxy.httpProxy }}"
{{- with .Values.registry.nodeSelector }} - name: HTTPS_PROXY
nodeSelector: value: "{{ .Values.proxy.httpsProxy }}"
{{ toYaml . | indent 8 }} - name: NO_PROXY
{{- end }} value: "{{ template "harbor.noProxy" . }}"
{{- with .Values.registry.affinity }} {{- end }}
affinity: {{- if .Values.internalTLS.enabled }}
{{ toYaml . | indent 8 }} - name: INTERNAL_TLS_ENABLED
{{- end }} value: "true"
{{- with .Values.registry.tolerations }} - name: INTERNAL_TLS_KEY_PATH
tolerations: value: /etc/harbor/ssl/registry/tls.key
{{ toYaml . | indent 8 }} - name: INTERNAL_TLS_CERT_PATH
{{- end }} value: /etc/harbor/ssl/registry/tls.crt
- name: INTERNAL_TLS_TRUST_CA_PATH
value: /etc/harbor/ssl/registry/ca.crt
{{- end }}
{{- if .Values.redis.external.existingSecret }}
- name: REGISTRY_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.redis.external.existingSecret }}
key: REDIS_PASSWORD
{{- end }}
{{- if .Values.persistence.imageChartStorage.azure.existingSecret }}
- name: REGISTRY_STORAGE_AZURE_ACCOUNTKEY
valueFrom:
secretKeyRef:
name: {{ .Values.persistence.imageChartStorage.azure.existingSecret }}
key: AZURE_STORAGE_ACCESS_KEY
{{- end }}
{{- if .Values.persistence.imageChartStorage.swift.existingSecret }}
- name: REGISTRY_STORAGE_SWIFT_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.persistence.imageChartStorage.swift.existingSecret }}
key: REGISTRY_STORAGE_SWIFT_PASSWORD
- name: REGISTRY_STORAGE_SWIFT_SECRETKEY
valueFrom:
secretKeyRef:
name: {{ .Values.persistence.imageChartStorage.swift.existingSecret }}
key: REGISTRY_STORAGE_SWIFT_SECRETKEY
optional: true
- name: REGISTRY_STORAGE_SWIFT_ACCESSKEY
valueFrom:
secretKeyRef:
name: {{ .Values.persistence.imageChartStorage.swift.existingSecret }}
key: REGISTRY_STORAGE_SWIFT_ACCESSKEY
optional: true
{{- end }}
{{- if .Values.persistence.imageChartStorage.oss.existingSecret }}
- name: REGISTRY_STORAGE_OSS_ACCESSKEYSECRET
valueFrom:
secretKeyRef:
name: {{ .Values.persistence.imageChartStorage.oss.existingSecret }}
key: REGISTRY_STORAGE_OSS_ACCESSKEYSECRET
optional: true
{{- end}}
{{- with .Values.registry.controller.extraEnvVars }}
{{- toYaml . | nindent 8 }}
{{- end }}
ports:
- containerPort: {{ template "harbor.registryctl.containerPort" . }}
volumeMounts:
- name: registry-data
mountPath: {{ .Values.persistence.imageChartStorage.filesystem.rootdirectory }}
subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }}
- name: registry-config
mountPath: /etc/registry/config.yml
subPath: config.yml
- name: registry-config
mountPath: /etc/registryctl/config.yml
subPath: ctl-config.yml
{{- if .Values.internalTLS.enabled }}
- name: registry-internal-certs
mountPath: /etc/harbor/ssl/registry
{{- end }}
{{- if .Values.persistence.imageChartStorage.caBundleSecretName }}
- name: storage-service-ca
mountPath: /harbor_cust_cert/custom-ca-bundle.crt
subPath: ca.crt
{{- end }}
{{- if and (and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs")) (not .Values.persistence.imageChartStorage.gcs.useWorkloadIdentity ) }}
- name: gcs-key
mountPath: /etc/registry/gcs-key.json
subPath: gcs-key.json
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
volumes:
- name: registry-htpasswd
secret:
{{- if not .Values.registry.credentials.existingSecret }}
secretName: {{ template "harbor.registry" . }}-htpasswd
{{ else }}
secretName: {{ .Values.registry.credentials.existingSecret }}
{{- end }}
items:
- key: REGISTRY_HTPASSWD
path: passwd
- name: registry-config
configMap:
name: "{{ template "harbor.registry" . }}"
- name: registry-data
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "filesystem") }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.persistentVolumeClaim.registry.existingClaim | default (include "harbor.registry" .) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: registry-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.registry.secretName" . }}
{{- end }}
{{- if and (and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs")) (not .Values.persistence.imageChartStorage.gcs.useWorkloadIdentity ) }}
- name: gcs-key
secret:
{{- if and (eq $type "gcs") $storage.gcs.existingSecret }}
secretName: {{ $storage.gcs.existingSecret }}
{{- else }}
secretName: {{ template "harbor.registry" . }}
{{- end }}
items:
- key: GCS_KEY_DATA
path: gcs-key.json
{{- end }}
{{- if .Values.persistence.imageChartStorage.caBundleSecretName }}
- name: storage-service-ca
secret:
secretName: {{ .Values.persistence.imageChartStorage.caBundleSecretName }}
{{- end }}
{{- if .Values.registry.middleware.enabled }}
{{- if eq .Values.registry.middleware.type "cloudFront" }}
- name: cloudfront-key
secret:
secretName: {{ .Values.registry.middleware.cloudFront.privateKeySecret }}
items:
- key: CLOUDFRONT_KEY_DATA
path: pk.pem
{{- end }}
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- with .Values.registry.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.registry.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.registry.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.registry.priorityClassName }}
priorityClassName: {{ .Values.registry.priorityClassName }}
{{- end }}
{{- if .Values.persistence.enabled }} {{- if .Values.persistence.enabled }}
{{- $registry := .Values.persistence.persistentVolumeClaim.registry -}} {{- $registry := .Values.persistence.persistentVolumeClaim.registry -}}
{{- if and (not $registry.existingClaim) (eq .Values.persistence.imageChartStorage.type "filesystem") }} {{- if and (not $registry.existingClaim) (eq .Values.persistence.imageChartStorage.type "filesystem") }}
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
apiVersion: v1 apiVersion: v1
metadata: metadata:
name: {{ template "harbor.registry" . }} name: {{ template "harbor.registry" . }}
{{- if eq .Values.persistence.resourcePolicy "keep" }} namespace: {{ .Release.Namespace | quote }}
annotations: annotations:
helm.sh/resource-policy: keep {{- range $key, $value := $registry.annotations }}
{{- end }} {{ $key }}: {{ $value | quote }}
labels: {{- end }}
{{ include "harbor.labels" . | indent 4 }} {{- if eq .Values.persistence.resourcePolicy "keep" }}
component: registry helm.sh/resource-policy: keep
spec: {{- end }}
accessModes: labels:
- {{ $registry.accessMode }} {{ include "harbor.labels" . | indent 4 }}
resources: component: registry
requests: app.kubernetes.io/component: registry
storage: {{ $registry.size }} spec:
{{- if $registry.storageClass }} accessModes:
{{- if eq "-" $registry.storageClass }} - {{ $registry.accessMode }}
storageClassName: "" resources:
{{- else }} requests:
storageClassName: {{ $registry.storageClass }} storage: {{ $registry.size }}
{{- end }} {{- if $registry.storageClass }}
{{- end }} {{- if eq "-" $registry.storageClass }}
{{- end }} storageClassName: ""
{{- end }} {{- else }}
\ No newline at end of file storageClassName: {{ $registry.storageClass }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
apiVersion: v1 {{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (include "harbor.registry" .) }}
kind: Secret apiVersion: v1
metadata: kind: Secret
name: "{{ template "harbor.registry" . }}" metadata:
labels: name: "{{ template "harbor.registry" . }}"
{{ include "harbor.labels" . | indent 4 }} namespace: {{ .Release.Namespace | quote }}
type: Opaque labels:
data: {{ include "harbor.labels" . | indent 4 }}
REGISTRY_HTPASSWD: {{ .Values.registry.credentials.htpasswd | b64enc | quote }} type: Opaque
REGISTRY_HTTP_SECRET: {{ .Values.registry.secret | default (randAlphaNum 16) | b64enc | quote }} data:
REGISTRY_REDIS_PASSWORD: {{ (include "harbor.redis.password" .) | b64enc | quote }} {{- if not .Values.registry.existingSecret }}
{{- $storage := .Values.persistence.imageChartStorage }} REGISTRY_HTTP_SECRET: {{ .Values.registry.secret | default (include "harbor.secretKeyHelper" (dict "key" "REGISTRY_HTTP_SECRET" "data" $existingSecret.data)) | default (randAlphaNum 16) | b64enc | quote }}
{{- $type := $storage.type }} {{- end }}
{{- if eq $type "azure" }} {{- if not .Values.redis.external.existingSecret }}
REGISTRY_STORAGE_AZURE_ACCOUNTKEY: {{ $storage.azure.accountkey | b64enc | quote }} REGISTRY_REDIS_PASSWORD: {{ include "harbor.redis.password" . | b64enc | quote }}
{{- else if eq $type "gcs" }} {{- end }}
GCS_KEY_DATA: {{ $storage.gcs.encodedkey | quote }} {{- $storage := .Values.persistence.imageChartStorage }}
{{- else if eq $type "s3" }} {{- $type := $storage.type }}
{{- if $storage.s3.accesskey }} {{- if and (eq $type "azure") (not $storage.azure.existingSecret) }}
REGISTRY_STORAGE_S3_ACCESSKEY: {{ $storage.s3.accesskey | b64enc | quote }} REGISTRY_STORAGE_AZURE_ACCOUNTKEY: {{ $storage.azure.accountkey | b64enc | quote }}
{{- end }} {{- else if and (and (eq $type "gcs") (not $storage.gcs.existingSecret)) (not $storage.gcs.useWorkloadIdentity) }}
{{- if $storage.s3.secretkey }} GCS_KEY_DATA: {{ $storage.gcs.encodedkey | quote }}
REGISTRY_STORAGE_S3_SECRETKEY: {{ $storage.s3.secretkey | b64enc | quote }} {{- else if eq $type "s3" }}
{{- end }} {{- if and (not $storage.s3.existingSecret) ($storage.s3.accesskey) }}
{{- else if eq $type "swift" }} REGISTRY_STORAGE_S3_ACCESSKEY: {{ $storage.s3.accesskey | b64enc | quote }}
REGISTRY_STORAGE_SWIFT_PASSWORD: {{ $storage.swift.password | b64enc | quote }} {{- end }}
{{- if $storage.swift.secretkey }} {{- if and (not $storage.s3.existingSecret) ($storage.s3.secretkey) }}
REGISTRY_STORAGE_SWIFT_SECRETKEY: {{ $storage.swift.secretkey | b64enc | quote }} REGISTRY_STORAGE_S3_SECRETKEY: {{ $storage.s3.secretkey | b64enc | quote }}
{{- end }} {{- end }}
{{- if $storage.swift.accesskey }} {{- else if and (eq $type "swift") (not ($storage.swift.existingSecret)) }}
REGISTRY_STORAGE_SWIFT_ACCESSKEY: {{ $storage.swift.accesskey | b64enc | quote }} REGISTRY_STORAGE_SWIFT_PASSWORD: {{ $storage.swift.password | b64enc | quote }}
{{- end }} {{- if $storage.swift.secretkey }}
{{- else if eq $type "oss" }} REGISTRY_STORAGE_SWIFT_SECRETKEY: {{ $storage.swift.secretkey | b64enc | quote }}
REGISTRY_STORAGE_OSS_ACCESSKEYSECRET: {{ $storage.oss.accesskeysecret | b64enc | quote }} {{- end }}
{{- end }} {{- if $storage.swift.accesskey }}
REGISTRY_STORAGE_SWIFT_ACCESSKEY: {{ $storage.swift.accesskey | b64enc | quote }}
{{- end }}
{{- else if and (eq $type "oss") ((not ($storage.oss.existingSecret))) }}
REGISTRY_STORAGE_OSS_ACCESSKEYSECRET: {{ $storage.oss.accesskeysecret | b64enc | quote }}
{{- end }}
{{- if not .Values.registry.credentials.existingSecret }}
---
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.registry" . }}-htpasswd"
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
{{- if .Values.registry.credentials.htpasswdString }}
REGISTRY_HTPASSWD: {{ .Values.registry.credentials.htpasswdString | b64enc | quote }}
{{- else }}
REGISTRY_HTPASSWD: {{ htpasswd .Values.registry.credentials.username .Values.registry.credentials.password | b64enc | quote }}
{{- end }}
{{- end }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: "{{ template "harbor.registry" . }}" name: "{{ template "harbor.registry" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
ports: spec:
- name: registry ports:
port: {{ template "harbor.registry.servicePort" . }} - name: {{ ternary "https-registry" "http-registry" .Values.internalTLS.enabled }}
- name: controller port: {{ template "harbor.registry.servicePort" . }}
port: {{ template "harbor.registryctl.servicePort" . }}
selector: - name: {{ ternary "https-controller" "http-controller" .Values.internalTLS.enabled }}
{{ include "harbor.matchLabels" . | indent 4 }} port: {{ template "harbor.registryctl.servicePort" . }}
component: registry {{- if .Values.metrics.enabled}}
\ No newline at end of file - name: {{ template "harbor.metricsPortName" . }}
port: {{ .Values.metrics.registry.port }}
{{- end }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: registry
{{- if and .Values.internalTLS.enabled }} {{- if and .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }} {{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.internalTLS.registry.secretName" . }}" name: "{{ template "harbor.internalTLS.registry.secretName" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: kubernetes.io/tls {{ include "harbor.labels" . | indent 4 }}
data: type: kubernetes.io/tls
ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }} data:
tls.crt: {{ (required "The \"internalTLS.registry.crt\" is required!" .Values.internalTLS.registry.crt) | b64enc | quote }} ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.registry.key\" is required!" .Values.internalTLS.registry.key) | b64enc | quote }} tls.crt: {{ (required "The \"internalTLS.registry.crt\" is required!" .Values.internalTLS.registry.crt) | b64enc | quote }}
{{- end }} tls.key: {{ (required "The \"internalTLS.registry.key\" is required!" .Values.internalTLS.registry.key) | b64enc | quote }}
{{- end }} {{- end }}
\ No newline at end of file {{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.registryCtl" . }}"
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
{{- template "harbor.traceEnvsForRegistryCtl" . }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.registryCtl" . }}"
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
{{- template "harbor.traceJaegerPassword" . }}
{{- if .Values.trivy.enabled }} {{- if .Values.trivy.enabled }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: {{ template "harbor.trivy" . }} name: {{ template "harbor.trivy" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: Opaque {{ include "harbor.labels" . | indent 4 }}
data: type: Opaque
redisURL: {{ include "harbor.redis.urlForTrivy" . | b64enc }} data:
gitHubToken: {{ .Values.trivy.gitHubToken | default "" | b64enc | quote }} redisURL: {{ include "harbor.redis.urlForTrivy" . | b64enc }}
{{- end }} gitHubToken: {{ .Values.trivy.gitHubToken | default "" | b64enc | quote }}
{{- end }}
{{- if .Values.trivy.enabled }} {{- if .Values.trivy.enabled }}
{{- $trivy := .Values.persistence.persistentVolumeClaim.trivy }} {{- $trivy := .Values.persistence.persistentVolumeClaim.trivy }}
apiVersion: apps/v1 apiVersion: apps/v1
kind: StatefulSet kind: StatefulSet
metadata: metadata:
name: {{ template "harbor.trivy" . }} name: {{ template "harbor.trivy" . }}
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
component: trivy {{ include "harbor.labels" . | indent 4 }}
spec: component: trivy
replicas: {{ .Values.trivy.replicas }} app.kubernetes.io/component: trivy
serviceName: {{ template "harbor.trivy" . }} spec:
selector: replicas: {{ .Values.trivy.replicas }}
matchLabels: serviceName: {{ template "harbor.trivy" . }}
{{ include "harbor.matchLabels" . | indent 6 }} selector:
component: trivy matchLabels:
template: {{ include "harbor.matchLabels" . | indent 6 }}
metadata: component: trivy
labels: template:
{{ include "harbor.labels" . | indent 8 }} metadata:
component: trivy labels:
annotations: {{ include "harbor.labels" . | indent 8 }}
checksum/secret: {{ include (print $.Template.BasePath "/trivy/trivy-secret.yaml") . | sha256sum }} component: trivy
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }} app.kubernetes.io/component: trivy
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }} {{- if .Values.trivy.podLabels }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }} {{ toYaml .Values.trivy.podLabels | indent 8 }}
checksum/tls: {{ include (print $.Template.BasePath "/trivy/trivy-tls.yaml") . | sha256sum }} {{- end }}
{{- end }} annotations:
{{- if .Values.trivy.podAnnotations }} checksum/secret: {{ include (print $.Template.BasePath "/trivy/trivy-secret.yaml") . | sha256sum }}
{{ toYaml .Values.trivy.podAnnotations | indent 8 }} {{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
{{- end }} checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
spec: {{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
{{- with .Values.global.imagePullSecrets }} checksum/tls: {{ include (print $.Template.BasePath "/trivy/trivy-tls.yaml") . | sha256sum }}
imagePullSecrets: {{- end }}
{{- toYaml . | nindent 8 }} {{- if .Values.trivy.podAnnotations }}
{{- end }} {{ toYaml .Values.trivy.podAnnotations | indent 8 }}
{{- with .Values.imagePullSecrets }} {{- end }}
imagePullSecrets: spec:
{{- toYaml . | nindent 8 }} {{- with .Values.imagePullSecrets }}
{{- end }} imagePullSecrets:
{{- if .Values.trivy.serviceAccountName }} {{- toYaml . | nindent 8 }}
serviceAccountName: {{ .Values.trivy.serviceAccountName }} {{- end }}
{{- end }} {{- if .Values.trivy.serviceAccountName }}
securityContext: serviceAccountName: {{ .Values.trivy.serviceAccountName }}
runAsNonRoot: true {{- end }}
runAsUser: 10000 securityContext:
fsGroup: 10000 runAsUser: 10000
automountServiceAccountToken: false fsGroup: 10000
containers: automountServiceAccountToken: {{ .Values.trivy.automountServiceAccountToken | default false }}
- name: trivy {{- with .Values.trivy.topologySpreadConstraints}}
{{- if contains "/" .Values.trivy.image.repository }} topologySpreadConstraints:
image: "{{ .Values.trivy.image.repository }}" {{- range . }}
{{- else }} - {{ . | toYaml | indent 8 | trim }}
image: "{{ .Values.trivy.image.hub | default .Values.global.hub }}/{{ .Values.trivy.image.repository }}:{{ .Values.trivy.image.tag | default .Values.global.tag }}{{ template ".beagle.imageArch" . }}" labelSelector:
{{- end }} matchLabels:
imagePullPolicy: "{{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}" {{ include "harbor.matchLabels" $ | indent 12 }}
securityContext: component: trivy
privileged: false {{- end }}
allowPrivilegeEscalation: false {{- end }}
env: {{- with .Values.trivy.initContainers }}
{{- if has "trivy" .Values.proxy.components }} initContainers:
- name: HTTP_PROXY {{- toYaml . | nindent 8 }}
value: "{{ .Values.proxy.httpProxy }}" {{- end }}
- name: HTTPS_PROXY containers:
value: "{{ .Values.proxy.httpsProxy }}" - name: trivy
- name: NO_PROXY image: {{ .Values.trivy.image.repository }}:{{ .Values.trivy.image.tag }}
value: "{{ template "harbor.noProxy" . }}" imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- end }} {{- if not (empty .Values.containerSecurityContext) }}
- name: "SCANNER_LOG_LEVEL" securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 12 }}
value: {{ .Values.logLevel | quote }} {{- end }}
- name: "SCANNER_TRIVY_CACHE_DIR" env:
value: "/home/scanner/.cache/trivy" {{- if has "trivy" .Values.proxy.components }}
- name: "SCANNER_TRIVY_REPORTS_DIR" - name: HTTP_PROXY
value: "/home/scanner/.cache/reports" value: "{{ .Values.proxy.httpProxy }}"
- name: "SCANNER_TRIVY_DEBUG_MODE" - name: HTTPS_PROXY
value: {{ .Values.trivy.debugMode | quote }} value: "{{ .Values.proxy.httpsProxy }}"
- name: "SCANNER_TRIVY_VULN_TYPE" - name: NO_PROXY
value: {{ .Values.trivy.vulnType | quote }} value: "{{ template "harbor.noProxy" . }}"
- name: "SCANNER_TRIVY_GITHUB_TOKEN" {{- end }}
valueFrom: - name: "SCANNER_LOG_LEVEL"
secretKeyRef: value: {{ .Values.logLevel | quote }}
name: {{ template "harbor.trivy" . }} - name: "SCANNER_TRIVY_CACHE_DIR"
key: gitHubToken value: "/home/scanner/.cache/trivy"
- name: "SCANNER_TRIVY_SEVERITY" - name: "SCANNER_TRIVY_REPORTS_DIR"
value: {{ .Values.trivy.severity | quote }} value: "/home/scanner/.cache/reports"
- name: "SCANNER_TRIVY_IGNORE_UNFIXED" - name: "SCANNER_TRIVY_DEBUG_MODE"
value: {{ .Values.trivy.ignoreUnfixed | default false | quote }} value: {{ .Values.trivy.debugMode | quote }}
- name: "SCANNER_TRIVY_SKIP_UPDATE" - name: "SCANNER_TRIVY_VULN_TYPE"
value: {{ .Values.trivy.skipUpdate | default false | quote }} value: {{ .Values.trivy.vulnType | quote }}
- name: "SCANNER_TRIVY_INSECURE" - name: "SCANNER_TRIVY_TIMEOUT"
value: {{ .Values.trivy.insecure | default false | quote }} value: {{ .Values.trivy.timeout | quote }}
- name: SCANNER_API_SERVER_ADDR - name: "SCANNER_TRIVY_GITHUB_TOKEN"
value: ":{{ template "harbor.trivy.containerPort" . }}" valueFrom:
{{- if .Values.internalTLS.enabled }} secretKeyRef:
- name: INTERNAL_TLS_ENABLED name: {{ template "harbor.trivy" . }}
value: "true" key: gitHubToken
- name: SCANNER_API_SERVER_TLS_KEY - name: "SCANNER_TRIVY_SEVERITY"
value: /etc/harbor/ssl/trivy/tls.key value: {{ .Values.trivy.severity | quote }}
- name: SCANNER_API_SERVER_TLS_CERTIFICATE - name: "SCANNER_TRIVY_IGNORE_UNFIXED"
value: /etc/harbor/ssl/trivy/tls.crt value: {{ .Values.trivy.ignoreUnfixed | default false | quote }}
{{- end }} - name: "SCANNER_TRIVY_SKIP_UPDATE"
- name: "SCANNER_REDIS_URL" value: {{ .Values.trivy.skipUpdate | default false | quote }}
valueFrom: - name: "SCANNER_TRIVY_SKIP_JAVA_DB_UPDATE"
secretKeyRef: value: {{ .Values.trivy.skipJavaDBUpdate | default false | quote }}
name: {{ template "harbor.trivy" . }} - name: "SCANNER_TRIVY_OFFLINE_SCAN"
key: redisURL value: {{ .Values.trivy.offlineScan | default false | quote }}
- name: "SCANNER_STORE_REDIS_URL" - name: "SCANNER_TRIVY_SECURITY_CHECKS"
valueFrom: value: {{ .Values.trivy.securityCheck | quote }}
secretKeyRef: - name: "SCANNER_TRIVY_INSECURE"
name: {{ template "harbor.trivy" . }} value: {{ .Values.trivy.insecure | default false | quote }}
key: redisURL - name: SCANNER_API_SERVER_ADDR
- name: "SCANNER_JOB_QUEUE_REDIS_URL" value: ":{{ template "harbor.trivy.containerPort" . }}"
valueFrom: {{- if .Values.internalTLS.enabled }}
secretKeyRef: - name: INTERNAL_TLS_ENABLED
name: {{ template "harbor.trivy" . }} value: "true"
key: redisURL - name: SCANNER_API_SERVER_TLS_KEY
ports: value: /etc/harbor/ssl/trivy/tls.key
- name: api-server - name: SCANNER_API_SERVER_TLS_CERTIFICATE
containerPort: {{ template "harbor.trivy.containerPort" . }} value: /etc/harbor/ssl/trivy/tls.crt
volumeMounts: {{- end }}
- name: data - name: "SCANNER_REDIS_URL"
mountPath: /home/scanner/.cache valueFrom:
subPath: {{ .Values.persistence.persistentVolumeClaim.trivy.subPath }} secretKeyRef:
readOnly: false name: {{ template "harbor.trivy" . }}
{{- if .Values.internalTLS.enabled }} key: redisURL
- name: trivy-internal-certs - name: "SCANNER_STORE_REDIS_URL"
mountPath: /etc/harbor/ssl/trivy valueFrom:
{{- end }} secretKeyRef:
{{- if .Values.caBundleSecretName }} name: {{ template "harbor.trivy" . }}
{{ include "harbor.caBundleVolumeMount" . | indent 10 }} key: redisURL
{{- end }} - name: "SCANNER_JOB_QUEUE_REDIS_URL"
livenessProbe: valueFrom:
httpGet: secretKeyRef:
scheme: {{ include "harbor.component.scheme" . | upper }} name: {{ template "harbor.trivy" . }}
path: /probe/healthy key: redisURL
port: api-server {{- with .Values.trivy.extraEnvVars }}
initialDelaySeconds: 5 {{- toYaml . | nindent 12 }}
periodSeconds: 10 {{- end }}
successThreshold: 1 ports:
failureThreshold: 10 - name: api-server
readinessProbe: containerPort: {{ template "harbor.trivy.containerPort" . }}
httpGet: volumeMounts:
scheme: {{ include "harbor.component.scheme" . | upper }} - name: data
path: /probe/ready mountPath: /home/scanner/.cache
port: api-server subPath: {{ .Values.persistence.persistentVolumeClaim.trivy.subPath }}
initialDelaySeconds: 5 readOnly: false
periodSeconds: 10 {{- if .Values.internalTLS.enabled }}
successThreshold: 1 - name: trivy-internal-certs
failureThreshold: 3 mountPath: /etc/harbor/ssl/trivy
resources: {{- end }}
{{ toYaml .Values.trivy.resources | indent 12 }} {{- if .Values.caBundleSecretName }}
{{- if or (or .Values.internalTLS.enabled .Values.caBundleSecretName) (or (not .Values.persistence.enabled) $trivy.existingClaim) }} {{ include "harbor.caBundleVolumeMount" . | indent 10 }}
volumes: {{- end }}
{{- if .Values.internalTLS.enabled }} livenessProbe:
- name: trivy-internal-certs httpGet:
secret: scheme: {{ include "harbor.component.scheme" . | upper }}
secretName: {{ template "harbor.internalTLS.trivy.secretName" . }} path: /probe/healthy
{{- end }} port: api-server
{{- if .Values.caBundleSecretName }} initialDelaySeconds: 5
{{ include "harbor.caBundleVolume" . | indent 6 }} periodSeconds: 10
{{- end }} successThreshold: 1
{{- if not .Values.persistence.enabled }} failureThreshold: 10
- name: "data" readinessProbe:
emptyDir: {} httpGet:
{{- else if $trivy.existingClaim }} scheme: {{ include "harbor.component.scheme" . | upper }}
- name: "data" path: /probe/ready
persistentVolumeClaim: port: api-server
claimName: {{ $trivy.existingClaim }} initialDelaySeconds: 5
{{- end }} periodSeconds: 10
{{- end }} successThreshold: 1
{{- with .Values.trivy.nodeSelector }} failureThreshold: 3
nodeSelector: resources:
{{ toYaml . | indent 8 }} {{ toYaml .Values.trivy.resources | indent 12 }}
{{- end }} {{- if or (or .Values.internalTLS.enabled .Values.caBundleSecretName) (or (not .Values.persistence.enabled) $trivy.existingClaim) }}
{{- with .Values.trivy.affinity }} volumes:
affinity: {{- if .Values.internalTLS.enabled }}
{{ toYaml . | indent 8 }} - name: trivy-internal-certs
{{- end }} secret:
{{- with .Values.trivy.tolerations }} secretName: {{ template "harbor.internalTLS.trivy.secretName" . }}
tolerations: {{- end }}
{{ toYaml . | indent 8 }} {{- if .Values.caBundleSecretName }}
{{- end }} {{ include "harbor.caBundleVolume" . | indent 6 }}
{{- if and .Values.persistence.enabled (not $trivy.existingClaim) }} {{- end }}
volumeClaimTemplates: {{- if not .Values.persistence.enabled }}
- metadata: - name: "data"
name: data emptyDir: {}
labels: {{- else if $trivy.existingClaim }}
{{ include "harbor.labels" . | indent 8 }} - name: "data"
spec: persistentVolumeClaim:
accessModes: [{{ $trivy.accessMode | quote }}] claimName: {{ $trivy.existingClaim }}
{{- if $trivy.storageClass }} {{- end }}
{{- if (eq "-" $trivy.storageClass) }} {{- end }}
storageClassName: "" {{- with .Values.trivy.nodeSelector }}
{{- else }} nodeSelector:
storageClassName: "{{ $trivy.storageClass }}" {{ toYaml . | indent 8 }}
{{- end }} {{- end }}
{{- end }} {{- with .Values.trivy.affinity }}
resources: affinity:
requests: {{ toYaml . | indent 8 }}
storage: {{ $trivy.size | quote }} {{- end }}
{{- end }} {{- with .Values.trivy.tolerations }}
{{- end }} tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.trivy.priorityClassName }}
priorityClassName: {{ .Values.trivy.priorityClassName }}
{{- end }}
{{- if and .Values.persistence.enabled (not $trivy.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: data
labels:
{{ include "harbor.legacy.labels" . | indent 8 }}
annotations:
{{- range $key, $value := $trivy.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
accessModes: [{{ $trivy.accessMode | quote }}]
{{- if $trivy.storageClass }}
{{- if (eq "-" $trivy.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: "{{ $trivy.storageClass }}"
{{- end }}
{{- end }}
resources:
requests:
storage: {{ $trivy.size | quote }}
{{- end }}
{{- end }}
{{ if .Values.trivy.enabled }} {{ if .Values.trivy.enabled }}
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: "{{ template "harbor.trivy" . }}" name: "{{ template "harbor.trivy" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
spec: {{ include "harbor.labels" . | indent 4 }}
ports: spec:
- name: api-server ports:
protocol: TCP - name: {{ ternary "https-trivy" "http-trivy" .Values.internalTLS.enabled }}
port: {{ template "harbor.trivy.servicePort" . }} protocol: TCP
selector: port: {{ template "harbor.trivy.servicePort" . }}
{{ include "harbor.matchLabels" . | indent 4 }} selector:
component: trivy {{ include "harbor.matchLabels" . | indent 4 }}
{{ end }} component: trivy
{{ end }}
{{- if and .Values.trivy.enabled .Values.internalTLS.enabled }} {{- if and .Values.trivy.enabled .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }} {{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: "{{ template "harbor.internalTLS.trivy.secretName" . }}" name: "{{ template "harbor.internalTLS.trivy.secretName" . }}"
labels: namespace: {{ .Release.Namespace | quote }}
{{ include "harbor.labels" . | indent 4 }} labels:
type: kubernetes.io/tls {{ include "harbor.labels" . | indent 4 }}
data: type: kubernetes.io/tls
ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }} data:
tls.crt: {{ (required "The \"internalTLS.trivy.crt\" is required!" .Values.internalTLS.trivy.crt) | b64enc | quote }} ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.trivy.key\" is required!" .Values.internalTLS.trivy.key) | b64enc | quote }} tls.crt: {{ (required "The \"internalTLS.trivy.crt\" is required!" .Values.internalTLS.trivy.crt) | b64enc | quote }}
{{- end }} tls.key: {{ (required "The \"internalTLS.trivy.key\" is required!" .Values.internalTLS.trivy.key) | b64enc | quote }}
{{- end }} {{- end }}
{{- end }}
module github.com/goharbor/harbor-helm
go 1.13
require (
github.com/gruntwork-io/terratest v0.28.2
github.com/stretchr/testify v1.6.0
k8s.io/api v0.18.3
)
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM=
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v38.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.1 h1:MXnqY6SlWySaZAqNnXThOvjRFdiiOuKtC6i7baFdNdU=
github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v0.0.0-20200109221225-a4f60165b7a3/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik=
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU=
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk=
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/gruntwork-io/gruntwork-cli v0.5.1 h1:mVmVsFubUSLSCO8bGigI63HXzvzkC0uWXzm4dd9pXRg=
github.com/gruntwork-io/gruntwork-cli v0.5.1/go.mod h1:IBX21bESC1/LGoV7jhXKUnTQTZgQ6dYRsoj/VqxUSZQ=
github.com/gruntwork-io/terratest v0.28.2 h1:M9CMfS/5unIawxYlz55eRDWH16AH522OAJcUc+zsKv4=
github.com/gruntwork-io/terratest v0.28.2/go.mod h1:lTntpr4gGDzb2YEQ1GTjC5G/xw9ixMwxGmZkPCk1O0A=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/oracle/oci-go-sdk v7.1.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok=
github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200107162124-548cf772de50 h1:YvQ10rzcqWXLlJZ3XCUoO25savxmscf4+SC+ZqiCHhA=
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191205215504-7b8c8591a921/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200113040837-eac381796e91/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0=
k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk=
k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg=
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
k8s.io/client-go v0.18.3 h1:QaJzz92tsN67oorwzmoB0a9r9ZVHuD5ryjbCKP0U22k=
k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE=
k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
#/bin/bash
set -e
version=${HELM_VERSION}
if [ "$version" = "2" ]
then
dist="helm-v2.8.0-linux-amd64.tar.gz"
# as the helm v3 removes tiller, here appends the "-c" option
# to args only when running helm v2 to display the client version
version_args="-c"
elif [ "$version" = "3" ]
then
# the "template" command doesn't work for helm beta3:
# https://github.com/helm/helm/issues/6404, use the beta2 for now
dist="helm-v3.0.0-beta.2-linux-amd64.tar.gz"
else
echo "unsupported helm version: $version"
exit 1
fi
wget -O /tmp/${dist} https://get.helm.sh/${dist}
tar -zxvf /tmp/${dist} -C /tmp/
sudo mv /tmp/linux-amd64/helm /usr/local/bin/helm
helm version $version_args
echo "Helm installed"
\ No newline at end of file
package integration
import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/gruntwork-io/terratest/modules/helm"
"github.com/gruntwork-io/terratest/modules/k8s"
"github.com/stretchr/testify/suite"
)
var (
client = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
)
func NewBaseTestSuite(values map[string]string) BaseTestSuite {
if values == nil {
values = map[string]string{}
}
return BaseTestSuite{
Options: &helm.Options{
KubectlOptions: &k8s.KubectlOptions{
Namespace: "default",
},
SetValues: values,
},
ReleaseName: "harbor",
URL: values["externalURL"],
}
}
type BaseTestSuite struct {
suite.Suite
Options *helm.Options
ReleaseName string
URL string // the external URL of Harbor
}
func (b *BaseTestSuite) SetupSuite() {
helm.Install(b.T(), b.Options, "../..", b.ReleaseName)
b.waitUntilHealthy(b.URL)
}
type overallStatus struct {
Status string `json:"status"`
Components []*componentStatus `json:"components"`
}
type componentStatus struct {
Name string `json:"name"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
}
func (b *BaseTestSuite) waitUntilHealthy(url string) {
url = fmt.Sprintf("%s/api/v2.0/health", url)
log.Printf("wait until Harbor is healthy by calling health check API: %s ...", url)
for i := 0; i < 60; i++ {
time.Sleep(10 * time.Second)
resp, err := client.Get(url)
if err != nil {
log.Printf("failed to call the health API: %v, retry 10 seconds later...", err)
continue
}
if resp.StatusCode != http.StatusOK {
log.Printf("the response status code %d != 200, retry 10 seconds later...", resp.StatusCode)
continue
}
data, err := ioutil.ReadAll(resp.Body)
b.Require().Nil(err)
resp.Body.Close()
status := &overallStatus{}
err = json.Unmarshal(data, status)
b.Require().Nil(err)
if status.Status != "healthy" {
for _, component := range status.Components {
if component.Status == "healthy" {
continue
}
log.Printf("the status of component %s isn't healthy: %s , retry 10 seconds later...",
component.Name, component.Error)
break
}
continue
}
log.Printf("the status is healthy")
return
}
b.FailNow("the status still isn't healthy after several retries")
}
func (b *BaseTestSuite) TestPush() {
addr := strings.TrimPrefix(b.URL, "http://")
addr = strings.TrimPrefix(addr, "https://")
// push image
b.T().Log("pushing the image...")
cmdStr := fmt.Sprintf("docker pull hello-world:latest;docker tag hello-world:latest %s/library/hello-world:latest; docker login %s -u admin -p Harbor12345;docker push %s/library/hello-world:latest",
addr, addr, addr)
cmd := exec.Command("/bin/sh", "-c", cmdStr)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
b.Require().Nil(err)
// delete image in local
b.T().Log("deleting the image in local")
cmdStr = fmt.Sprintf("docker rmi %s/library/hello-world:latest", addr)
cmd = exec.Command("/bin/sh", "-c", cmdStr)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
b.Require().Nil(err)
// pull image
b.T().Log("pull the image...")
cmdStr = fmt.Sprintf("docker pull %s/library/hello-world:latest", addr)
cmd = exec.Command("/bin/sh", "-c", cmdStr)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
b.Require().Nil(err)
}
func (b *BaseTestSuite) TearDownSuite() {
helm.Delete(b.T(), &helm.Options{}, b.ReleaseName, true)
}
package integration
import (
"fmt"
"testing"
"github.com/gruntwork-io/terratest/modules/k8s"
"github.com/stretchr/testify/suite"
)
type IngressTestSuite struct {
BaseTestSuite
}
func (i *IngressTestSuite) TestIngress() {
k8s.GetIngress(i.T(), i.Options.KubectlOptions, fmt.Sprintf("%s-harbor-ingress", i.ReleaseName))
k8s.GetIngress(i.T(), i.Options.KubectlOptions, fmt.Sprintf("%s-harbor-ingress-notary", i.ReleaseName))
}
func TestIngressTestSuite(t *testing.T) {
suite.Run(t, &IngressTestSuite{
BaseTestSuite: NewBaseTestSuite(map[string]string{
"expose.ingress.hosts.core": "harbor.local",
"expose.ingress.hosts.notary": "notary.harbor.local",
"externalURL": "https://harbor.local",
}),
})
}
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
- containerPort: 30003
hostPort: 30003
protocol: TCP
package integration
import (
"testing"
"github.com/gruntwork-io/terratest/modules/k8s"
"github.com/stretchr/testify/suite"
)
type NodePortTestSuite struct {
BaseTestSuite
}
func (n *NodePortTestSuite) TestNodePort() {
service := k8s.GetService(n.T(), n.Options.KubectlOptions, "harbor")
n.Equal("NodePort", string(service.Spec.Type))
}
func TestNodePortTestSuite(t *testing.T) {
suite.Run(t, &NodePortTestSuite{
BaseTestSuite: NewBaseTestSuite(map[string]string{
"expose.type": "nodePort",
"expose.tls.auto.commonName": "127.0.0.1",
"expose.nodePort.ports.https.nodePort": "30003",
"externalURL": "https://127.0.0.1:30003",
}),
})
}
package unittest
import (
"os"
"testing"
"github.com/gruntwork-io/terratest/modules/helm"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/stretchr/testify/suite"
appsV1 "k8s.io/api/apps/v1"
)
type TrivyStatefulSetTestSuite struct {
suite.Suite
}
func (suite *TrivyStatefulSetTestSuite) render(values map[string]string) *appsV1.StatefulSet {
helmChartPath := "../../"
options := &helm.Options{
SetValues: values,
}
debug := os.Getenv("debug")
if debug != "true" {
options.Logger = logger.Discard
}
output := helm.RenderTemplate(suite.T(), options, helmChartPath, "harbor", []string{"templates/trivy/trivy-sts.yaml"})
var ss appsV1.StatefulSet
helm.UnmarshalK8SYaml(suite.T(), output, &ss)
return &ss
}
func (suite *TrivyStatefulSetTestSuite) TestPersistenceDisabled() {
values := map[string]string{
"persistence.enabled": "false",
"persistence.persistentVolumeClaim.trivy.existingClaim": "trivy-data",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 1)
suite.NotNil(ss.Spec.Template.Spec.Volumes[0].EmptyDir)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
func (suite *TrivyStatefulSetTestSuite) TestPersistenceEnabled() {
values := map[string]string{
"persistence.enabled": "true",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 0)
suite.Len(ss.Spec.VolumeClaimTemplates, 1)
}
func (suite *TrivyStatefulSetTestSuite) TestExistingClaim() {
values := map[string]string{
"persistence.enabled": "true",
"persistence.persistentVolumeClaim.trivy.existingClaim": "trivy-data",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 1)
suite.NotNil(ss.Spec.Template.Spec.Volumes[0].PersistentVolumeClaim)
suite.Equal("trivy-data", ss.Spec.Template.Spec.Volumes[0].PersistentVolumeClaim.ClaimName)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
func (suite *TrivyStatefulSetTestSuite) TestInternalTLSEnabled() {
{
values := map[string]string{
"internalTLS.enabled": "true",
"persistence.enabled": "false",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 2)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
{
values := map[string]string{
"internalTLS.enabled": "true",
"persistence.enabled": "true",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 1)
suite.Len(ss.Spec.VolumeClaimTemplates, 1)
}
{
values := map[string]string{
"internalTLS.enabled": "true",
"persistence.enabled": "true",
"persistence.persistentVolumeClaim.trivy.existingClaim": "trivy-data",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 2)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
}
func (suite *TrivyStatefulSetTestSuite) TestCustomCA() {
{
values := map[string]string{
"caBundleSecretName": "ca-bundle-secret",
"persistence.enabled": "false",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 2)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
{
values := map[string]string{
"caBundleSecretName": "ca-bundle-secret",
"internalTLS.enabled": "true",
"persistence.enabled": "false",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 3)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
{
values := map[string]string{
"caBundleSecretName": "ca-bundle-secret",
"internalTLS.enabled": "true",
"persistence.enabled": "true",
"persistence.persistentVolumeClaim.trivy.existingClaim": "trivy-data",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 3)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
{
values := map[string]string{
"caBundleSecretName": "ca-bundle-secret",
"persistence.enabled": "true",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 1)
suite.Len(ss.Spec.VolumeClaimTemplates, 1)
}
{
values := map[string]string{
"caBundleSecretName": "ca-bundle-secret",
"persistence.enabled": "true",
"persistence.persistentVolumeClaim.trivy.existingClaim": "trivy-data",
}
ss := suite.render(values)
suite.Len(ss.Spec.Template.Spec.Volumes, 2)
suite.Len(ss.Spec.VolumeClaimTemplates, 0)
}
}
func TestTrivyStatefulSetTestSuite(t *testing.T) {
suite.Run(t, &TrivyStatefulSetTestSuite{})
}
#/bin/bash
set -e
helm lint .
# expose the service via ingress, this disables the deployment of nginx
helm template --set "expose.type=ingress" --output-dir /tmp/ .
# expose the service via node port, this enables the deployment of nginx
helm template --set "expose.type=nodePort,expose.tls.commonName=127.0.0.1" --output-dir /tmp/ .
\ No newline at end of file
...@@ -2,8 +2,9 @@ global: ...@@ -2,8 +2,9 @@ global:
hub: registry.cn-qingdao.aliyuncs.com/wod hub: registry.cn-qingdao.aliyuncs.com/wod
imagePullPolicy: "IfNotPresent" imagePullPolicy: "IfNotPresent"
imageArch: amd64 imageArch: amd64
host: wodcloud.local host: wocloud.local
imagePullSecrets: imagePullSecrets:
- name: beagle-registry - name: beagle-registry
registrySecrets: true registrySecrets: true
\ No newline at end of file externalURL: https://hub.wocloud.local
\ No newline at end of file
expose: expose:
# Set the way how to expose the service. Set the type as "ingress", # Set how to expose the service. Set the type as "ingress", "clusterIP", "nodePort" or "loadBalancer"
# "clusterIP", "nodePort" or "loadBalancer" and fill the information # and fill the information in the corresponding section
# in the corresponding section type: ingress
type: ingress tls:
tls: # Enable TLS or not.
# Enable the tls or not. Note: if the type is "ingress" and the tls # Delete the "ssl-redirect" annotations in "expose.ingress.annotations" when TLS is disabled and "expose.type" is "ingress"
# is disabled, the port must be included in the command when pull/push # Note: if the "expose.type" is "ingress" and TLS is disabled,
# images. Refer to https://github.com/goharbor/harbor/issues/5291 # the port must be included in the command when pulling/pushing images.
# for the detail. # Refer to https://github.com/registry.cn-qingdao.aliyuncs.com/wod/harbor/issues/5291 for details.
enabled: false enabled: true
# The source of the tls certificate. Set it as "auto", "secret" # The source of the tls certificate. Set as "auto", "secret"
# or "none" and fill the information in the corresponding section # or "none" and fill the information in the corresponding section
# 1) auto: generate the tls certificate automatically # 1) auto: generate the tls certificate automatically
# 2) secret: read the tls certificate from the specified secret. # 2) secret: read the tls certificate from the specified secret.
# The tls certificate can be generated manually or by cert manager # The tls certificate can be generated manually or by cert manager
# 3) none: configure no tls certificate for the ingress. If the default # 3) none: configure no tls certificate for the ingress. If the default
# tls certificate is configured in the ingress controller, choose this option # tls certificate is configured in the ingress controller, choose this option
certSource: auto certSource: auto
auto: auto:
# The common name used to generate the certificate, it's necessary # The common name used to generate the certificate, it's necessary
# when the type isn't "ingress" # when the type isn't "ingress"
commonName: '' commonName: ""
secret: secret:
# The name of secret which contains keys named: # The name of secret which contains keys named:
# "tls.crt" - the certificate # "tls.crt" - the certificate
# "tls.key" - the private key # "tls.key" - the private key
secretName: '' secretName: ""
# The name of secret which contains keys named: ingress:
# "tls.crt" - the certificate hosts:
# "tls.key" - the private key core: hub
# Only needed when the "expose.type" is "ingress". # set to the type of ingress controller if it has specific requirements.
notarySecretName: '' # leave as `default` for most ingress controllers.
ingress: # set to `gce` if using the GCE ingress controller
hosts: # set to `ncp` if using the NCP (NSX-T Container Plugin) ingress controller
core: hub # set to `alb` if using the ALB ingress controller
notary: notary # set to `f5-bigip` if using the F5 BIG-IP ingress controller
# set to the type of ingress controller if it has specific requirements. controller: default
# leave as `default` for most ingress controllers. ## Allow .Capabilities.KubeVersion.Version to be overridden while creating ingress
# set to `gce` if using the GCE ingress controller kubeVersionOverride: ""
# set to `ncp` if using the NCP (NSX-T Container Plugin) ingress controller className: ""
controller: default annotations:
annotations: # note different ingress controllers may require a different ssl-redirect annotation
ingress.kubernetes.io/ssl-redirect: 'true' # for Envoy, use ingress.kubernetes.io/force-ssl-redirect: "true" and remove the nginx lines below
ingress.kubernetes.io/proxy-body-size: '0' ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-redirect: 'true' ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-body-size: '0' nginx.ingress.kubernetes.io/ssl-redirect: "true"
clusterIP: nginx.ingress.kubernetes.io/proxy-body-size: "0"
# The name of ClusterIP service # ingress-specific labels
name: harbor labels: {}
ports: clusterIP:
# The service port Harbor listens on when serving with HTTP # The name of ClusterIP service
httpPort: 80 name: harbor
# The service port Harbor listens on when serving with HTTPS # The ip address of the ClusterIP service (leave empty for acquiring dynamic ip)
httpsPort: 443 staticClusterIP: ""
# The service port Notary listens on. Only needed when notary.enabled ports:
# is set to true # The service port Harbor listens on when serving HTTP
notaryPort: 4443 httpPort: 80
nodePort: # The service port Harbor listens on when serving HTTPS
# The name of NodePort service httpsPort: 443
name: harbor # Annotations on the ClusterIP service
ports: annotations: {}
http: # ClusterIP-specific labels
# The service port Harbor listens on when serving with HTTP labels: {}
port: 80 nodePort:
# The node port Harbor listens on when serving with HTTP # The name of NodePort service
nodePort: 30002 name: harbor
https: ports:
# The service port Harbor listens on when serving with HTTPS http:
port: 443 # The service port Harbor listens on when serving HTTP
# The node port Harbor listens on when serving with HTTPS port: 80
nodePort: 30003 # The node port Harbor listens on when serving HTTP
# Only needed when notary.enabled is set to true nodePort: 30002
notary: https:
# The service port Notary listens on # The service port Harbor listens on when serving HTTPS
port: 4443 port: 443
# The node port Notary listens on # The node port Harbor listens on when serving HTTPS
nodePort: 30004 nodePort: 30003
loadBalancer: # Annotations on the nodePort service
# The name of LoadBalancer service annotations: {}
name: harbor # nodePort-specific labels
# Set the IP if the LoadBalancer supports assigning IP labels: {}
IP: '' loadBalancer:
ports: # The name of LoadBalancer service
# The service port Harbor listens on when serving with HTTP name: harbor
httpPort: 80 # Set the IP if the LoadBalancer supports assigning IP
# The service port Harbor listens on when serving with HTTPS IP: ""
httpsPort: 443 ports:
# The service port Notary listens on. Only needed when notary.enabled # The service port Harbor listens on when serving HTTP
# is set to true httpPort: 80
notaryPort: 4443 # The service port Harbor listens on when serving HTTPS
annotations: {} httpsPort: 443
sourceRanges: [] # Annotations on the loadBalancer service
annotations: {}
# The external URL for Harbor core service. It is used to # loadBalancer-specific labels
# 1) populate the docker/helm commands showed on portal labels: {}
# 2) populate the token service URL returned to docker/notary client sourceRanges: []
#
# Format: protocol://domain[:port]. Usually: # The external URL for Harbor core service. It is used to
# 1) if "expose.type" is "ingress", the "domain" should be # 1) populate the docker/helm commands showed on portal
# the value of "expose.ingress.hosts.core" # 2) populate the token service URL returned to docker client
# 2) if "expose.type" is "clusterIP", the "domain" should be #
# the value of "expose.clusterIP.name" # Format: protocol://domain[:port]. Usually:
# 3) if "expose.type" is "nodePort", the "domain" should be # 1) if "expose.type" is "ingress", the "domain" should be
# the IP address of k8s node # the value of "expose.ingress.hosts.core"
# # 2) if "expose.type" is "clusterIP", the "domain" should be
# If Harbor is deployed behind the proxy, set it as the URL of proxy # the value of "expose.clusterIP.name"
externalURL: https://hub # 3) if "expose.type" is "nodePort", the "domain" should be
# the IP address of k8s node
# The internal TLS used for harbor components secure communicating. In order to enable https #
# in each components tls cert files need to provided in advance. # If Harbor is deployed behind the proxy, set it as the URL of proxy
internalTLS: externalURL: https://hub.wodcloud.local
# If internal TLS enabled
enabled: false # The persistence is enabled by default and a default StorageClass
# There are three ways to provide tls # is needed in the k8s cluster to provision volumes dynamically.
# 1) "auto" will generate cert automatically # Specify another StorageClass in the "storageClass" or set "existingClaim"
# 2) "manual" need provide cert file manually in following value # if you already have existing persistent volumes to use
# 3) "secret" internal certificates from secret #
certSource: 'auto' # For storing images and charts, you can also use "azure", "gcs", "s3",
# The content of trust ca, only available when `certSource` is "manual" # "swift" or "oss". Set it in the "imageChartStorage" section
trustCa: '' persistence:
# core related cert configuration enabled: true
core: # Setting it to "keep" to avoid removing PVCs during a helm delete
# secret name for core's tls certs # operation. Leaving it empty will delete PVCs after the chart deleted
secretName: '' # (this does not apply for PVCs that are created for internal database
# Content of core's TLS cert file, only available when `certSource` is "manual" # and redis components, i.e. they are never deleted automatically)
crt: '' resourcePolicy: "keep"
# Content of core's TLS key file, only available when `certSource` is "manual" persistentVolumeClaim:
key: '' registry:
# jobservice related cert configuration # Use the existing PVC which must be created manually before bound,
jobservice: # and specify the "subPath" if the PVC is shared with other components
# secret name for jobservice's tls certs existingClaim: ""
secretName: '' # Specify the "storageClass" used to provision the volume. Or the default
# Content of jobservice's TLS key file, only available when `certSource` is "manual" # StorageClass will be used (the default).
crt: '' # Set it to "-" to disable dynamic provisioning
# Content of jobservice's TLS key file, only available when `certSource` is "manual" storageClass: "csi-s3"
key: '' subPath: ""
# registry related cert configuration accessMode: ReadWriteOnce
registry: size: 5Gi
# secret name for registry's tls certs annotations: {}
secretName: '' jobservice:
# Content of registry's TLS key file, only available when `certSource` is "manual" jobLog:
crt: '' existingClaim: ""
# Content of registry's TLS key file, only available when `certSource` is "manual" storageClass: "csi-s3"
key: '' subPath: ""
# portal related cert configuration accessMode: ReadWriteOnce
portal: size: 1Gi
# secret name for portal's tls certs annotations: {}
secretName: '' # If external database is used, the following settings for database will
# Content of portal's TLS key file, only available when `certSource` is "manual" # be ignored
crt: '' database:
# Content of portal's TLS key file, only available when `certSource` is "manual" existingClaim: ""
key: '' storageClass: "hostpath"
# chartmuseum related cert configuration subPath: ""
chartmuseum: accessMode: ReadWriteOnce
# secret name for chartmuseum's tls certs size: 1Gi
secretName: '' annotations: {}
# Content of chartmuseum's TLS key file, only available when `certSource` is "manual" # If external Redis is used, the following settings for Redis will
crt: '' # be ignored
# Content of chartmuseum's TLS key file, only available when `certSource` is "manual" redis:
key: '' existingClaim: ""
# clair related cert configuration storageClass: "csi-s3"
clair: subPath: ""
# secret name for clair's tls certs accessMode: ReadWriteOnce
secretName: '' size: 1Gi
# Content of clair's TLS key file, only available when `certSource` is "manual" annotations: {}
crt: '' trivy:
# Content of clair's TLS key file, only available when `certSource` is "manual" existingClaim: ""
key: '' storageClass: "csi-s3"
# trivy related cert configuration subPath: ""
trivy: accessMode: ReadWriteOnce
# secret name for trivy's tls certs size: 5Gi
secretName: '' annotations: {}
# Content of trivy's TLS key file, only available when `certSource` is "manual" # Define which storage backend is used for registry to store
crt: '' # images and charts. Refer to
# Content of trivy's TLS key file, only available when `certSource` is "manual" # https://github.com/distribution/distribution/blob/release/2.8/docs/configuration.md#storage
key: '' # for the detail.
imageChartStorage:
# The persistence is enabled by default and a default StorageClass # Specify whether to disable `redirect` for images and chart storage, for
# is needed in the k8s cluster to provision volumes dynamicly. # backends which not supported it (such as using minio for `s3` storage type), please disable
# Specify another StorageClass in the "storageClass" or set "existingClaim" # it. To disable redirects, simply set `disableredirect` to `true` instead.
# if you have already existing persistent volumes to use # Refer to
# # https://github.com/distribution/distribution/blob/release/2.8/docs/configuration.md#redirect
# For storing images and charts, you can also use "azure", "gcs", "s3", # for the detail.
# "swift" or "oss". Set it in the "imageChartStorage" section disableredirect: false
persistence: # Specify the "caBundleSecretName" if the storage service uses a self-signed certificate.
enabled: true # The secret must contain keys named "ca.crt" which will be injected into the trust store
# Setting it to "keep" to avoid removing PVCs during a helm delete # of registry's containers.
# operation. Leaving it empty will delete PVCs after the chart deleted # caBundleSecretName:
# (this does not apply for PVCs that are created for internal database
# and redis components, i.e. they are never deleted automatically) # Specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift",
resourcePolicy: 'keep' # "oss" and fill the information needed in the corresponding section. The type
persistentVolumeClaim: # must be "filesystem" if you want to use persistent volumes for registry
registry: type: oss
# Use the existing PVC which must be created manually before bound, filesystem:
# and specify the "subPath" if the PVC is shared with other components rootdirectory: /storage
existingClaim: '' #maxthreads: 100
# Specify the "storageClass" used to provision the volume. Or the default azure:
# StorageClass will be used(the default). accountname: accountname
# Set it to "-" to disable dynamic provisioning accountkey: base64encodedaccountkey
storageClass: 'hostpath' container: containername
subPath: '' #realm: core.windows.net
accessMode: ReadWriteOnce # To use existing secret, the key must be AZURE_STORAGE_ACCESS_KEY
size: 5Gi existingSecret: ""
chartmuseum: gcs:
existingClaim: '' bucket: bucketname
storageClass: 'hostpath' # The base64 encoded json file which contains the key
subPath: '' encodedkey: base64-encoded-json-key-file
accessMode: ReadWriteOnce #rootdirectory: /gcs/object/name/prefix
size: 5Gi #chunksize: "5242880"
jobservice: # To use existing secret, the key must be GCS_KEY_DATA
existingClaim: '' existingSecret: ""
storageClass: 'hostpath' useWorkloadIdentity: false
subPath: '' s3:
accessMode: ReadWriteOnce # Set an existing secret for S3 accesskey and secretkey
size: 1Gi # keys in the secret should be REGISTRY_STORAGE_S3_ACCESSKEY and REGISTRY_STORAGE_S3_SECRETKEY for registry
# If external database is used, the following settings for database will #existingSecret: ""
# be ignored region: us-west-1
database: bucket: bucketname
existingClaim: '' #accesskey: awsaccesskey
storageClass: 'hostpath' #secretkey: awssecretkey
subPath: '' #regionendpoint: http://myobjects.local
accessMode: ReadWriteOnce #encrypt: false
size: 10Gi #keyid: mykeyid
# If external Redis is used, the following settings for Redis will #secure: true
# be ignored #skipverify: false
redis: #v4auth: true
existingClaim: '' #chunksize: "5242880"
storageClass: 'hostpath' #rootdirectory: /s3/object/name/prefix
subPath: '' #storageclass: STANDARD
accessMode: ReadWriteOnce #multipartcopychunksize: "33554432"
size: 1Gi #multipartcopymaxconcurrency: 100
trivy: #multipartcopythresholdsize: "33554432"
existingClaim: '' swift:
storageClass: 'hostpath' authurl: https://storage.myprovider.com/v3/auth
subPath: '' username: username
accessMode: ReadWriteOnce password: password
size: 5Gi container: containername
# Define which storage backend is used for registry and chartmuseum to store # keys in existing secret must be REGISTRY_STORAGE_SWIFT_PASSWORD, REGISTRY_STORAGE_SWIFT_SECRETKEY, REGISTRY_STORAGE_SWIFT_ACCESSKEY
# images and charts. Refer to existingSecret: ""
# https://github.com/docker/distribution/blob/master/docs/configuration.md#storage #region: fr
# for the detail. #tenant: tenantname
imageChartStorage: #tenantid: tenantid
# Specify whether to disable `redirect` for images and chart storage, for #domain: domainname
# backends which not supported it (such as using minio for `s3` storage type), please disable #domainid: domainid
# it. To disable redirects, simply set `disableredirect` to `true` instead. #trustid: trustid
# Refer to #insecureskipverify: false
# https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect #chunksize: 5M
# for the detail. #prefix:
disableredirect: false #secretkey: secretkey
# Specify the "caBundleSecretName" if the storage service uses a self-signed certificate. #accesskey: accesskey
# The secret must contain keys named "ca.crt" which will be injected into the trust store #authversion: 3
# of registry's and chartmuseum's containers. #endpointtype: public
# caBundleSecretName: #tempurlcontainerkey: false
#tempurlmethods:
# Specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift", oss:
# "oss" and fill the information needed in the corresponding section. The type accesskeyid: ""
# must be "filesystem" if you want to use persistent volumes for registry accesskeysecret: ""
# and chartmuseum region: ""
type: filesystem bucket: ""
filesystem: # key in existingSecret must be REGISTRY_STORAGE_OSS_ACCESSKEYSECRET
rootdirectory: /storage existingSecret: ""
#maxthreads: 100 endpoint: ""
azure: #internal: false
accountname: accountname #encrypt: false
accountkey: base64encodedaccountkey secure: true
container: containername #chunksize: 10M
#realm: core.windows.net rootdirectory: hub
gcs:
bucket: bucketname # The initial password of Harbor admin. Change it from portal after launching Harbor
# The base64 encoded json file which contains the key # or give an existing secret for it
encodedkey: base64-encoded-json-key-file # key in secret is given via (default to HARBOR_ADMIN_PASSWORD)
#rootdirectory: /gcs/object/name/prefix # existingSecretAdminPassword:
#chunksize: "5242880" existingSecretAdminPasswordKey: HARBOR_ADMIN_PASSWORD
s3: harborAdminPassword: "Harbor12345"
region: us-west-1
bucket: bucketname # The internal TLS used for harbor components secure communicating. In order to enable https
#accesskey: awsaccesskey # in each component tls cert files need to provided in advance.
#secretkey: awssecretkey internalTLS:
#regionendpoint: http://myobjects.local # If internal TLS enabled
#encrypt: false enabled: false
#keyid: mykeyid # enable strong ssl ciphers (default: false)
#secure: true strong_ssl_ciphers: false
#skipverify: false # There are three ways to provide tls
#v4auth: true # 1) "auto" will generate cert automatically
#chunksize: "5242880" # 2) "manual" need provide cert file manually in following value
#rootdirectory: /s3/object/name/prefix # 3) "secret" internal certificates from secret
#storageclass: STANDARD certSource: "auto"
#multipartcopychunksize: "33554432" # The content of trust ca, only available when `certSource` is "manual"
#multipartcopymaxconcurrency: 100 trustCa: ""
#multipartcopythresholdsize: "33554432" # core related cert configuration
swift: core:
authurl: https://storage.myprovider.com/v3/auth # secret name for core's tls certs
username: username secretName: ""
password: password # Content of core's TLS cert file, only available when `certSource` is "manual"
container: containername crt: ""
#region: fr # Content of core's TLS key file, only available when `certSource` is "manual"
#tenant: tenantname key: ""
#tenantid: tenantid # jobservice related cert configuration
#domain: domainname jobservice:
#domainid: domainid # secret name for jobservice's tls certs
#trustid: trustid secretName: ""
#insecureskipverify: false # Content of jobservice's TLS key file, only available when `certSource` is "manual"
#chunksize: 5M crt: ""
#prefix: # Content of jobservice's TLS key file, only available when `certSource` is "manual"
#secretkey: secretkey key: ""
#accesskey: accesskey # registry related cert configuration
#authversion: 3 registry:
#endpointtype: public # secret name for registry's tls certs
#tempurlcontainerkey: false secretName: ""
#tempurlmethods: # Content of registry's TLS key file, only available when `certSource` is "manual"
oss: crt: ""
accesskeyid: accesskeyid # Content of registry's TLS key file, only available when `certSource` is "manual"
accesskeysecret: accesskeysecret key: ""
region: regionname # portal related cert configuration
bucket: bucketname portal:
#endpoint: endpoint # secret name for portal's tls certs
#internal: false secretName: ""
#encrypt: false # Content of portal's TLS key file, only available when `certSource` is "manual"
#secure: true crt: ""
#chunksize: 10M # Content of portal's TLS key file, only available when `certSource` is "manual"
#rootdirectory: rootdirectory key: ""
# trivy related cert configuration
imagePullPolicy: IfNotPresent trivy:
# secret name for trivy's tls certs
# Use this set to assign a list of default pullSecrets secretName: ""
imagePullSecrets: # Content of trivy's TLS key file, only available when `certSource` is "manual"
# - name: docker-registry-secret crt: ""
# - name: internal-registry-secret # Content of trivy's TLS key file, only available when `certSource` is "manual"
key: ""
# The update strategy for deployments with persistent volumes(jobservice, registry
# and chartmuseum): "RollingUpdate" or "Recreate" ipFamily:
# Set it as "Recreate" when "RWM" for volumes isn't supported # ipv6Enabled set to true if ipv6 is enabled in cluster, currently it affected the nginx related component
updateStrategy: ipv6:
type: RollingUpdate enabled: true
# ipv4Enabled set to true if ipv4 is enabled in cluster, currently it affected the nginx related component
# debug, info, warning, error or fatal ipv4:
logLevel: info enabled: true
# The initial password of Harbor admin. Change it from portal after launching Harbor imagePullPolicy: IfNotPresent
harborAdminPassword: 'spaceIN511'
# Use this set to assign a list of default pullSecrets
# The name of the secret which contains key named "ca.crt". Setting this enables the imagePullSecrets:
# download link on portal to download the certificate of CA when the certificate isn't # - name: docker-registry-secret
# generated automatically # - name: internal-registry-secret
caSecretName: ''
# The update strategy for deployments with persistent volumes(jobservice, registry): "RollingUpdate" or "Recreate"
# The secret key used for encryption. Must be a string of 16 chars. # Set it as "Recreate" when "RWM" for volumes isn't supported
secretKey: 'IpTIscRIgmerlare' updateStrategy:
type: RollingUpdate
# The proxy settings for updating clair vulnerabilities from the Internet and replicating
# artifacts from/to the registries that cannot be reached directly # debug, info, warning, error or fatal
proxy: logLevel: info
httpProxy:
httpsProxy: # The name of the secret which contains key named "ca.crt". Setting this enables the
noProxy: 127.0.0.1,localhost,.local,.internal # download link on portal to download the CA certificate when the certificate isn't
components: # generated automatically
- core caSecretName: ""
- jobservice
- clair # The secret key used for encryption. Must be a string of 16 chars.
- trivy secretKey: "not-a-secure-key"
# If using existingSecretSecretKey, the key must be secretKey
# The custom ca bundle secret, the secret must contain key named "ca.crt" existingSecretSecretKey: ""
# which will be injected into the trust store for chartmuseum, clair, core, jobservice, registry, trivy components
# caBundleSecretName: "" # The proxy settings for updating trivy vulnerabilities from the Internet and replicating
# artifacts from/to the registries that cannot be reached directly
## UAA Authentication Options proxy:
# If you're using UAA for authentication behind a self-signed httpProxy:
# certificate you will need to provide the CA Cert. httpsProxy:
# Set uaaSecretName below to provide a pre-created secret that noProxy: 127.0.0.1,localhost,.local,.internal
# contains a base64 encoded CA Certificate named `ca.crt`. components:
# uaaSecretName: - core
- jobservice
# If expose the service via "ingress", the Nginx will not be used - trivy
nginx:
image: # Run the migration job via helm hook
repository: nginx enableMigrateHelmHook: false
tag: v2.1.6
# set the service account to be used, default if left empty # The custom ca bundle secret, the secret must contain key named "ca.crt"
serviceAccountName: '' # which will be injected into the trust store for core, jobservice, registry, trivy components
replicas: 1 # caBundleSecretName: ""
# resources:
# requests: ## UAA Authentication Options
# memory: 256Mi # If you're using UAA for authentication behind a self-signed
# cpu: 100m # certificate you will need to provide the CA Cert.
nodeSelector: {} # Set uaaSecretName below to provide a pre-created secret that
tolerations: [] # contains a base64 encoded CA Certificate named `ca.crt`.
affinity: {} # uaaSecretName:
## Additional deployment annotations
podAnnotations: {} metrics:
enabled: false
portal: core:
image: path: /metrics
repository: harbor-portal port: 8001
tag: v2.1.6 registry:
# set the service account to be used, default if left empty path: /metrics
serviceAccountName: '' port: 8001
replicas: 1 jobservice:
# resources: path: /metrics
# requests: port: 8001
# memory: 256Mi exporter:
# cpu: 100m path: /metrics
nodeSelector: {} port: 8001
tolerations: [] ## Create prometheus serviceMonitor to scrape harbor metrics.
affinity: {} ## This requires the monitoring.coreos.com/v1 CRD. Please see
## Additional deployment annotations ## https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md
podAnnotations: {} ##
serviceMonitor:
core: enabled: false
image: additionalLabels: {}
repository: harbor-core # Scrape interval. If not set, the Prometheus default scrape interval is used.
tag: v2.1.6 interval: ""
# set the service account to be used, default if left empty # Metric relabel configs to apply to samples before ingestion.
serviceAccountName: '' metricRelabelings:
replicas: 1 []
## Startup probe values # - action: keep
startupProbe: # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'
enabled: false # sourceLabels: [__name__]
initialDelaySeconds: 10 # Relabel configs to apply to samples before ingestion.
# resources: relabelings:
# requests: []
# memory: 256Mi # - sourceLabels: [__meta_kubernetes_pod_node_name]
# cpu: 100m # separator: ;
nodeSelector: {} # regex: ^(.*)$
tolerations: [] # targetLabel: nodename
affinity: {} # replacement: $1
## Additional deployment annotations # action: replace
podAnnotations: {}
# Secret is used when core server communicates with other components. trace:
# If a secret key is not specified, Helm will generate one. enabled: false
# Must be a string of 16 chars. # trace provider: jaeger or otel
secret: '' # jaeger should be 1.26+
# Fill the name of a kubernetes secret if you want to use your own provider: jaeger
# TLS certificate and private key for token encryption/decryption. # set sample_rate to 1 if you wanna sampling 100% of trace data; set 0.5 if you wanna sampling 50% of trace data, and so forth
# The secret must contain keys named: sample_rate: 1
# "tls.crt" - the certificate # namespace used to differentiate different harbor services
# "tls.key" - the private key # namespace:
# The default key pair will be used if it isn't set # attributes is a key value dict contains user defined attributes used to initialize trace provider
secretName: '' # attributes:
# The XSRF key. Will be generated automatically if it isn't specified # application: harbor
xsrfKey: '' jaeger:
# jaeger supports two modes:
jobservice: # collector mode(uncomment endpoint and uncomment username, password if needed)
image: # agent mode(uncomment agent_host and agent_port)
repository: harbor-jobservice endpoint: http://hostname:14268/api/traces
tag: v2.1.6 # username:
replicas: 1 # password:
# set the service account to be used, default if left empty # agent_host: hostname
serviceAccountName: '' # export trace data by jaeger.thrift in compact mode
maxJobWorkers: 10 # agent_port: 6831
# The logger for jobs: "file", "database" or "stdout" otel:
jobLogger: file endpoint: hostname:4318
# resources: url_path: /v1/traces
# requests: compression: false
# memory: 256Mi insecure: true
# cpu: 100m # timeout is in seconds
nodeSelector: {} timeout: 10
tolerations: []
affinity: {} # cache layer configurations
## Additional deployment annotations # if this feature enabled, harbor will cache the resource
podAnnotations: {} # `project/project_metadata/repository/artifact/manifest` in the redis
# Secret is used when job service communicates with other components. # which help to improve the performance of high concurrent pulling manifest.
# If a secret key is not specified, Helm will generate one. cache:
# Must be a string of 16 chars. # default is not enabled.
secret: '' enabled: false
# default keep cache for one day.
registry: expireHours: 24
# set the service account to be used, default if left empty
serviceAccountName: '' ## set Container Security Context to comply with PSP restricted policy if necessary
registry: ## each of the conatiner will apply the same security context
image: ## containerSecurityContext:{} is initially an empty yaml that you could edit it on demand, we just filled with a common template for convenience
repository: registry containerSecurityContext:
tag: v2.7.1 privileged: false
resources: allowPrivilegeEscalation: false
limits: seccompProfile:
memory: 4Gi type: RuntimeDefault
requests: runAsNonRoot: true
memory: 256Mi capabilities:
controller: drop:
image: - ALL
repository: harbor-registryctl
tag: v2.1.6 # If service exposed via "ingress", the Nginx will not be used
nginx:
# resources: image:
# requests: repository: registry.cn-qingdao.aliyuncs.com/wod/nginx-photon
# memory: 256Mi tag: v2.13.2
# cpu: 100m # set the service account to be used, default if left empty
replicas: 1 serviceAccountName: ""
nodeSelector: {} # mount the service account token
tolerations: [] automountServiceAccountToken: false
affinity: {} replicas: 1
## Additional deployment annotations revisionHistoryLimit: 10
podAnnotations: {} # resources:
# Secret is used to secure the upload state from client # requests:
# and registry storage backend. # memory: 256Mi
# See: https://github.com/docker/distribution/blob/master/docs/configuration.md#http # cpu: 100m
# If a secret key is not specified, Helm will generate one. extraEnvVars: []
# Must be a string of 16 chars. nodeSelector: {}
secret: '' tolerations: []
# If true, the registry returns relative URLs in Location headers. The client is responsible for resolving the correct URL. affinity: {}
relativeurls: false # Spread Pods across failure-domains like regions, availability zones or nodes
credentials: topologySpreadConstraints: []
username: 'harbor_registry_user' # - maxSkew: 1
password: 'harbor_registry_password' # topologyKey: topology.kubernetes.io/zone
# If you update the username or password of registry, make sure use cli tool htpasswd to generate the bcrypt hash # nodeTaintsPolicy: Honor
# e.g. "htpasswd -nbBC10 $username $password" # whenUnsatisfiable: DoNotSchedule
htpasswd: 'harbor_registry_user:$2y$10$9L4Tc0DJbFFMB6RdSCunrOpTHdwhid4ktBJmLD00bYgqkkGOvll3m' ## Additional deployment annotations
podAnnotations: {}
middleware: ## Additional deployment labels
enabled: false podLabels: {}
type: cloudFront ## The priority class to run the pod as
cloudFront: priorityClassName:
baseurl: example.cloudfront.net
keypairid: KEYPAIRID portal:
duration: 3000s image:
ipfilteredby: none repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-portal
# The secret key that should be present is CLOUDFRONT_KEY_DATA, which should be the encoded private key tag: v2.13.2
# that allows access to CloudFront # set the service account to be used, default if left empty
privateKeySecret: 'my-secret' serviceAccountName: ""
# mount the service account token
chartmuseum: automountServiceAccountToken: false
enabled: true replicas: 1
# set the service account to be used, default if left empty revisionHistoryLimit: 10
serviceAccountName: '' # resources:
# Harbor defaults ChartMuseum to returning relative urls, if you want using absolute url you should enable it by change the following value to 'true' # requests:
absoluteUrl: false # memory: 256Mi
image: # cpu: 100m
repository: chartmuseum extraEnvVars: []
tag: v0.12.0 nodeSelector: {}
storageSpec: tolerations: []
type: hostPath affinity: {}
emptyDir: {} # Spread Pods across failure-domains like regions, availability zones or nodes
hostPath: topologySpreadConstraints: []
root: /data # - maxSkew: 1
replicas: 1 # topologyKey: topology.kubernetes.io/zone
# resources: # nodeTaintsPolicy: Honor
# requests: # whenUnsatisfiable: DoNotSchedule
# memory: 256Mi ## Additional deployment annotations
# cpu: 100m podAnnotations: {}
nodeSelector: {} ## Additional deployment labels
tolerations: [] podLabels: {}
affinity: {} ## Additional service annotations
## Additional deployment annotations serviceAnnotations: {}
podAnnotations: {} ## The priority class to run the pod as
priorityClassName:
clair: # containers to be run before the controller's container starts.
enabled: true initContainers: []
# set the service account to be used, default if left empty # Example:
serviceAccountName: '' #
clair: # - name: wait
image: # image: busybox
repository: clair # command: [ 'sh', '-c', "sleep 20" ]
tag: v2.1.7
# resources: core:
# requests: image:
# memory: 256Mi repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-core
# cpu: 100m tag: v2.13.2
adapter: # set the service account to be used, default if left empty
image: serviceAccountName: ""
repository: harbor-scanner-clair # mount the service account token
tag: v1.1.1 automountServiceAccountToken: false
# resources: replicas: 1
# requests: revisionHistoryLimit: 10
# memory: 256Mi ## Startup probe values
# cpu: 100m startupProbe:
replicas: 1 enabled: true
# The interval of clair updaters, the unit is hour, set to 0 to initialDelaySeconds: 10
# disable the updaters # resources:
updatersInterval: 12 # requests:
nodeSelector: {} # memory: 256Mi
tolerations: [] # cpu: 100m
affinity: {} extraEnvVars: []
## Additional deployment annotations nodeSelector: {}
podAnnotations: {} tolerations: []
affinity: {}
trivy: # Spread Pods across failure-domains like regions, availability zones or nodes
# enabled the flag to enable Trivy scanner topologySpreadConstraints: []
enabled: true # - maxSkew: 1
image: # topologyKey: topology.kubernetes.io/zone
# repository the repository for Trivy adapter image # nodeTaintsPolicy: Honor
repository: harbor-scanner-trivy # whenUnsatisfiable: DoNotSchedule
# tag the tag for Trivy adapter image ## Additional deployment annotations
tag: v0.17.0 podAnnotations: {}
# set the service account to be used, default if left empty ## Additional deployment labels
serviceAccountName: '' podLabels: {}
# replicas the number of Pod replicas ## Additional service annotations
replicas: 1 serviceAnnotations: {}
# debugMode the flag to enable Trivy debug mode with more verbose scanning log ## The priority class to run the pod as
debugMode: false priorityClassName:
# vulnType a comma-separated list of vulnerability types. Possible values are `os` and `library`. # containers to be run before the controller's container starts.
vulnType: 'os,library' initContainers: []
# severity a comma-separated list of severities to be checked # Example:
severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL' #
# ignoreUnfixed the flag to display only fixed vulnerabilities # - name: wait
ignoreUnfixed: false # image: busybox
# insecure the flag to skip verifying registry certificate # command: [ 'sh', '-c', "sleep 20" ]
insecure: false ## User settings configuration json string
# gitHubToken the GitHub access token to download Trivy DB configureUserSettings:
# # The provider for updating project quota(usage), there are 2 options, redis or db.
# Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases. # By default it is implemented by db but you can configure it to redis which
# It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached # can improve the performance of high concurrent pushing to the same project,
# in the local file system (`/home/scanner/.cache/trivy/db/trivy.db`). In addition, the database contains the update # and reduce the database connections spike and occupies.
# timestamp so Trivy can detect whether it should download a newer version from the Internet or use the cached one. # Using redis will bring up some delay for quota usage updation for display, so only
# Currently, the database is updated every 12 hours and published as a new release to GitHub. # suggest switch provider to redis if you were ran into the db connections spike around
# # the scenario of high concurrent pushing to same project, no improvment for other scenes.
# Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough quotaUpdateProvider: db # Or redis
# for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000 # Secret is used when core server communicates with other components.
# requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult # If a secret key is not specified, Helm will generate one. Alternatively set existingSecret to use an existing secret
# https://developer.github.com/v3/#rate-limiting # Must be a string of 16 chars.
# secret: ""
# You can create a GitHub token by following the instructions in # Fill in the name of a kubernetes secret if you want to use your own
# https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line # If using existingSecret, the key must be secret
gitHubToken: '' existingSecret: ""
# skipUpdate the flag to disable Trivy DB downloads from GitHub # Fill the name of a kubernetes secret if you want to use your own
# # TLS certificate and private key for token encryption/decryption.
# You might want to set the value of this flag to `true` in test or CI/CD environments to avoid GitHub rate limiting issues. # The secret must contain keys named:
# If the value is set to `true` you have to manually download the `trivy.db` file and mount it in the # "tls.key" - the private key
# `/home/scanner/.cache/trivy/db/trivy.db` path. # "tls.crt" - the certificate
skipUpdate: false secretName: ""
resources: # If not specifying a preexisting secret, a secret can be created from tokenKey and tokenCert and used instead.
requests: # If none of secretName, tokenKey, and tokenCert are specified, an ephemeral key and certificate will be autogenerated.
cpu: 200m # tokenKey and tokenCert must BOTH be set or BOTH unset.
memory: 512Mi # The tokenKey value is formatted as a multiline string containing a PEM-encoded RSA key, indented one more than tokenKey on the following line.
limits: tokenKey: |
cpu: 1 # If tokenKey is set, the value of tokenCert must be set as a PEM-encoded certificate signed by tokenKey, and supplied as a multiline string, indented one more than tokenCert on the following line.
memory: 1Gi tokenCert: |
nodeSelector: {} # The XSRF key. Will be generated automatically if it isn't specified
tolerations: [] # While you specified, Please make sure it is 32 characters, otherwise would have validation issue at the harbor-core runtime
affinity: {} # https://github.com/registry.cn-qingdao.aliyuncs.com/wod/harbor/pull/21154
## Additional deployment annotations xsrfKey: ""
podAnnotations: {} # If using existingSecret, the key is defined by core.existingXsrfSecretKey
existingXsrfSecret: ""
notary: # If using existingSecret, the key
enabled: true existingXsrfSecretKey: CSRF_KEY
server: # The time duration for async update artifact pull_time and repository
# set the service account to be used, default if left empty # pull_count, the unit is second. Will be 10 seconds if it isn't set.
serviceAccountName: '' # eg. artifactPullAsyncFlushDuration: 10
image: artifactPullAsyncFlushDuration:
repository: notary-server gdpr:
tag: v0.6.1 deleteUser: false
replicas: 1 auditLogsCompliant: false
# resources:
# requests: jobservice:
# memory: 256Mi image:
# cpu: 100m repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-jobservice
signer: tag: v2.13.2
# set the service account to be used, default if left empty # set the service account to be used, default if left empty
serviceAccountName: '' serviceAccountName: ""
image: # mount the service account token
repository: notary-signer automountServiceAccountToken: false
tag: v0.6.1 replicas: 1
replicas: 1 revisionHistoryLimit: 10
# resources: # resources:
# requests: # requests:
# memory: 256Mi # memory: 256Mi
# cpu: 100m # cpu: 100m
nodeSelector: {} extraEnvVars: []
tolerations: [] nodeSelector: {}
affinity: {} tolerations: []
## Additional deployment annotations affinity: {}
podAnnotations: {} # Spread Pods across failure-domains like regions, availability zones or nodes
# Fill the name of a kubernetes secret if you want to use your own topologySpreadConstraints:
# TLS certificate authority, certificate and private key for notary # - maxSkew: 1
# communications. # topologyKey: topology.kubernetes.io/zone
# The secret must contain keys named ca.crt, tls.crt and tls.key that # nodeTaintsPolicy: Honor
# contain the CA, certificate and private key. # whenUnsatisfiable: DoNotSchedule
# They will be generated if not set. ## Additional deployment annotations
secretName: '' podAnnotations: {}
## Additional deployment labels
database: podLabels: {}
# if external database is used, set "type" to "external" ## The priority class to run the pod as
# and fill the connection informations in "external" section priorityClassName:
type: internal # containers to be run before the controller's container starts.
internal: initContainers: []
# set the service account to be used, default if left empty # Example:
serviceAccountName: '' #
image: # - name: wait
repository: harbor-db # image: busybox
tag: v2.1.6 # command: [ 'sh', '-c', "sleep 20" ]
# The initial superuser password for internal database maxJobWorkers: 10
password: 'spaceIN511' # The logger for jobs: "file", "database" or "stdout"
resources: jobLoggers:
limits: - file
memory: 4Gi # - database
requests: # - stdout
memory: 256Mi # The jobLogger sweeper duration (ignored if `jobLogger` is `stdout`)
nodeSelector: {} loggerSweeperDuration: 14 #days
tolerations: [] notification:
affinity: {} webhook_job_max_retry: 3
external: webhook_job_http_client_timeout: 3 # in seconds
host: '192.168.0.1' reaper:
port: '5432' # the max time to wait for a task to finish, if unfinished after max_update_hours, the task will be mark as error, but the task will continue to run, default value is 24
username: 'user' max_update_hours: 24
password: 'password' # the max time for execution in running state without new task created
coreDatabase: 'registry' max_dangling_hours: 168
clairDatabase: 'clair' # Secret is used when job service communicates with other components.
notaryServerDatabase: 'notary_server' # If a secret key is not specified, Helm will generate one.
notarySignerDatabase: 'notary_signer' # Must be a string of 16 chars.
# "disable" - No SSL secret: ""
# "require" - Always SSL (skip verification) # Use an existing secret resource
# "verify-ca" - Always SSL (verify that the certificate presented by the existingSecret: ""
# server was signed by a trusted CA) # Key within the existing secret for the job service secret
# "verify-full" - Always SSL (verify that the certification presented by the existingSecretKey: JOBSERVICE_SECRET
# server was signed by a trusted CA and the server host name matches the one
# in the certificate) registry:
sslmode: 'disable' registry:
# The maximum number of connections in the idle connection pool. image:
# If it <=0, no idle connections are retained. repository: registry.cn-qingdao.aliyuncs.com/wod/registry-photon
maxIdleConns: 50 tag: v2.13.2
# The maximum number of open connections to the database. # resources:
# If it <= 0, then there is no limit on the number of open connections. # requests:
# Note: the default number of connections is 1024 for postgre of harbor. # memory: 256Mi
maxOpenConns: 1000 # cpu: 100m
## Additional deployment annotations extraEnvVars: []
podAnnotations: {} controller:
image:
redis: repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-registryctl
# if external Redis is used, set "type" to "external" tag: v2.13.2
# and fill the connection informations in "external" section # resources:
type: internal # requests:
internal: # memory: 256Mi
# set the service account to be used, default if left empty # cpu: 100m
serviceAccountName: '' extraEnvVars: []
image: # set the service account to be used, default if left empty
repository: redis serviceAccountName: ""
tag: 6.2.6 # mount the service account token
# resources: automountServiceAccountToken: false
# requests: replicas: 1
# memory: 256Mi revisionHistoryLimit: 10
# cpu: 100m nodeSelector: {}
nodeSelector: {} tolerations: []
tolerations: [] affinity: {}
affinity: {} # Spread Pods across failure-domains like regions, availability zones or nodes
external: topologySpreadConstraints: []
# support redis, redis+sentinel # - maxSkew: 1
# addr for redis: <host_redis>:<port_redis> # topologyKey: topology.kubernetes.io/zone
# addr for redis+sentinel: <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3> # nodeTaintsPolicy: Honor
addr: '192.168.0.2:6379' # whenUnsatisfiable: DoNotSchedule
# The name of the set of Redis instances to monitor, it must be set to support redis+sentinel ## Additional deployment annotations
sentinelMasterSet: '' podAnnotations: {}
# The "coreDatabaseIndex" must be "0" as the library Harbor ## Additional deployment labels
# used doesn't support configuring it podLabels: {}
coreDatabaseIndex: '0' ## The priority class to run the pod as
jobserviceDatabaseIndex: '1' priorityClassName:
registryDatabaseIndex: '2' # containers to be run before the controller's container starts.
chartmuseumDatabaseIndex: '3' initContainers: []
clairAdapterIndex: '4' # Example:
trivyAdapterIndex: '5' #
password: '' # - name: wait
## Additional deployment annotations # image: busybox
podAnnotations: {} # command: [ 'sh', '-c', "sleep 20" ]
# Secret is used to secure the upload state from client
commonLabels: # and registry storage backend.
app.bd-apaas.com/cluster-component: registry # See: https://github.com/distribution/distribution/blob/release/2.8/docs/configuration.md#http
# If a secret key is not specified, Helm will generate one.
# Must be a string of 16 chars.
secret: ""
# Use an existing secret resource
existingSecret: ""
# Key within the existing secret for the registry service secret
existingSecretKey: REGISTRY_HTTP_SECRET
# If true, the registry returns relative URLs in Location headers. The client is responsible for resolving the correct URL.
relativeurls: false
credentials:
username: "harbor_registry_user"
password: "harbor_registry_password"
# If using existingSecret, the key must be REGISTRY_PASSWD and REGISTRY_HTPASSWD
existingSecret: ""
# Login and password in htpasswd string format. Excludes `registry.credentials.username` and `registry.credentials.password`. May come in handy when integrating with tools like argocd or flux. This allows the same line to be generated each time the template is rendered, instead of the `htpasswd` function from helm, which generates different lines each time because of the salt.
# htpasswdString: $apr1$XLefHzeG$Xl4.s00sMSCCcMyJljSZb0 # example string
htpasswdString: ""
middleware:
enabled: false
type: cloudFront
cloudFront:
baseurl: example.cloudfront.net
keypairid: KEYPAIRID
duration: 3000s
ipfilteredby: none
# The secret key that should be present is CLOUDFRONT_KEY_DATA, which should be the encoded private key
# that allows access to CloudFront
privateKeySecret: "my-secret"
# enable purge _upload directories
upload_purging:
enabled: true
# remove files in _upload directories which exist for a period of time, default is one week.
age: 168h
# the interval of the purge operations
interval: 24h
dryrun: false
trivy:
# enabled the flag to enable Trivy scanner
enabled: true
image:
# repository the repository for Trivy adapter image
repository: registry.cn-qingdao.aliyuncs.com/wod/trivy-adapter-photon
# tag the tag for Trivy adapter image
tag: v2.13.2
# set the service account to be used, default if left empty
serviceAccountName: ""
# mount the service account token
automountServiceAccountToken: false
# replicas the number of Pod replicas
replicas: 1
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1
memory: 1Gi
extraEnvVars: []
nodeSelector: {}
tolerations: []
affinity: {}
# Spread Pods across failure-domains like regions, availability zones or nodes
topologySpreadConstraints: []
# - maxSkew: 1
# topologyKey: topology.kubernetes.io/zone
# nodeTaintsPolicy: Honor
# whenUnsatisfiable: DoNotSchedule
## Additional deployment annotations
podAnnotations: {}
## Additional deployment labels
podLabels: {}
## The priority class to run the pod as
priorityClassName:
# containers to be run before the controller's container starts.
initContainers: []
# Example:
#
# - name: wait
# image: busybox
# command: [ 'sh', '-c', "sleep 20" ]
# debugMode the flag to enable Trivy debug mode with more verbose scanning log
debugMode: false
# vulnType a comma-separated list of vulnerability types. Possible values are `os` and `library`.
vulnType: "os,library"
# severity a comma-separated list of severities to be checked
severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
# ignoreUnfixed the flag to display only fixed vulnerabilities
ignoreUnfixed: false
# insecure the flag to skip verifying registry certificate
insecure: false
# gitHubToken the GitHub access token to download Trivy DB
#
# Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases.
# It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached
# in the local file system (`/home/scanner/.cache/trivy/db/trivy.db`). In addition, the database contains the update
# timestamp so Trivy can detect whether it should download a newer version from the Internet or use the cached one.
# Currently, the database is updated every 12 hours and published as a new release to GitHub.
#
# Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough
# for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000
# requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult
# https://developer.github.com/v3/#rate-limiting
#
# You can create a GitHub token by following the instructions in
# https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
gitHubToken: ""
# skipUpdate the flag to disable Trivy DB downloads from GitHub
#
# You might want to set the value of this flag to `true` in test or CI/CD environments to avoid GitHub rate limiting issues.
# If the value is set to `true` you have to manually download the `trivy.db` file and mount it in the
# `/home/scanner/.cache/trivy/db/trivy.db` path.
skipUpdate: false
# skipJavaDBUpdate If the flag is enabled you have to manually download the `trivy-java.db` file and mount it in the
# `/home/scanner/.cache/trivy/java-db/trivy-java.db` path
#
skipJavaDBUpdate: false
# The offlineScan option prevents Trivy from sending API requests to identify dependencies.
#
# Scanning JAR files and pom.xml may require Internet access for better detection, but this option tries to avoid it.
# For example, the offline mode will not try to resolve transitive dependencies in pom.xml when the dependency doesn't
# exist in the local repositories. It means a number of detected vulnerabilities might be fewer in offline mode.
# It would work if all the dependencies are in local.
# This option doesn’t affect DB download. You need to specify skipUpdate as well as offlineScan in an air-gapped environment.
offlineScan: false
# Comma-separated list of what security issues to detect. Defaults to `vuln`.
securityCheck: "vuln"
# The duration to wait for scan completion
timeout: 5m0s
database:
# if external database is used, set "type" to "external"
# and fill the connection information in "external" section
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-db
tag: v2.13.2
# set the service account to be used, default if left empty
serviceAccountName: ""
# mount the service account token
automountServiceAccountToken: false
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
# The timeout used in livenessProbe; 1 to 5 seconds
livenessProbe:
timeoutSeconds: 1
# The timeout used in readinessProbe; 1 to 5 seconds
readinessProbe:
timeoutSeconds: 1
extraEnvVars: []
nodeSelector:
kubernetes.io/hostname: 172.16.1.11
tolerations: []
affinity: {}
## The priority class to run the pod as
priorityClassName:
# containers to be run before the controller's container starts.
extrInitContainers: []
# Example:
#
# - name: wait
# image: busybox
# command: [ 'sh', '-c', "sleep 20" ]
# The initial superuser password for internal database
password: "changeit"
# The size limit for Shared memory, pgSQL use it for shared_buffer
# More details see:
# https://github.com/registry.cn-qingdao.aliyuncs.com/wod/harbor/issues/15034
shmSizeLimit: 512Mi
initContainer:
migrator: {}
# resources:
# requests:
# memory: 128Mi
# cpu: 100m
permissions: {}
# resources:
# requests:
# memory: 128Mi
# cpu: 100m
external:
host: "192.168.0.1"
port: "5432"
username: "user"
password: "password"
coreDatabase: "registry"
# if using existing secret, the key must be "password"
existingSecret: ""
# "disable" - No SSL
# "require" - Always SSL (skip verification)
# "verify-ca" - Always SSL (verify that the certificate presented by the
# server was signed by a trusted CA)
# "verify-full" - Always SSL (verify that the certification presented by the
# server was signed by a trusted CA and the server host name matches the one
# in the certificate)
sslmode: "disable"
# The maximum number of connections in the idle connection pool per pod (core+exporter).
# If it <=0, no idle connections are retained.
maxIdleConns: 100
# The maximum number of open connections to the database per pod (core+exporter).
# If it <= 0, then there is no limit on the number of open connections.
# Note: the default number of connections is 1024 for harbor's postgres.
maxOpenConns: 900
## Additional deployment annotations
podAnnotations: {}
## Additional deployment labels
podLabels: {}
redis:
# if external Redis is used, set "type" to "external"
# and fill the connection information in "external" section
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/redis-photon
tag: v2.13.2
# set the service account to be used, default if left empty
serviceAccountName: ""
# mount the service account token
automountServiceAccountToken: false
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
extraEnvVars: []
nodeSelector: {}
tolerations: []
affinity: {}
## The priority class to run the pod as
priorityClassName:
# containers to be run before the controller's container starts.
initContainers: []
# Example:
#
# - name: wait
# image: busybox
# command: [ 'sh', '-c', "sleep 20" ]
# # jobserviceDatabaseIndex defaults to "1"
# # registryDatabaseIndex defaults to "2"
# # trivyAdapterIndex defaults to "5"
# # harborDatabaseIndex defaults to "0", but it can be configured to "6", this config is optional
# # cacheLayerDatabaseIndex defaults to "0", but it can be configured to "7", this config is optional
jobserviceDatabaseIndex: "1"
registryDatabaseIndex: "2"
trivyAdapterIndex: "5"
# harborDatabaseIndex: "6"
# cacheLayerDatabaseIndex: "7"
external:
# support redis, redis+sentinel
# addr for redis: <host_redis>:<port_redis>
# addr for redis+sentinel: <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3>
addr: "192.168.0.2:6379"
# The name of the set of Redis instances to monitor, it must be set to support redis+sentinel
sentinelMasterSet: ""
# TLS configuration for redis connection
# only server-authentication is supported, mTLS for redis connection is not supported
# tls connection will be disable by default
# Once `tlsOptions.enable` set as true, tls/ssl connection will be used for redis
# Please set the `caBundleSecretName` in this configuration file which conatins redis server rootCA if it is self-signed.
# The secret must contain keys named "ca.crt" which will be injected into the trust store
tlsOptions:
enable: false
# The "coreDatabaseIndex" must be "0" as the library Harbor
# used doesn't support configuring it
# harborDatabaseIndex defaults to "0", but it can be configured to "6", this config is optional
# cacheLayerDatabaseIndex defaults to "0", but it can be configured to "7", this config is optional
coreDatabaseIndex: "0"
jobserviceDatabaseIndex: "1"
registryDatabaseIndex: "2"
trivyAdapterIndex: "5"
# harborDatabaseIndex: "6"
# cacheLayerDatabaseIndex: "7"
# username field can be an empty string, and it will be authenticated against the default user
username: ""
password: ""
# If using existingSecret, the key must be REDIS_PASSWORD
existingSecret: ""
## Additional deployment annotations
podAnnotations: {}
## Additional deployment labels
podLabels: {}
exporter:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-exporter
tag: v2.13.2
serviceAccountName: ""
# mount the service account token
automountServiceAccountToken: false
replicas: 1
revisionHistoryLimit: 10
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
extraEnvVars: []
podAnnotations: {}
## Additional deployment labels
podLabels: {}
nodeSelector: {}
tolerations: []
affinity: {}
# Spread Pods across failure-domains like regions, availability zones or nodes
topologySpreadConstraints: []
## The priority class to run the pod as
priorityClassName:
# - maxSkew: 1
# topologyKey: topology.kubernetes.io/zone
# nodeTaintsPolicy: Honor
# whenUnsatisfiable: DoNotSchedule
cacheDuration: 23
cacheCleanInterval: 14400
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment