Commit 75fc385a authored by 吕永新's avatar 吕永新

Add version v2.1.0

parent 577a521f
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
charts/*
charts/*
requirements.lock
\ No newline at end of file
docs/*
.git/*
.gitignore
CONTRIBUTING.md
\ No newline at end of file
docs/*
.git/*
.gitignore
CONTRIBUTING.md
.travis.yaml
test/*
\ No newline at end of file
......@@ -2,7 +2,7 @@
Please follow [Harbor contributing guide](https://github.com/goharbor/harbor/blob/master/CONTRIBUTING.md) to learn how to make code contribution.
# Contributers
## Contributers
Thanks very much to all contributers who submitted pull requests to Helm Chart for Harbor.
......
apiVersion: v1
name: harbor
version: 1.1.1
appVersion: 1.8.1
version: 1.4.0-dev
appVersion: dev
description: An open source trusted cloud native registry that stores, signs, and scans content
keywords:
- docker
- registry
- harbor
home: https://goharbor.io
icon: https://raw.githubusercontent.com/goharbor/harbor/master/docs/img/harbor_logo.png
icon: https://raw.githubusercontent.com/goharbor/website/master/static/img/logos/harbor-icon-color.png
sources:
- https://github.com/goharbor/harbor
- https://github.com/goharbor/harbor-helm
maintainers:
- name: Jesse Hu
email: huh@vmware.com
- name: paulczar
email: username.taken@gmail.com
- name: Wenkai Yin
email: yinw@vmware.com
- name: Weiwei He
email: hweiwei@vmware.com
- name: Qian Deng
email: dengq@vmware.com
engine: gotpl
# harbor
## install
```bash
# 1.install
# label node
kubectl label node <nodename> harbor=enabled
helm install \
/etc/kubernetes/helm/harbor \
--name=harbor \
--namespace=devops \
-f /etc/kubernetes/helm/harbor/values-overrides.yaml
# uninstall
helm delete harbor --purge
# update
helm upgrade harbor /etc/kubernetes/helm/harbor \
-f /etc/kubernetes/helm/harbor/values-overrides.yaml
# template
helm template \
/etc/kubernetes/helm/harbor \
--name=harbor \
--namespace=harbor \
-f /etc/kubernetes/helm/harbor/values-overrides.yaml > /etc/kubernetes/helm/harbor/dist.yaml
```
## images
```bash
# goharbor/harbor-portal
docker pull goharbor/harbor-portal:v1.8.2 && \
docker tag goharbor/harbor-portal:v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-portal:v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-portal:v1.8.2
# goharbor/harbor-core
docker pull goharbor/harbor-core:v1.8.2 && \
docker tag goharbor/harbor-core:v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-core:v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-core:v1.8.2
# goharbor/harbor-jobservice
docker pull goharbor/harbor-jobservice:v1.8.2 && \
docker tag goharbor/harbor-jobservice:v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-jobservice:v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-jobservice:v1.8.2
# goharbor/harbor-db
docker pull goharbor/harbor-db:v1.8.2 && \
docker tag goharbor/harbor-db:v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-db:v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-db:v1.8.2
# registry
docker pull registry:2.7.1 && \
docker tag registry:2.7.1 registry-vpc.cn-qingdao.aliyuncs.com/wod/registry:2.7.1 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/registry:2.7.1
# goharbor/harbor-registryctl
docker pull goharbor/harbor-registryctl:v1.8.2 && \
docker tag goharbor/harbor-registryctl:v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-registryctl:v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/harbor-registryctl:v1.8.2
# goharbor/chartmuseum-photon
docker pull goharbor/chartmuseum-photon:v0.9.0-v1.8.2 && \
docker tag goharbor/chartmuseum-photon:v0.9.0-v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/chartmuseum-photon:v0.9.0-v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/chartmuseum-photon:v0.9.0-v1.8.2
# goharbor/clair-photon
docker pull goharbor/clair-photon:v2.0.8-v1.8.2 && \
docker tag goharbor/clair-photon:v2.0.8-v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/clair-photon:v2.0.8-v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/clair-photon:v2.0.8-v1.8.2
# goharbor/notary-server-photon
docker pull goharbor/notary-server-photon:v0.6.1-v1.8.2 && \
docker tag goharbor/notary-server-photon:v0.6.1-v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/notary-server-photon:v0.6.1-v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/notary-server-photon:v0.6.1-v1.8.2
# goharbor/notary-signer-photon
docker pull goharbor/notary-signer-photon:v0.6.1-v1.8.2 && \
docker tag goharbor/notary-signer-photon:v0.6.1-v1.8.2 registry-vpc.cn-qingdao.aliyuncs.com/wod/notary-signer-photon:v0.6.1-v1.8.2 && \
docker push registry-vpc.cn-qingdao.aliyuncs.com/wod/notary-signer-photon:v0.6.1-v1.8.2
```
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
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 }}/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
# Harbor High Availability Guide
---
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.8.0+
- 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)
## Installation
## Usage
### Download Chart
Download Harbor helm chart code.
Download Harbor helm chart:
```bash
git clone https://github.com/goharbor/harbor-helm
cd harbor-helm
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**
- **Ingress rule**
Configure the `expose.ingress.hosts.core` and `expose.ingress.hosts.notary`.
- **External URL**
- **External URL**
Configure the `externalURL`.
- **External PostgreSQL**
Set the `database.type` to `external` and fill the information in `database.external` section.
- **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.
- **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.
- **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 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.
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`.
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`.
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**
- **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`:
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 .
```
# Upgrade Guide
---
title: Upgrade Guide
---
This guide is used to upgrade Harbor deployed by chart since version 0.3.0.
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
## 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:
```
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:
```
kubectl get secret secret-name -o yaml > secret.yaml
```
Replace the `secret-name` with the one got in step i
3) Rename the secret by setting `metadata.name` in `secret.yaml`
4) Create a new secret:
```
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 iii
4. **Upgrade**
Run upgrade command:
### 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
```
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).
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.
- 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
......@@ -2,14 +2,16 @@
**Notes:** The master branch is in heavy development, please use the other stable versions instead. A high available solution for Harbor based on chart can be find [here](docs/High%20Availability.md). And refer to the [guide](docs/Upgrade.md) to upgrade the existing deployment.
This repository, including the issues, focus on deploying Harbor chart via helm. So for the functionality issues or questions of Harbor, please open issues on [goharbor/harbor](https://github.com/goharbor/harbor)
## Introduction
This [Helm](https://github.com/kubernetes/helm) chart installs [Harbor](https://github.com/goharbor/harbor) in a Kubernetes cluster. Welcome to [contribute](CONTRIBUTING.md) to Helm Chart for Harbor.
## Prerequisites
- Kubernetes cluster 1.10+
- Helm 2.8.0+
- Kubernetes cluster 1.16+
- Helm 2.10.0+
## Installation
......@@ -21,15 +23,15 @@ helm repo add harbor https://helm.goharbor.io
### Configure the chart
The following items can be set via `--set` flag during installation or configured by editing the `values.yaml` directly(need to download the chart first).
The following items can be set via `--set` flag during installation or configured by editing the `values.yaml` directly(need to download the chart first).
#### Configure the way how to expose Harbor service:
#### Configure the way how to expose Harbor service
- **Ingress**: The ingress controller must be installed in the Kubernetes cluster.
- **Ingress**: The ingress controller must be installed in the Kubernetes cluster.
**Notes:** if the TLS is disabled, the port must be included in the command when pulling/pushing images. Refer to issue [#5291](https://github.com/goharbor/harbor/issues/5291) for the detail.
- **ClusterIP**: Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster.
- **NodePort**: Exposes the service on each Node’s IP at a static port (the NodePort). You’ll be able to contact the NodePort service, from outside the cluster, by requesting `NodeIP:NodePort`.
- **LoadBalancer**: Exposes the service externally using a cloud provider’s load balancer.
- **NodePort**: Exposes the service on each Node’s IP at a static port (the NodePort). You’ll be able to contact the NodePort service, from outside the cluster, by requesting `NodeIP:NodePort`.
- **LoadBalancer**: Exposes the service externally using a cloud provider’s load balancer.
#### Configure the external URL
......@@ -43,43 +45,43 @@ Format: `protocol://domain[:port]`. Usually:
- if expose the service via `Ingress`, the `domain` should be the value of `expose.ingress.hosts.core`
- if expose the service via `ClusterIP`, the `domain` should be the value of `expose.clusterIP.name`
- if expose the service via `NodePort`, the `domain` should be the IP address of one Kubernetes node
- if expose the service via `LoadBalancer`, set the `domain` as your own domain name and add a CNAME record to map the domain name to the one you got from the cloud provider
- if expose the service via `LoadBalancer`, set the `domain` as your own domain name and add a CNAME record to map the domain name to the one you got from the cloud provider
If Harbor is deployed behind the proxy, set it as the URL of proxy.
#### Configure the way how to persistent data:
#### Configure the way how to persistent data
- **Disable**: The data does not survive the termination of a pod.
- **Persistent Volume Claim(default)**: A default `StorageClass` is needed in the Kubernetes cluster to dynamic provision the volumes. Specify another StorageClass in the `storageClass` or set `existingClaim` if you have already existing persistent volumes to use.
- **External Storage(only for images and charts)**: For images and charts, the external storages are supported: `azure`, `gcs`, `s3` `swift` and `oss`.
#### Configure the secrets
- **Secret keys**: Secret keys are used for secure communication between components. Fill `core.secret`, `jobservice.secret` and `registry.secret` to configure.
- **Certificates**:
- *notary*: Used for authentication during communications. Fill `notary.secretName` to configure. Notary server certificate must be issued with notary service name as subject alternative name.
- *core*: Used for token encryption/decryption. Fill `core.secretName` to configure.
Secrets and certificates must be setup to avoid changes on every Helm upgrade (see: [#107](https://github.com/goharbor/harbor-helm/issues/107)).
#### Configure the other items listed in [configuration](#configuration) section.
#### Configure the other items listed in [configuration](#configuration) section
### Install the chart
Install the Harbor helm chart with a release name `my-release`:
helm 2:
```bash
helm install --name my-release harbor/harbor
```
helm 3:
```bash
helm install my-release harbor/harbor
```
## Uninstallation
To uninstall/delete the `my-release` deployment:
helm 2:
```bash
helm delete --purge my-release
```
helm 3:
```
helm uninstall my-release
```
## Configuration
......@@ -87,35 +89,63 @@ The following table lists the configurable parameters of the Harbor chart and th
| Parameter | Description | Default |
| --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| **Expose** |
| `expose.type` | The way how to expose the service: `ingress`, `clusterIP`, `nodePort` or `loadBalancer`, other values will be ignored and the creation of service will be skipped. | `ingress` |
| `expose.tls.enabled` | Enable the tls or not | `true` |
| **Expose** |
| `expose.type` | The way how to expose the service: `ingress`, `clusterIP`, `nodePort` or `loadBalancer`, other values will be ignored and the creation of service will be skipped. | `ingress` |
| `expose.tls.enabled` | Enable the tls or not | `true` |
| `expose.tls.certSource` | 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 | `auto` |
| `expose.tls.auto.commonName` | The common name used to generate the certificate, it's necessary when the type isn't `ingress` | |
| `expose.tls.secret.secretName` | The name of secret which contains keys named: `tls.crt` - the certificate; `tls.key` - the private key | |
| `expose.tls.secret.notarySecretName` | 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` | |
| `expose.ingress.hosts.core` | The host of Harbor core service in ingress rule | `core.harbor.domain` |
| `expose.ingress.hosts.notary` | The host of Harbor Notary service in ingress rule | `notary.harbor.domain` |
| `expose.ingress.controller` | The ingress controller type. Currently supports `default`, `gce` and `ncp` | `default` |
| `expose.tls.secretName` | Fill the name of secret if you want to use your own TLS certificate and private key. The secret must contain keys named `tls.crt` and `tls.key` that contain the certificate and private key to use for TLS. The certificate and private key will be generated automatically if it is not set | |
| `expose.tls.notarySecretName` | By default, the Notary service will use the same cert and key as described above. Fill the name of secret if you want to use a separated one. Only needed when the `expose.type` is `ingress`. | |
| `expose.tls.commonName` | The common name used to generate the certificate, it's necessary when the `expose.type` is `clusterIP` or `nodePort` and `expose.tls.secretName` is null | |
| `expose.ingress.hosts.core` | The host of Harbor core service in ingress rule | `core.harbor.domain` |
| `expose.ingress.hosts.notary` | The host of Harbor Notary service in ingress rule | `notary.harbor.domain` |
| `expose.ingress.annotations` | The annotations used in ingress | |
| `expose.clusterIP.name` | The name of ClusterIP service | `harbor` |
| `expose.clusterIP.ports.httpPort` | The service port Harbor listens on when serving with HTTP | `80` |
| `expose.clusterIP.ports.httpsPort` | The service port Harbor listens on when serving with HTTPS | `443` |
| `expose.clusterIP.ports.notaryPort` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true` | `4443` |
| `expose.nodePort.name` | The name of NodePort service | `harbor` |
| `expose.nodePort.ports.http.port` | The service port Harbor listens on when serving with HTTP | `80` |
| `expose.nodePort.ports.http.nodePort` | The node port Harbor listens on when serving with HTTP | `30002` |
| `expose.nodePort.ports.https.port` | The service port Harbor listens on when serving with HTTPS | `443` |
| `expose.nodePort.ports.https.nodePort` | The node port Harbor listens on when serving with HTTPS | `30003` |
| `expose.nodePort.ports.notary.port` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true` | `4443` |
| `expose.nodePort.ports.notary.nodePort` | The node port Notary listens on. Only needed when `notary.enabled` is set to `true` | `30004` |
| `expose.ingress.annotations` | The annotations used in ingress | |
| `expose.clusterIP.name` | The name of ClusterIP service | `harbor` |
| `expose.clusterIP.ports.httpPort` | The service port Harbor listens on when serving with HTTP | `80` |
| `expose.clusterIP.ports.httpsPort` | The service port Harbor listens on when serving with HTTPS | `443` |
| `expose.clusterIP.ports.notaryPort` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true` | `4443` |
| `expose.nodePort.name` | The name of NodePort service | `harbor` |
| `expose.nodePort.ports.http.port` | The service port Harbor listens on when serving with HTTP | `80` |
| `expose.nodePort.ports.http.nodePort` | The node port Harbor listens on when serving with HTTP | `30002` |
| `expose.nodePort.ports.https.port` | The service port Harbor listens on when serving with HTTPS | `443` |
| `expose.nodePort.ports.https.nodePort` | The node port Harbor listens on when serving with HTTPS | `30003` |
| `expose.nodePort.ports.notary.port` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true` | `4443` |
| `expose.nodePort.ports.notary.nodePort` | The node port Notary listens on. Only needed when `notary.enabled` is set to `true` | `30004` |
| `expose.loadBalancer.name` | The name of service |`harbor`|
| `expose.loadBalancer.IP` | The IP of the loadBalancer. It works only when loadBalancer support assigning IP |`""`|
| `expose.loadBalancer.ports.httpPort` | The service port Harbor listens on when serving with HTTP |`80`|
| `expose.loadBalancer.ports.httpsPort` | The service port Harbor listens on when serving with HTTP |`30002`|
| `expose.loadBalancer.ports.httpsPort` | The service port Harbor listens on when serving with HTTPS |`30002`|
| `expose.loadBalancer.ports.notaryPort` | The service port Notary listens on. Only needed when `notary.enabled` is set to `true`|
| `expose.loadBalancer.annotations` | The annotations attached to the loadBalancer service | {} |
| `expose.loadBalancer.sourceRanges` | List of IP address ranges to assign to loadBalancerSourceRanges | [] |
| **Internal TLS** |
| `internalTLS.enabled` | Enable the tls for the components (chartmuseum, clair, core, jobservice, portal, registry, trivy) | `false` |
| `internalTLS.certSource` | Method to provide tls for the components, options is `auto`, `manual`, `secret`. | `auto` |
| `internalTLS.trustCa` | The content of trust ca, only available when `certSrouce` is `manual`. **Note**: all the internal certificates of the components must be issued by this ca | |
| `internalTLS.core.secretName` | The secret name for core component, only available when `certSource` is `secret`. The secret must contain keys named: `ca.crt` - the certificate of CA which is used to issue internal key and crt pair for components and all Harbor components must issued by the same CA , `tls.crt` - the content of the TLS cert file, `tls.key` - the content of the TLS key file. | |
| `internalTLS.core.crt` | Content of core's TLS cert file, only available when `certSource` is `manual` | |
| `internalTLS.core.key` | Content of core's TLS key file, only available when `certSource` is `manual` | |
| `internalTLS.jobservice.secretName` | The secret name for jobservice component, only available when `certSource` is `secret`. The secret must contain keys named: `ca.crt` - the certificate of CA which is used to issue internal key and crt pair for components and all Harbor components must issued by the same CA , `tls.crt` - the content of the TLS cert file, `tls.key` - the content of the TLS key file. | |
| `internalTLS.jobservice.crt` | Content of jobservice's TLS cert file, only available when `certSource` is `manual` | |
| `internalTLS.jobservice.key` | Content of jobservice's TLS key file, only available when `certSource` is `manual` | |
| `internalTLS.registry.secretName` | The secret name for registry component, only available when `certSource` is `secret`. The secret must contain keys named: `ca.crt` - the certificate of CA which is used to issue internal key and crt pair for components and all Harbor components must issued by the same CA , `tls.crt` - the content of the TLS cert file, `tls.key` - the content of the TLS key file. | |
| `internalTLS.registry.crt` | Content of registry's TLS cert file, only available when `certSource` is `manual` | |
| `internalTLS.registry.key` | Content of registry's TLS key file, only available when `certSource` is `manual` | |
| `internalTLS.portal.secretName` | The secret name for portal component, only available when `certSource` is `secret`. The secret must contain keys named: `ca.crt` - the certificate of CA which is used to issue internal key and crt pair for components and all Harbor components must issued by the same CA , `tls.crt` - the content of the TLS cert file, `tls.key` - the content of the TLS key file. | |
| `internalTLS.portal.crt` | Content of portal's TLS cert file, only available when `certSource` is `manual` | |
| `internalTLS.portal.key` | Content of portal's TLS key file, only available when `certSource` is `manual` | |
| `internalTLS.chartmuseum.secretName` | The secret name for chartmuseum component, only available when `certSource` is `secret`. The secret must contain keys named: `ca.crt` - the certificate of CA which is used to issue internal key and crt pair for components and all Harbor components must issued by the same CA , `tls.crt` - the content of the TLS cert file, `tls.key` - the content of the TLS key file. | |
| `internalTLS.chartmuseum.crt` | Content of chartmuseum's TLS cert file, only available when `certSource` is `manual` | |
| `internalTLS.chartmuseum.key` | Content of chartmuseum's TLS key file, only available when `certSource` is `manual` | |
| `internalTLS.clair.secretName` | The secret name for clair component, only available when `certSource` is `secret`. The secret must contain keys named: `ca.crt` - the certificate of CA which is used to issue internal key and crt pair for components and all Harbor components must issued by the same CA , `tls.crt` - the content of the TLS cert file, `tls.key` - the content of the TLS key file. | |
| `internalTLS.clair.crt` | Content of clair's TLS cert file, only available when `certSource` is `manual` | |
| `internalTLS.clair.key` | Content of clair's TLS key file, only available when `certSource` is `manual` | |
| `internalTLS.trivy.secretName` | The secret name for trivy component, only available when `certSource` is `secret`. The secret must contain keys named: `ca.crt` - the certificate of CA which is used to issue internal key and crt pair for components and all Harbor components must issued by the same CA , `tls.crt` - the content of the TLS cert file, `tls.key` - the content of the TLS key file. | |
| `internalTLS.trivy.crt` | Content of trivy's TLS cert file, only available when `certSource` is `manual` | |
| `internalTLS.trivy.key` | Content of trivy's TLS key file, only available when `certSource` is `manual` | |
| **Persistence** |
| `persistence.enabled` | Enable the data persistence or not | `true` |
| `persistence.resourcePolicy` | Setting it to `keep` to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted | `keep` |
| `persistence.resourcePolicy` | Setting it to `keep` to avoid removing PVCs during a helm delete operation. Leaving it empty will delete PVCs after the chart deleted. Does not affect PVCs created for internal database and redis components. | `keep` |
| `persistence.persistentVolumeClaim.registry.existingClaim` | Use the existing PVC which must be created manually before bound, and specify the `subPath` if the PVC is shared with other components | |
| `persistence.persistentVolumeClaim.registry.storageClass` | Specify the `storageClass` used to provision the volume. Or the default StorageClass will be used(the default). Set it to `-` to disable dynamic provisioning | |
| `persistence.persistentVolumeClaim.registry.subPath` | The sub path used in the volume | |
......@@ -142,13 +172,23 @@ The following table lists the configurable parameters of the Harbor chart and th
| `persistence.persistentVolumeClaim.redis.accessMode` | The access mode of the volume. If external Redis is used, the setting will be ignored | `ReadWriteOnce` |
| `persistence.persistentVolumeClaim.redis.size` | The size of the volume. If external Redis is used, the setting will be ignored | `1Gi` |
| `persistence.imageChartStorage.disableredirect` | The configuration for managing redirects from content backends. For backends which not supported it (such as using minio for `s3` storage type), please set it to `true` to disable redirects. Refer to the [guide](https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect) for more information about the detail | `false` |
| `persistence.imageChartStorage.caBundleSecretName` | 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. | |
| `persistence.imageChartStorage.type` | The type of storage for images and charts: `filesystem`, `azure`, `gcs`, `s3`, `swift` or `oss`. The type must be `filesystem` if you want to use persistent volumes for registry and chartmuseum. Refer to the [guide](https://github.com/docker/distribution/blob/master/docs/configuration.md#storage) for more information about the detail | `filesystem` |
| **General** |
| `externalURL` | The external URL for Harbor core service | `https://core.harbor.domain` |
| `imagePullPolicy` | The image pull policy | `IfNotPresent` |
| `logLevel` | The log level | `debug` |
| `harborAdminPassword` | The initial password of Harbor admin. Change it from portal after launching Harbor | `Harbor12345` |
| `secretkey` | The key used for encryption. Must be a string of 16 chars | `not-a-secure-key` |
| `caBundleSecretName` | The custom ca bundle secret name, the secret must contain key named "ca.crt" which will be injected into the trust store for chartmuseum, clair, core, jobservice, registry, trivy components. | |
| `uaaSecretName` | If using external UAA auth which has a self signed cert, you can provide a pre-created secret containing it under the key `ca.crt`. | |
| `imagePullPolicy` | The image pull policy | |
| `imagePullSecrets` | The imagePullSecrets names for all deployments | |
| `updateStrategy.type` | 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 | `RollingUpdate` |
| `logLevel` | The log level: `debug`, `info`, `warning`, `error` or `fatal` | `info` |
| `harborAdminPassword` | The initial password of Harbor admin. Change it from portal after launching Harbor | `Harbor12345` |
| `caSecretName` | 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 | |
| `secretkey` | The key used for encryption. Must be a string of 16 chars | `not-a-secure-key` |
| `proxy.httpProxy` | The URL of the HTTP proxy server | |
| `proxy.httpsProxy` | The URL of the HTTPS proxy server | |
| `proxy.noProxy` | The URLs that the proxy settings not apply to | 127.0.0.1,localhost,.local,.internal |
| `proxy.components` | The component list that the proxy settings apply to | core, jobservice, clair |
| **Nginx** (if expose the service via `ingress`, the Nginx will not be used) |
| `nginx.image.repository` | Image repository | `goharbor/nginx-photon` |
| `nginx.image.tag` | Image tag | `dev` |
......@@ -167,17 +207,19 @@ The following table lists the configurable parameters of the Harbor chart and th
| `portal.tolerations` | Tolerations for pod assignment | `[]` |
| `portal.affinity` | Node/Pod affinities | `{}` |
| `portal.podAnnotations` | Annotations to add to the portal pod | `{}` |
| **Core** |
| `core.image.repository` | Repository for Harbor core image | `goharbor/harbor-core` |
| `core.image.tag` | Tag for Harbor core image | `dev` |
| `core.replicas` | The replica count | `1` |
| `core.resources` | The [resources] to allocate for container | undefined |
| `core.nodeSelector` | Node labels for pod assignment | `{}` |
| `core.tolerations` | Tolerations for pod assignment | `[]` |
| `core.affinity` | Node/Pod affinities | `{}` |
| `core.podAnnotations` | Annotations to add to the core pod | `{}` |
| `core.secret` | 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. | |
| `core.secretName` | 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 and `tls.key` - the private key. The default key pair will be used if it isn't set | |
| **Core** |
| `core.image.repository` | Repository for Harbor core image | `goharbor/harbor-core` |
| `core.image.tag` | Tag for Harbor core image | `dev` |
| `core.replicas` | The replica count | `1` |
| `core.startupProbe.initialDelaySeconds` | The initial delay in seconds for the startup probe | `10` |
| `core.resources` | The [resources] to allocate for container | undefined |
| `core.nodeSelector` | Node labels for pod assignment | `{}` |
| `core.tolerations` | Tolerations for pod assignment | `[]` |
| `core.affinity` | Node/Pod affinities | `{}` |
| `core.podAnnotations` | Annotations to add to the core pod | `{}` |
| `core.secret` | 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. | |
| `core.secretName` | 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 and `tls.key` - the private key. The default key pair will be used if it isn't set | |
| `core.xsrfKey` | The XSRF key. Will be generated automatically if it isn't specified | |
| **Jobservice** |
| `jobservice.image.repository` | Repository for jobservice image | `goharbor/harbor-jobservice` |
| `jobservice.image.tag` | Tag for jobservice image | `dev` |
......@@ -201,10 +243,15 @@ The following table lists the configurable parameters of the Harbor chart and th
| `registry.nodeSelector` | Node labels for pod assignment | `{}` |
| `registry.tolerations` | Tolerations for pod assignment | `[]` |
| `registry.affinity` | Node/Pod affinities | `{}` |
| `registry.middleware` | Middleware is used to add support for a CDN between backend storage and `docker pull` recipient. See [official docs](https://github.com/docker/distribution/blob/master/docs/configuration.md#middleware).
| `registry.podAnnotations` | Annotations to add to the registry pod | `{}` |
| `registry.secret` | 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. | |
| `registry.secret` | Secret is used to secure the upload state from client and registry storage backend. See [official docs](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. | |
| `registry.credentials.username` | The username for accessing the registry instance, which is hosted by htpasswd auth mode. More details see [official docs](https://github.com/docker/distribution/blob/master/docs/configuration.md#htpasswd). | `harbor_registry_user` |
| `registry.credentials.password` | The password for accessing the registry instance, which is hosted by htpasswd auth mode. More details see [official docs](https://github.com/docker/distribution/blob/master/docs/configuration.md#htpasswd). It is suggested you update this value before installation. | `harbor_registry_password` |
| `registry.credentials.htpasswd` | The content of htpasswd file based on the value of `registry.credentials.username` `registry.credentials.password`. Currently `helm` does not support bcrypt in the template script, if the credential is updated you need to manually generated by calling [htpasswd](https://httpd.apache.org/docs/2.4/programs/htpasswd.html): `htpasswd -nbBC10 $username $password`. More details see [official_docs](https://github.com/docker/distribution/blob/master/docs/configuration.md#htpasswd).| `harbor_registry_user:$2y$10$9L4Tc0DJbFFMB6RdSCunrOpTHdwhid4ktBJmLD00bYgqkkGOvll3m` |
| **Chartmuseum** |
| `chartmuseum.enabled` | Enable chartmusuem to store chart | `true` |
| `chartmuseum.absoluteUrl` | If true, ChartMuseum will return absolute URLs. The default behavior is to return relative URLs | `false` |
| `chartmuseum.image.repository` | Repository for chartmuseum image | `goharbor/chartmuseum-photon` |
| `chartmuseum.image.tag` | Tag for chartmuseum image | `dev` |
| `chartmuseum.replicas` | The replica count | `1` |
......@@ -213,19 +260,33 @@ The following table lists the configurable parameters of the Harbor chart and th
| `chartmuseum.tolerations` | Tolerations for pod assignment | `[]` |
| `chartmuseum.affinity` | Node/Pod affinities | `{}` |
| `chartmuseum.podAnnotations` | Annotations to add to the chart museum pod | `{}` |
| **Clair** |
| `clair.enabled` | Enable Clair | `true` |
| `clair.image.repository` | Repository for clair image | `goharbor/clair-photon` |
| `clair.image.tag` | Tag for clair image | `dev` |
| `clair.replicas` | The replica count | `1` |
| `clair.httpProxy` | The HTTP proxy used to update vulnerabilities database from internet | |
| `clair.httpsProxy` | The HTTPS proxy used to update vulnerabilities database from internet | |
| `clair.updatersInterval` | The interval of clair updaters, the unit is hour, set to 0 to disable the updaters | `12` |
| `clair.resources` | The [resources] to allocate for container | undefined |
| `clair.nodeSelector` | Node labels for pod assignment | `{}` |
| `clair.tolerations` | Tolerations for pod assignment | `[]` |
| `clair.affinity` | Node/Pod affinities | `{}` |
| `clair.podAnnotations` | Annotations to add to the clair pod | `{}` |
| **Clair** |
| `clair.enabled` | Enable Clair | `true` |
| `clair.clair.image.repository` | Repository for clair image | `goharbor/clair-photon` |
| `clair.clair.image.tag` | Tag for clair image | `dev` |
| `clair.clair.resources` | The [resources] to allocate for clair container | |
| `clair.adapter.image.repository` | Repository for clair adapter image | `goharbor/clair-adapter-photon` |
| `clair.adapter.image.tag` | Tag for clair adapter image | `dev` |
| `clair.adapter.resources` | The [resources] to allocate for clair adapter container | |
| `clair.replicas` | The replica count | `1` |
| `clair.updatersInterval` | The interval of clair updaters, the unit is hour, set to 0 to disable the updaters | `12` |
| `clair.nodeSelector` | Node labels for pod assignment | `{}` |
| `clair.tolerations` | Tolerations for pod assignment | `[]` |
| `clair.affinity` | Node/Pod affinities | `{}` |
| `clair.podAnnotations` | Annotations to add to the clair pod | `{}` |
| **[Trivy][trivy]** |
| `trivy.enabled` | The flag to enable Trivy scanner | `true` |
| `trivy.image.repository` | Repository for Trivy adapter image | `goharbor/trivy-adapter-photon` |
| `trivy.image.tag` | Tag for Trivy adapter image | `dev` |
| `trivy.resources` | The [resources] to allocate for Trivy adapter container | |
| `trivy.replicas` | The number of Pod replicas | `1` |
| `trivy.debugMode` | The flag to enable Trivy debug mode | `false` |
| `trivy.vulnType` | Comma-separated list of vulnerability types. Possible values `os` and `library`. | `os,library` |
| `trivy.severity` | Comma-separated list of severities to be checked | `UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL` |
| `trivy.ignoreUnfixed` | The flag to display only fixed vulnerabilities | `false` |
| `trivy.insecure` | The flag to skip verifying registry certificate | `false` |
| `trivy.skipUpdate` | The flag to disable [Trivy DB][trivy-db] downloads from GitHub | `false` |
| `trivy.gitHubToken` | The GitHub access token to download [Trivy DB][trivy-db] (see [GitHub rate limiting][trivy-rate-limiting]) | |
| **Notary** |
| `notary.enabled` | Enable Notary? | `true` |
| `notary.server.image.repository` | Repository for notary server image | `goharbor/notary-server-photon` |
......@@ -241,10 +302,10 @@ The following table lists the configurable parameters of the Harbor chart and th
| `notary.affinity` | Node/Pod affinities | `{}` |
| `notary.podAnnotations` | Annotations to add to the notary pod | `{}` |
| `notary.secretName` | 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 `tls.ca`, `tls.crt` and `tls.key` that contain the CA, certificate and private key. They will be generated if not set. | |
| **Database** |
| `database.type` | If external database is used, set it to `external` | `internal` |
| `database.internal.image.repository` | Repository for database image | `goharbor/harbor-db` |
| `database.internal.image.tag` | Tag for database image | `dev` |
| **Database** |
| `database.type` | If external database is used, set it to `external` | `internal` |
| `database.internal.image.repository` | Repository for database image | `goharbor/harbor-db` |
| `database.internal.image.tag` | Tag for database image | `dev` |
| `database.internal.password` | The password for database | `changeit` |
| `database.internal.resources` | The [resources] to allocate for container | undefined |
| `database.internal.nodeSelector` | Node labels for pod assignment | `{}` |
......@@ -258,23 +319,30 @@ The following table lists the configurable parameters of the Harbor chart and th
| `database.external.clairDatabase` | The database used by clair | `clair` |
| `database.external.notaryServerDatabase` | The database used by Notary server | `notary_server` |
| `database.external.notarySignerDatabase` | The database used by Notary signer | `notary_signer` |
| `database.external.sslmode` | Connection method of external database (require | prefer | disable) | `disable` |
| `database.external.sslmode` | Connection method of external database (require, verify-full, verify-ca, disable) | `disable` |
| `database.maxIdleConns` | The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained. | `50` |
| `database.maxOpenConns` | The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections. | `100` |
| `database.podAnnotations` | Annotations to add to the database pod | `{}` |
| **Redis** |
| `redis.type` | If external redis is used, set it to `external` | `internal` |
| `redis.internal.image.repository` | Repository for redis image | `goharbor/redis-photon` |
| `redis.internal.image.tag` | Tag for redis image | `dev` |
| `redis.internal.resources` | The [resources] to allocate for container | undefined |
| `redis.internal.nodeSelector` | Node labels for pod assignment | `{}` |
| `redis.internal.tolerations` | Tolerations for pod assignment | `[]` |
| `redis.internal.affinity` | Node/Pod affinities | `{}` |
| `redis.external.host` | The hostname of external Redis | `192.168.0.2` |
| `redis.external.port` | The port of external Redis | `6379` |
| `redis.external.coreDatabaseIndex` | The database index for core | `0` |
| `redis.external.jobserviceDatabaseIndex` | The database index for jobservice | `1` |
| `redis.external.registryDatabaseIndex` | The database index for registry | `2` |
| `redis.external.chartmuseumDatabaseIndex` | The database index for chartmuseum | `3` |
| `redis.external.password` | The password of external Redis | |
| `redis.podAnnotations` | Annotations to add to the redis pod | `{}` |
| **Redis** |
| `redis.type` | If external redis is used, set it to `external` | `internal` |
| `redis.internal.image.repository` | Repository for redis image | `goharbor/redis-photon` |
| `redis.internal.image.tag` | Tag for redis image | `dev` |
| `redis.internal.resources` | The [resources] to allocate for container | undefined |
| `redis.internal.nodeSelector` | Node labels for pod assignment | `{}` |
| `redis.internal.tolerations` | Tolerations for pod assignment | `[]` |
| `redis.internal.affinity` | Node/Pod affinities | `{}` |
| `redis.external.addr` | The addr of external Redis: <host_redis>:<port_redis>. When using sentinel, it should be <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3> | `192.168.0.2:6379` |
| `redis.external.sentinelMasterSet` | The name of the set of Redis instances to monitor | |
| `redis.external.coreDatabaseIndex` | The database index for core | `0` |
| `redis.external.jobserviceDatabaseIndex` | The database index for jobservice | `1` |
| `redis.external.registryDatabaseIndex` | The database index for registry | `2` |
| `redis.external.chartmuseumDatabaseIndex` | The database index for chartmuseum | `3` |
| `redis.external.clairAdapterIndex` | The database index for clair adapter | `4` |
| `redis.external.trivyAdapterIndex` | The database index for trivy adapter | `5` |
| `redis.external.password` | The password of external Redis | |
| `redis.podAnnotations` | Annotations to add to the redis pod | `{}` |
[resources]: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
[trivy]: https://github.com/aquasecurity/trivy
[trivy-db]: https://github.com/aquasecurity/trivy-db
[trivy-rate-limiting]: https://github.com/aquasecurity/trivy#github-rate-limiting
Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at {{ .Values.externalURL }}.
For more details, please visit https://github.com/goharbor/harbor.
\ No newline at end of file
Then you should be able to visit the Harbor portal at {{ .Values.externalURL }}
For more details, please visit https://github.com/goharbor/harbor
......@@ -13,7 +13,7 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
*/}}
{{- define "harbor.fullname" -}}
{{- $name := default "harbor" .Values.nameOverride -}}
{{- printf "%s" .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/* Helm required labels */}}
......@@ -21,6 +21,7 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
chart: {{ .Chart.Name }}
app: "{{ template "harbor.name" . }}"
{{- end -}}
{{/* matchLabels */}}
......@@ -30,7 +31,7 @@ app: "{{ template "harbor.name" . }}"
{{- end -}}
{{- define "harbor.autoGenCert" -}}
{{- if and .Values.expose.tls.enabled (not .Values.expose.tls.secretName) -}}
{{- if and .Values.expose.tls.enabled (eq .Values.expose.tls.certSource "auto") -}}
{{- printf "true" -}}
{{- else -}}
{{- printf "false" -}}
......@@ -145,90 +146,90 @@ postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.datab
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 -}}
{{- define "harbor.redis.host" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- template "harbor.redis" . -}}
{{- else -}}
{{- .Values.redis.external.host -}}
{{- end -}}
{{- define "harbor.redis.scheme" -}}
{{- with .Values.redis }}
{{- ternary "redis+sentinel" "redis" (and (eq .type "external" ) (not (not .external.sentinelMasterSet))) }}
{{- end }}
{{- end -}}
{{- define "harbor.redis.port" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "6379" -}}
{{- else -}}
{{- .Values.redis.external.port -}}
{{- end -}}
/*host:port*/
{{- define "harbor.redis.addr" -}}
{{- with .Values.redis }}
{{- ternary (printf "%s:6379" (include "harbor.redis" $ )) .external.addr (eq .type "internal") }}
{{- end }}
{{- end -}}
{{- define "harbor.redis.coreDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "0" }}
{{- else -}}
{{- .Values.redis.external.coreDatabaseIndex -}}
{{- end -}}
{{- define "harbor.redis.masterSet" -}}
{{- with .Values.redis }}
{{- ternary .external.sentinelMasterSet "" (eq "redis+sentinel" (include "harbor.redis.scheme" $)) }}
{{- end }}
{{- end -}}
{{- define "harbor.redis.jobserviceDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "1" }}
{{- else -}}
{{- .Values.redis.external.jobserviceDatabaseIndex -}}
{{- end -}}
{{- define "harbor.redis.password" -}}
{{- with .Values.redis }}
{{- ternary "" .external.password (eq .type "internal") }}
{{- end }}
{{- end -}}
{{- define "harbor.redis.registryDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "2" }}
{{- else -}}
{{- .Values.redis.external.registryDatabaseIndex -}}
{{- end -}}
/*scheme://[redis:password@]host:port[/master_set]*/
{{- define "harbor.redis.url" -}}
{{- with .Values.redis }}
{{- $path := ternary "" (printf "/%s" (include "harbor.redis.masterSet" $)) (not (include "harbor.redis.masterSet" $)) }}
{{- $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 -}}
{{- end }}
{{- end -}}
{{- define "harbor.redis.chartmuseumDatabaseIndex" -}}
{{- if eq .Values.redis.type "internal" -}}
{{- printf "%s" "3" }}
{{- else -}}
{{- .Values.redis.external.chartmuseumDatabaseIndex -}}
{{- end -}}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForCore" -}}
{{- with .Values.redis }}
{{- $index := ternary "0" .external.coreDatabaseIndex (eq .type "internal") }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- end }}
{{- end -}}
{{- define "harbor.redis.rawPassword" -}}
{{- if and (eq .Values.redis.type "external") .Values.redis.external.password -}}
{{- .Values.redis.external.password -}}
{{- end -}}
/*scheme://[redis:password@]addr/db_index*/
{{- define "harbor.redis.urlForJobservice" -}}
{{- with .Values.redis }}
{{- $index := ternary "1" .external.jobserviceDatabaseIndex (eq .type "internal") }}
{{- printf "%s/%s" (include "harbor.redis.url" $) $index -}}
{{- end }}
{{- end -}}
{{- define "harbor.redis.escapedRawPassword" -}}
{{- if (include "harbor.redis.rawPassword" . ) -}}
{{- include "harbor.redis.rawPassword" . | urlquery | replace "+" "%20" -}}
{{- end -}}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForRegistry" -}}
{{- with .Values.redis }}
{{- $index := ternary "2" .external.registryDatabaseIndex (eq .type "internal") }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- end }}
{{- end -}}
{{/*the username redis is used for a placeholder as no username needed in redis*/}}
{{- define "harbor.redisForJobservice" -}}
{{- if (include "harbor.redis.escapedRawPassword" . ) -}}
{{- printf "redis://redis:%s@%s:%s/%s" (include "harbor.redis.escapedRawPassword" . ) (include "harbor.redis.host" . ) (include "harbor.redis.port" . ) (include "harbor.redis.jobserviceDatabaseIndex" . ) }}
{{- else }}
{{- template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}/{{ template "harbor.redis.jobserviceDatabaseIndex" . }}
{{- end -}}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForClair" -}}
{{- with .Values.redis }}
{{- $index := ternary "4" .external.clairAdapterIndex (eq .type "internal") }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- end }}
{{- end -}}
{{/*the username redis is used for a placeholder as no username needed in redis*/}}
{{- define "harbor.redisForGC" -}}
{{- if (include "harbor.redis.escapedRawPassword" . ) -}}
{{- printf "redis://redis:%s@%s:%s/%s" (include "harbor.redis.escapedRawPassword" . ) (include "harbor.redis.host" . ) (include "harbor.redis.port" . ) (include "harbor.redis.registryDatabaseIndex" . ) }}
{{- else }}
{{- printf "redis://%s:%s/%s" (include "harbor.redis.host" . ) (include "harbor.redis.port" . ) (include "harbor.redis.registryDatabaseIndex" . ) -}}
{{- end -}}
/*scheme://[redis:password@]addr/db_index?idle_timeout_seconds=30*/
{{- define "harbor.redis.urlForTrivy" -}}
{{- with .Values.redis }}
{{- $index := ternary "5" .external.trivyAdapterIndex (eq .type "internal") }}
{{- printf "%s/%s?idle_timeout_seconds=30" (include "harbor.redis.url" $) $index -}}
{{- end }}
{{- end -}}
{{/*
host:port,pool_size,password
100 is the default value of pool size
*/}}
{{- define "harbor.redisForCore" -}}
{{- template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }},100,{{ template "harbor.redis.rawPassword" . }}
{{- define "harbor.redis.dbForRegistry" -}}
{{- with .Values.redis }}
{{- ternary "2" .external.registryDatabaseIndex (eq .type "internal") }}
{{- end }}
{{- end -}}
{{- define "harbor.redis.dbForChartmuseum" -}}
{{- with .Values.redis }}
{{- ternary "3" .external.chartmuseumDatabaseIndex (eq .type "internal") }}
{{- end }}
{{- end -}}
{{- define "harbor.portal" -}}
......@@ -263,6 +264,10 @@ host:port,pool_size,password
{{- printf "%s-clair" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.trivy" -}}
{{- printf "%s-trivy" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.notary-server" -}}
{{- printf "%s-notary-server" (include "harbor.fullname" .) -}}
{{- end -}}
......@@ -277,4 +282,302 @@ host:port,pool_size,password
{{- define "harbor.ingress" -}}
{{- printf "%s-ingress" (include "harbor.fullname" .) -}}
{{- end -}}
\ No newline at end of file
{{- end -}}
{{- define "harbor.ingress-notary" -}}
{{- printf "%s-ingress-notary" (include "harbor.fullname" .) -}}
{{- end -}}
{{- define "harbor.noProxy" -}}
{{- 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 -}}
{{- end -}}
{{- define "harbor.caBundleVolume" -}}
- name: ca-bundle-certs
secret:
secretName: {{ .Values.caBundleSecretName }}
{{- end -}}
{{- define "harbor.caBundleVolumeMount" -}}
- name: ca-bundle-certs
mountPath: /harbor_cust_cert/custom-ca.crt
subPath: ca.crt
{{- end -}}
{{/* scheme for all components except notary because it only support http mode */}}
{{- define "harbor.component.scheme" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "https" -}}
{{- else -}}
{{- printf "http" -}}
{{- end -}}
{{- end -}}
{{/* chartmuseum component container port */}}
{{- define "harbor.chartmuseum.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "9443" -}}
{{- else -}}
{{- printf "9999" -}}
{{- end -}}
{{- end -}}
{{/* chartmuseum component service port */}}
{{- define "harbor.chartmuseum.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "443" -}}
{{- else -}}
{{- printf "80" -}}
{{- end -}}
{{- end -}}
{{/* clair adapter component container port */}}
{{- define "harbor.clairAdapter.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* clair adapter component service port */}}
{{- define "harbor.clairAdapter.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* core component container port */}}
{{- define "harbor.core.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* core component service port */}}
{{- define "harbor.core.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "443" -}}
{{- else -}}
{{- printf "80" -}}
{{- end -}}
{{- end -}}
{{/* jobservice component container port */}}
{{- define "harbor.jobservice.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* jobservice component service port */}}
{{- define "harbor.jobservice.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "443" -}}
{{- else -}}
{{- printf "80" -}}
{{- end -}}
{{- end -}}
{{/* portal component container port */}}
{{- define "harbor.portal.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* portal component service port */}}
{{- define "harbor.portal.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "443" -}}
{{- else -}}
{{- printf "80" -}}
{{- end -}}
{{- end -}}
{{/* registry component container port */}}
{{- define "harbor.registry.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "5443" -}}
{{- else -}}
{{- printf "5000" -}}
{{- end -}}
{{- end -}}
{{/* registry component service port */}}
{{- define "harbor.registry.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "5443" -}}
{{- else -}}
{{- printf "5000" -}}
{{- end -}}
{{- end -}}
{{/* registryctl component container port */}}
{{- define "harbor.registryctl.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* registryctl component service port */}}
{{- define "harbor.registryctl.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* trivy component container port */}}
{{- define "harbor.trivy.containerPort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* trivy component service port */}}
{{- define "harbor.trivy.servicePort" -}}
{{- if .Values.internalTLS.enabled -}}
{{- printf "8443" -}}
{{- else -}}
{{- printf "8080" -}}
{{- end -}}
{{- end -}}
{{/* CLAIR_ADAPTER_URL */}}
{{- define "harbor.clairAdapterURL" -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.clair" .) (include "harbor.clairAdapter.servicePort" .) -}}
{{- end -}}
{{/* CORE_URL */}}
{{/* port is included in this url as a workaround for issue https://github.com/aquasecurity/harbor-scanner-trivy/issues/108 */}}
{{- define "harbor.coreURL" -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.core" .) (include "harbor.core.servicePort" .) -}}
{{- end -}}
{{/* JOBSERVICE_URL */}}
{{- define "harbor.jobserviceURL" -}}
{{- printf "%s://%s-jobservice" (include "harbor.component.scheme" .) (include "harbor.fullname" .) -}}
{{- end -}}
{{/* PORTAL_URL */}}
{{- define "harbor.portalURL" -}}
{{- printf "%s://%s" (include "harbor.component.scheme" .) (include "harbor.portal" .) -}}
{{- end -}}
{{/* REGISTRY_URL */}}
{{- define "harbor.registryURL" -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.registry" .) (include "harbor.registry.servicePort" .) -}}
{{- end -}}
{{/* REGISTRY_CONTROLLER_URL */}}
{{- define "harbor.registryControllerURL" -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.registry" .) (include "harbor.registryctl.servicePort" .) -}}
{{- end -}}
{{/* TOKEN_SERVICE_URL */}}
{{- define "harbor.tokenServiceURL" -}}
{{- printf "%s/service/token" (include "harbor.coreURL" .) -}}
{{- end -}}
{{/* TRIVY_ADAPTER_URL */}}
{{- define "harbor.trivyAdapterURL" -}}
{{- printf "%s://%s:%s" (include "harbor.component.scheme" .) (include "harbor.trivy" .) (include "harbor.trivy.servicePort" .) -}}
{{- end -}}
{{- define "harbor.internalTLS.chartmuseum.secretName" -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.chartmuseum.secretName -}}
{{- else -}}
{{- printf "%s-chartmuseum-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.clair.secretName" -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.clair.secretName -}}
{{- else -}}
{{- printf "%s-clair-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.core.secretName" -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.core.secretName -}}
{{- else -}}
{{- printf "%s-core-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.jobservice.secretName" -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.jobservice.secretName -}}
{{- else -}}
{{- printf "%s-jobservice-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.portal.secretName" -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.portal.secretName -}}
{{- else -}}
{{- printf "%s-portal-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.registry.secretName" -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.registry.secretName -}}
{{- else -}}
{{- printf "%s-registry-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{- end -}}
{{- define "harbor.internalTLS.trivy.secretName" -}}
{{- if eq .Values.internalTLS.certSource "secret" -}}
{{- .Values.internalTLS.trivy.secretName -}}
{{- else -}}
{{- printf "%s-trivy-internal-tls" (include "harbor.fullname" .) -}}
{{- end -}}
{{- end -}}
{{- define "harbor.tlsCoreSecretForIngress" -}}
{{- if eq .Values.expose.tls.certSource "none" -}}
{{- printf "" -}}
{{- else if eq .Values.expose.tls.certSource "secret" -}}
{{- .Values.expose.tls.secret.secretName -}}
{{- else -}}
{{- include "harbor.ingress" . -}}
{{- end -}}
{{- end -}}
{{- define "harbor.tlsNotarySecretForIngress" -}}
{{- if eq .Values.expose.tls.certSource "none" -}}
{{- printf "" -}}
{{- else if eq .Values.expose.tls.certSource "secret" -}}
{{- .Values.expose.tls.secret.notarySecretName -}}
{{- else -}}
{{- include "harbor.ingress" . -}}
{{- end -}}
{{- end -}}
{{- define "harbor.tlsSecretForNginx" -}}
{{- if eq .Values.expose.tls.certSource "secret" -}}
{{- .Values.expose.tls.secret.secretName -}}
{{- else -}}
{{- include "harbor.nginx" . -}}
{{- end -}}
{{- end -}}
......@@ -6,11 +6,23 @@ metadata:
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
PORT: "9999"
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"
CACHE_REDIS_ADDR: "{{ template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}"
CACHE_REDIS_DB: "{{ template "harbor.redis.chartmuseumDatabaseIndex" . }}"
{{- 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 }}/chartrepo
{{- end }}
DEPTH: "1"
{{- if eq .Values.logLevel "debug" }}
DEBUG: "true"
......@@ -22,10 +34,7 @@ data:
DISABLE_API: "false"
DISABLE_STATEFILES: "false"
ALLOW_OVERWRITE: "true"
#CHART_URL: {{ .Values.externalURL }}/chartrepo
AUTH_ANONYMOUS_GET: "false"
TLS_CERT: ""
TLS_KEY: ""
CONTEXT_PATH: ""
INDEX_LIMIT: "0"
MAX_STORAGE_OBJECTS: "0"
......@@ -41,6 +50,7 @@ data:
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"
......@@ -62,36 +72,39 @@ data:
{{- 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.secretkey }}
{{- if $storage.swift.prefix }}
STORAGE_OPENSTACK_PREFIX: {{ $storage.swift.prefix }}
{{- end }}
{{- if $storage.swift.secretkey }}
{{- 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.secretkey }}
{{- if $storage.swift.tenantid }}
OS_PROJECT_ID: {{ $storage.swift.tenantid }}
{{- end }}
{{- if $storage.swift.secretkey }}
{{- if $storage.swift.tenant }}
OS_PROJECT_NAME: {{ $storage.swift.tenant }}
{{- end }}
{{- if $storage.swift.secretkey }}
{{- if $storage.swift.domainid }}
OS_DOMAIN_ID: {{ $storage.swift.domainid }}
{{- end }}
{{- if $storage.swift.secretkey }}
{{- 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.secretkey }}
{{- if $storage.oss.rootdirectory }}
STORAGE_ALIBABA_PREFIX: {{ $storage.oss.rootdirectory }}
{{- end }}
{{- if $storage.oss.secretkey }}
{{- if $storage.oss.endpoint }}
STORAGE_ALIBABA_ENDPOINT: {{ $storage.oss.endpoint }}
{{- end }}
ALIBABA_CLOUD_ACCESS_KEY_ID: {{ $storage.oss.accesskeyid }}
......
......@@ -5,26 +5,45 @@ metadata:
name: "{{ template "harbor.chartmuseum" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
app: chartmuseum
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 }}
app: chartmuseum
component: chartmuseum
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: chartmuseum
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:
securityContext:
fsGroup: 10000
{{- if .Values.chartmuseum.serviceAccountName }}
serviceAccountName: {{ .Values.chartmuseum.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: chartmuseum
image: {{ .Values.chartmuseum.image.repository }}:{{ .Values.chartmuseum.image.tag }}
......@@ -32,13 +51,15 @@ spec:
livenessProbe:
httpGet:
path: /health
port: 9999
initialDelaySeconds: 1
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.chartmuseum.containerPort" . }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 9999
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.chartmuseum.containerPort" . }}
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.chartmuseum.resources }}
......@@ -51,30 +72,90 @@ spec:
- 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: 9999
- containerPort: {{ template "harbor.chartmuseum.containerPort" . }}
volumeMounts:
- name: data
- name: chartmuseum-data
mountPath: /chart_storage
- name: etc-localtime
mountPath: /etc/localtime
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: etc-localtime
hostPath:
path: /etc/localtime
path: /etc/localtime
{{- if eq .Values.chartmuseum.storageSpec.type "hostPath" }}
- name: data
- name: chartmuseum-data
hostPath:
path: {{.Values.chartmuseum.storageSpec.hostPath.root | default "/data" }}/{{ .Release.Namespace }}/{{ .Release.Name }}/chartmuseum
{{- else if eq .Values.chartmuseum.storageSpec.type "emptyDir" }}
- name: data
- name: chartmuseum-data
emptyDir: {}
{{- end }}
{{- 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 }}
......
......@@ -7,7 +7,7 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
CACHE_REDIS_PASSWORD: {{ include "harbor.redis.rawPassword" . | b64enc | quote }}
CACHE_REDIS_PASSWORD: {{ include "harbor.redis.password" . | b64enc | quote }}
{{- $storage := .Values.persistence.imageChartStorage }}
{{- $storageType := $storage.type }}
{{- if eq $storageType "azure" }}
......
......@@ -7,9 +7,9 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 80
targetPort: 9999
- port: {{ template "harbor.chartmuseum.servicePort" . }}
targetPort: {{ template "harbor.chartmuseum.containerPort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: chartmuseum
component: chartmuseum
{{- end }}
\ No newline at end of file
{{ if .Values.clair.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.clair" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: clair
data:
config.yaml: |
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
notifier:
attempts: 3
renotifyinterval: 2h
http:
endpoint: "http://{{ template "harbor.core" . }}/service/notifications/clair"
{{ end }}
......@@ -5,33 +5,47 @@ metadata:
name: {{ template "harbor.clair" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: clair
component: clair
spec:
replicas: {{ .Values.clair.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: clair
component: clair
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: clair
component: clair
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/clair/clair-cm.yaml") . | sha256sum }}
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:
securityContext:
fsGroup: 10000
{{- if .Values.clair.serviceAccountName }}
serviceAccountName: {{ .Values.clair.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: clair
image: {{ .Values.clair.image.repository }}:{{ .Values.clair.image.tag }}
image: {{ .Values.clair.clair.image.repository }}:{{ .Values.clair.clair.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /health
port: 6061
initialDelaySeconds: 30
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
......@@ -41,38 +55,107 @@ spec:
periodSeconds: 10
args: ["-log-level", "{{ .Values.logLevel }}"]
env:
{{- if .Values.clair.httpProxy }}
{{- if has "clair" .Values.proxy.components }}
- name: HTTP_PROXY
value: {{ .Values.clair.httpProxy }}
{{- end }}
{{- if .Values.clair.httpsProxy }}
value: "{{ .Values.proxy.httpProxy }}"
- name: HTTPS_PROXY
value: {{ .Values.clair.httpsProxy }}
{{- end }}
value: "{{ .Values.proxy.httpsProxy }}"
- name: NO_PROXY
value: "{{ template "harbor.registry" . }},{{ template "harbor.core" . }}"
{{- if .Values.clair.resources }}
value: "{{ template "harbor.noProxy" . }}"
{{- end }}
{{- if .Values.clair.clair.resources }}
resources:
{{ toYaml .Values.clair.resources | indent 10 }}
{{ toYaml .Values.clair.clair.resources | indent 10 }}
{{- end }}
ports:
- containerPort: 6060
volumeMounts:
- name: clair-config
- 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
image: {{ .Values.clair.adapter.image.repository }}:{{ .Values.clair.adapter.image.tag }}
imagePullPolicy: {{ .Values.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 }}
- name: etc-localtime
mountPath: /etc/localtime
mountPath: /etc/localtime
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
- name: clair-config
configMap:
name: "{{ template "harbor.clair" . }}"
items:
- key: config.yaml
path: config.yaml
- 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 }}
......
{{- 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
......@@ -7,11 +7,9 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- name: clair
port: 6060
- name: health
port: 6061
- name: adapter
port: {{ include "harbor.clairAdapter.servicePort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: clair
component: clair
{{ end }}
......@@ -7,41 +7,53 @@ metadata:
data:
app.conf: |+
appname = Harbor
runmode = dev
runmode = prod
enablegzip = true
[dev]
httpport = 8080
[prod]
httpport = {{ ternary "8443" "8080" .Values.internalTLS.enabled }}
PORT: "{{ ternary "8443" "8080" .Values.internalTLS.enabled }}"
DATABASE_TYPE: "postgresql"
POSTGRESQL_HOST: "{{ template "harbor.database.host" . }}"
POSTGRESQL_PORT: "{{ template "harbor.database.port" . }}"
POSTGRESQL_USERNAME: "{{ template "harbor.database.username" . }}"
POSTGRESQL_DATABASE: "{{ template "harbor.database.coreDatabase" . }}"
POSTGRESQL_SSLMODE: "{{ template "harbor.database.sslmode" . }}"
POSTGRESQL_MAX_IDLE_CONNS: "{{ .Values.database.maxIdleConns }}"
POSTGRESQL_MAX_OPEN_CONNS: "{{ .Values.database.maxOpenConns }}"
EXT_ENDPOINT: "{{ .Values.externalURL }}"
CORE_URL: "http://{{ template "harbor.core" . }}"
JOBSERVICE_URL: "http://{{ template "harbor.fullname" . }}-jobservice"
REGISTRY_URL: "http://{{ template "harbor.registry" . }}:5000"
TOKEN_SERVICE_URL: "http://{{ template "harbor.core" . }}/service/token"
CORE_URL: "{{ template "harbor.coreURL" . }}"
JOBSERVICE_URL: "{{ template "harbor.jobserviceURL" . }}"
REGISTRY_URL: "{{ template "harbor.registryURL" . }}"
TOKEN_SERVICE_URL: "{{ template "harbor.tokenServiceURL" . }}"
WITH_NOTARY: "{{ .Values.notary.enabled }}"
NOTARY_URL: "http://{{ template "harbor.notary-server" . }}:4443"
CFG_EXPIRATION: "5"
CORE_LOCAL_URL: "{{ ternary "https://127.0.0.1:8443" "http://127.0.0.1:8080" .Values.internalTLS.enabled }}"
WITH_CLAIR: "{{ .Values.clair.enabled }}"
CLAIR_DB_HOST: "{{ template "harbor.database.host" . }}"
CLAIR_DB_PORT: "{{ template "harbor.database.port" . }}"
CLAIR_DB_USERNAME: "{{ template "harbor.database.username" . }}"
CLAIR_DB: "{{ template "harbor.database.clairDatabase" . }}"
CLAIR_DB_SSLMODE: "{{ template "harbor.database.sslmode" . }}"
CLAIR_URL: "http://{{ template "harbor.fullname" . }}-clair:6060"
CLAIR_ADAPTER_URL: "{{ template "harbor.clairAdapterURL" . }}"
WITH_TRIVY: {{ .Values.trivy.enabled | quote }}
TRIVY_ADAPTER_URL: "{{ template "harbor.trivyAdapterURL" . }}"
REGISTRY_STORAGE_PROVIDER_NAME: "{{ .Values.persistence.imageChartStorage.type }}"
WITH_CHARTMUSEUM: "{{ .Values.chartmuseum.enabled }}"
CHART_REPOSITORY_URL: "http://{{ template "harbor.chartmuseum" . }}"
CHART_REPOSITORY_URL: "{{ template "harbor.component.scheme" . }}://{{ template "harbor.chartmuseum" . }}"
LOG_LEVEL: "{{ .Values.logLevel }}"
CONFIG_PATH: "/etc/core/app.conf"
SYNC_REGISTRY: "false"
CHART_CACHE_DRIVER: "redis"
_REDIS_URL: "{{ template "harbor.redisForCore" . }}"
_REDIS_URL_REG: "{{ template "harbor.redisForGC" . }}"
PORTAL_URL: "http://{{ template "harbor.portal" . }}"
REGISTRYCTL_URL: "http://{{ template "harbor.registry" . }}:8080"
CLAIR_HEALTH_CHECK_SERVER_URL: "http://{{ template "harbor.clair" . }}:6061"
\ No newline at end of file
_REDIS_URL_CORE: "{{ template "harbor.redis.urlForCore" . }}"
_REDIS_URL_REG: "{{ template "harbor.redis.urlForRegistry" . }}"
PORTAL_URL: "{{ template "harbor.portalURL" . }}"
REGISTRY_CONTROLLER_URL: "{{ template "harbor.registryControllerURL" . }}"
REGISTRY_CREDENTIAL_USERNAME: "{{ .Values.registry.credentials.username }}"
{{- if .Values.uaaSecretName }}
UAA_CA_ROOT: "/etc/core/auth-ca/auth-ca.crt"
{{- end }}
{{- if has "core" .Values.proxy.components }}
HTTP_PROXY: "{{ .Values.proxy.httpProxy }}"
HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}"
NO_PROXY: "{{ template "harbor.noProxy" . }}"
{{- end }}
PERMITTED_REGISTRY_TYPES_FOR_PROXY_CACHE: "docker-hub,harbor"
{{- if hasKey .Values.core "gcTimeWindowHours" }}
#make the GC time window configurable for testing
GC_TIME_WINDOW_HOURS: "{{ .Values.core.gcTimeWindowHours }}"
{{- end }}
\ No newline at end of file
......@@ -4,41 +4,65 @@ metadata:
name: {{ template "harbor.core" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: core
component: core
spec:
replicas: {{ .Values.core.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: core
component: core
template:
metadata:
labels:
{{ include "harbor.matchLabels" . | indent 8 }}
app: core
component: core
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/core/core-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.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.core.podAnnotations }}
{{ toYaml .Values.core.podAnnotations | indent 8 }}
{{- end }}
spec:
securityContext:
fsGroup: 10000
{{- if .Values.core.serviceAccountName }}
serviceAccountName: {{ .Values.core.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: core
image: {{ .Values.core.image.repository }}:{{ .Values.core.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
startupProbe:
httpGet:
path: /api/v2.0/ping
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.core.containerPort" . }}
failureThreshold: 360
initialDelaySeconds: {{ .Values.core.startupProbe.initialDelaySeconds }}
periodSeconds: 10
livenessProbe:
httpGet:
path: /api/ping
port: 8080
initialDelaySeconds: 20
path: /api/v2.0/ping
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.core.containerPort" . }}
failureThreshold: 2
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/ping
port: 8080
initialDelaySeconds: 20
path: /api/v2.0/ping
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.core.containerPort" . }}
failureThreshold: 2
periodSeconds: 10
envFrom:
- configMapRef:
......@@ -55,9 +79,19 @@ spec:
valueFrom:
secretKeyRef:
name: "{{ template "harbor.jobservice" . }}"
key: secret
key: JOBSERVICE_SECRET
{{- if .Values.internalTLS.enabled }}
- name: INTERNAL_TLS_ENABLED
value: "true"
- name: INTERNAL_TLS_KEY_PATH
value: /etc/harbor/ssl/core/tls.key
- name: INTERNAL_TLS_CERT_PATH
value: /etc/harbor/ssl/core/tls.crt
- name: INTERNAL_TLS_TRUST_CA_PATH
value: /etc/harbor/ssl/core/ca.crt
{{- end }}
ports:
- containerPort: 8080
- containerPort: {{ template "harbor.core.containerPort" . }}
volumeMounts:
- name: etc-localtime
mountPath: /etc/localtime
......@@ -72,11 +106,22 @@ spec:
subPath: tls.key
{{- if .Values.expose.tls.enabled }}
- name: ca-download
mountPath: /etc/core/ca/ca.crt
subPath: ca.crt
mountPath: /etc/core/ca
{{- end }}
{{- if .Values.uaaSecretName }}
- name: auth-ca-cert
mountPath: /etc/core/auth-ca/auth-ca.crt
subPath: auth-ca.crt
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: core-internal-certs
mountPath: /etc/harbor/ssl/core
{{- end }}
- name: psc
mountPath: /etc/core/token
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
{{- if .Values.core.resources }}
resources:
{{ toYaml .Values.core.resources | indent 10 }}
......@@ -84,10 +129,13 @@ spec:
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
path: /etc/localtime
- name: config
configMap:
name: {{ template "harbor.core" . }}
items:
- key: app.conf
path: app.conf
- name: secret-key
secret:
secretName: {{ template "harbor.core" . }}
......@@ -104,19 +152,32 @@ spec:
{{- if .Values.expose.tls.enabled }}
- name: ca-download
secret:
{{- if eq (include "harbor.autoGenCertForIngress" .) "true" }}
{{- 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.nginx" . }}
{{- else }}
secretName: {{ .Values.expose.tls.secretName }}
secretName: {{ template "harbor.tlsSecretForNginx" . }}
{{- end }}
{{- end }}
{{- if .Values.uaaSecretName }}
- name: auth-ca-cert
secret:
secretName: {{ .Values.uaaSecretName }}
items:
- key: ca.crt
path: 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 }}
......
......@@ -14,6 +14,5 @@ data:
{{- end }}
HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }}
POSTGRESQL_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{- if .Values.clair.enabled }}
CLAIR_DB_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{- end }}
\ No newline at end of file
REGISTRY_CREDENTIAL_PASSWORD: {{ .Values.registry.credentials.password | b64enc | quote }}
CSRF_KEY: {{ .Values.core.xsrfKey | default (randAlphaNum 32) | b64enc | quote }}
......@@ -9,8 +9,8 @@ spec:
type: NodePort
{{- end }}
ports:
- port: 80
targetPort: 8080
- port: {{ template "harbor.core.servicePort" . }}
targetPort: {{ template "harbor.core.containerPort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: core
component: core
......@@ -6,36 +6,52 @@ metadata:
name: "{{ template "harbor.database" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
app: database
component: database
spec:
replicas: 1
serviceName: "{{ template "harbor.database" . }}"
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: database
component: database
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: database
component: database
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/database/database-secret.yaml") . | sha256sum }}
{{- if .Values.database.podAnnotations }}
{{ toYaml .Values.database.podAnnotations | indent 8 }}
{{- end }}
spec:
tolerations:
- effect: NoSchedule
operator: Exists
{{- if .Values.database.internal.serviceAccountName }}
serviceAccountName: {{ .Values.database.internal.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
initContainers:
- name: "change-permission-of-directory"
securityContext:
runAsUser: 0
image: {{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["/bin/sh"]
args: ["-c", "chown -R postgres:postgres /var/lib/postgresql/data"]
volumeMounts:
- name: database-data
mountPath: /var/lib/postgresql/data
subPath: {{ $database.subPath }}
- name: "remove-lost-found"
image: {{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["rm", "-Rf", "/var/lib/postgresql/data/lost+found"]
volumeMounts:
- name: data
- name: database-data
mountPath: /var/lib/postgresql/data
subPath: {{ $database.subPath }}
containers:
- name: database
image: {{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }}
......@@ -44,7 +60,7 @@ spec:
exec:
command:
- /docker-healthcheck.sh
initialDelaySeconds: 60
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
exec:
......@@ -61,21 +77,23 @@ spec:
name: "{{ template "harbor.database" . }}"
volumeMounts:
- name: etc-localtime
mountPath: /etc/localtime
- name: data
mountPath: /etc/localtime
- name: database-data
mountPath: /var/lib/postgresql/data
subPath: {{ $database.subPath }}
{{- if not .Values.persistence.enabled }}
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
path: /etc/localtime
{{- if eq .Values.database.internal.storageSpec.type "hostPath" }}
- name: data
- name: "database-data"
hostPath:
path: {{.Values.database.internal.storageSpec.hostPath.root | default "/data" }}/{{ .Release.Namespace }}/{{ .Release.Name }}/database
{{- else if eq .Values.database.internal.storageSpec.type "emptyDir" }}
- name: data
- name: "database-data"
emptyDir: {}
{{- end }}
{{- end }}
{{- with .Values.database.internal.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
......@@ -91,11 +109,11 @@ spec:
{{- if eq .Values.database.internal.storageSpec.type "volumeClaimTemplate" }}
volumeClaimTemplates:
- metadata:
name: "data"
labels:
name: "database-data"
labels:
{{ include "harbor.labels" . | indent 8 }}
app: database
spec:
{{ toYaml $.Values.database.internal.storageSpec.volumeClaimTemplate.spec | indent 6 }}
{{- end }}
{{- end -}}
{{- end -}}
{{- end -}}
......@@ -10,5 +10,5 @@ spec:
- port: 5432
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: database
component: database
{{- end -}}
\ No newline at end of file
......@@ -8,13 +8,15 @@
{{- $_ := set . "v2_path" "/v2/*" -}}
{{- $_ := set . "chartrepo_path" "/chartrepo/*" -}}
{{- $_ := set . "controller_path" "/c/*" -}}
{{- $_ := set . "notary_path" "/" -}}
{{- else if eq .Values.expose.ingress.controller "ncp" }}
{{- $_ := set . "portal_path" "/" -}}
{{- $_ := set . "portal_path" "/.*" -}}
{{- $_ := set . "api_path" "/api/.*" -}}
{{- $_ := set . "service_path" "/service/.*" -}}
{{- $_ := set . "v2_path" "/v2/.*" -}}
{{- $_ := set . "chartrepo_path" "/chartrepo/.*" -}}
{{- $_ := set . "controller_path" "/c/.*" -}}
{{- $_ := set . "notary_path" "/.*" -}}
{{- else }}
{{- $_ := set . "portal_path" "/" -}}
{{- $_ := set . "api_path" "/api/" -}}
......@@ -22,8 +24,15 @@
{{- $_ := set . "v2_path" "/v2/" -}}
{{- $_ := set . "chartrepo_path" "/chartrepo/" -}}
{{- $_ := set . "controller_path" "/c/" -}}
{{- $_ := set . "notary_path" "/" -}}
{{- end }}
---
{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: extensions/v1beta1
{{- else }}
apiVersion: networking.k8s.io/v1beta1
{{- end }}
kind: Ingress
metadata:
name: "{{ template "harbor.ingress" . }}"
......@@ -31,36 +40,23 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
annotations:
{{ toYaml $ingress.annotations | indent 4 }}
{{- if .Values.internalTLS.enabled }}
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
{{- end }}
{{- if eq .Values.expose.ingress.controller "ncp" }}
ncp/use-regex: "true"
{{- if $tls.enabled }}
ncp/http-redirect: "true"
{{- end }}
{{- end }}
spec:
{{- if $tls.enabled }}
tls:
{{- if $tls.secretName }}
- secretName: {{ $tls.secretName }}
{{- else }}
- secretName: "{{ template "harbor.ingress" . }}"
{{- end }}
- secretName: {{ template "harbor.tlsCoreSecretForIngress" . }}
{{- if $ingress.hosts.core }}
hosts:
- {{ $ingress.hosts.core }}
{{- end }}
{{- if .Values.notary.enabled }}
{{- if $tls.notarySecretName }}
- secretName: {{ $tls.notarySecretName }}
{{- else if $tls.secretName }}
- secretName: {{ $tls.secretName }}
{{- else }}
- secretName: "{{ template "harbor.ingress" . }}"
{{- end }}
{{- if $ingress.hosts.notary }}
hosts:
- {{ $ingress.hosts.notary }}
{{- end }}
{{- end }}
{{- end }}
{{- if eq .Values.expose.ingress.controller "ncp" }}
backend:
serviceName: {{ template "harbor.portal" . }}
servicePort: 80
{{- end }}
rules:
- http:
......@@ -68,41 +64,72 @@ spec:
- path: {{ .portal_path }}
backend:
serviceName: {{ template "harbor.portal" . }}
servicePort: 80
servicePort: {{ template "harbor.portal.servicePort" . }}
- path: {{ .api_path }}
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
servicePort: {{ template "harbor.core.servicePort" . }}
- path: {{ .service_path }}
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
servicePort: {{ template "harbor.core.servicePort" . }}
- path: {{ .v2_path }}
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
servicePort: {{ template "harbor.core.servicePort" . }}
- path: {{ .chartrepo_path }}
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
servicePort: {{ template "harbor.core.servicePort" . }}
- path: {{ .controller_path }}
backend:
serviceName: {{ template "harbor.core" . }}
servicePort: 80
servicePort: {{ template "harbor.core.servicePort" . }}
{{- if $ingress.hosts.core }}
host: {{ $ingress.hosts.core }}
{{- end }}
{{- if .Values.notary.enabled }}
{{- if .Values.notary.enabled }}
---
{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: extensions/v1beta1
{{- else }}
apiVersion: networking.k8s.io/v1beta1
{{- end }}
kind: Ingress
metadata:
name: "{{ template "harbor.ingress-notary" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
annotations:
{{ toYaml $ingress.annotations | indent 4 }}
{{- if eq .Values.expose.ingress.controller "ncp" }}
ncp/use-regex: "true"
{{- if $tls.enabled }}
ncp/http-redirect: "true"
{{- end }}
{{- end }}
spec:
{{- if $tls.enabled }}
tls:
- secretName: {{ template "harbor.tlsNotarySecretForIngress" . }}
{{- if $ingress.hosts.notary }}
hosts:
- {{ $ingress.hosts.notary }}
{{- end }}
{{- end }}
rules:
- http:
paths:
- path: /
- path: {{ .notary_path }}
backend:
serviceName: {{ template "harbor.notary-server" . }}
servicePort: 4443
{{- if $ingress.hosts.notary }}
host: {{ $ingress.hosts.notary }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
---
apiVersion: bcc.bd-apaas.com/v1alpha1
......@@ -120,7 +147,7 @@ spec:
priority: 0
services:
- kind: Service
name: harbor-portal
name: {{ template "harbor.portal" . }}
namespace: devops
port: 80
- kind: Rule
......@@ -129,7 +156,7 @@ spec:
priority: 0
services:
- kind: Service
name: harbor-core
name: {{ template "harbor.core" . }}
namespace: devops
port: 80
- kind: Rule
......@@ -138,7 +165,7 @@ spec:
priority: 0
services:
- kind: Service
name: harbor-core
name: {{ template "harbor.core" . }}
namespace: devops
port: 80
- kind: Rule
......@@ -147,7 +174,7 @@ spec:
priority: 0
services:
- kind: Service
name: harbor-core
name: {{ template "harbor.core" . }}
namespace: devops
port: 80
- kind: Rule
......@@ -156,7 +183,7 @@ spec:
priority: 0
services:
- kind: Service
name: harbor-core
name: {{ template "harbor.core" . }}
namespace: devops
port: 80
- kind: Rule
......@@ -165,7 +192,7 @@ spec:
priority: 0
services:
- kind: Service
name: harbor-core
name: {{ template "harbor.core" . }}
namespace: devops
port: 80
- kind: Rule
......@@ -174,7 +201,7 @@ spec:
priority: 0
services:
- kind: Service
name: harbor-notary-server
name: {{ template "harbor.notary-server" . }}
namespace: devops
port: 4443
tls:
......@@ -191,7 +218,7 @@ spec:
apiVersion: bcc.bd-apaas.com/v1alpha1
kind: IngressHost
metadata:
name: harbor-natory
name: harbor-notary
namespace: {{ .Release.Namespace }}
spec:
host: {{ .Values.expose.ingress.hosts.notary }}
\ No newline at end of file
host: {{ .Values.expose.ingress.hosts.notary }}
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
{{- $ca := genCA "harbor-internal-ca" 365 }}
{{- $coreCN := (include "harbor.core" .) }}
{{- $coreCrt := genSignedCert $coreCN (list "127.0.0.1") (list "localhost" $coreCN) 365 $ca }}
{{- $jsCN := (include "harbor.jobservice" .) }}
{{- $jsCrt := genSignedCert $jsCN nil (list $jsCN) 365 $ca }}
{{- $regCN := (include "harbor.registry" .) }}
{{- $regCrt := genSignedCert $regCN nil (list $regCN) 365 $ca }}
{{- $portalCN := (include "harbor.portal" .) }}
{{- $portalCrt := genSignedCert $portalCN nil (list $portalCN) 365 $ca }}
---
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.core.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $coreCrt.Cert | b64enc | quote }}
tls.key: {{ $coreCrt.Key | b64enc | quote }}
---
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.jobservice.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $jsCrt.Cert | b64enc | quote }}
tls.key: {{ $jsCrt.Key | b64enc | quote }}
---
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.registry.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $regCrt.Cert | b64enc | quote }}
tls.key: {{ $regCrt.Key | b64enc | quote }}
---
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.portal.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $portalCrt.Cert | b64enc | quote }}
tls.key: {{ $portalCrt.Key | b64enc | quote }}
{{- if .Values.chartmuseum.enabled }}
---
{{- $chartCN := (include "harbor.chartmuseum" .) }}
{{- $chartCrt := genSignedCert $chartCN nil (list $chartCN) 365 $ca }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.chartmuseum.secretName" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ $ca.Cert | b64enc | quote }}
tls.crt: {{ $chartCrt.Cert | b64enc | quote }}
tls.key: {{ $chartCrt.Key | b64enc | quote }}
{{- end }}
{{- if .Values.clair.enabled }}
---
{{- $clairCN := (include "harbor.clair" .) }}
{{- $clairCrt := genSignedCert $clairCN nil (list $clairCN) 365 $ca }}
apiVersion: v1
kind: Secret
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
kind: ConfigMap
metadata:
name: "{{ template "harbor.jobservice" . }}-env"
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
CORE_URL: "{{ template "harbor.coreURL" . }}"
TOKEN_SERVICE_URL: "{{ template "harbor.tokenServiceURL" . }}"
REGISTRY_URL: "{{ template "harbor.registryURL" . }}"
REGISTRY_CONTROLLER_URL: "{{ template "harbor.registryControllerURL" . }}"
REGISTRY_CREDENTIAL_USERNAME: "{{ .Values.registry.credentials.username }}"
{{- if has "jobservice" .Values.proxy.components }}
HTTP_PROXY: "{{ .Values.proxy.httpProxy }}"
HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}"
NO_PROXY: "{{ template "harbor.noProxy" . }}"
{{- end }}
......@@ -6,14 +6,21 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
data:
config.yml: |+
protocol: "http"
port: 8080
#Server listening port
protocol: "{{ template "harbor.component.scheme" . }}"
port: {{ template "harbor.jobservice.containerPort". }}
{{- if .Values.internalTLS.enabled }}
https_config:
cert: "/etc/harbor/ssl/jobservice/tls.crt"
key: "/etc/harbor/ssl/jobservice/tls.key"
{{- end }}
worker_pool:
workers: {{ .Values.jobservice.maxJobWorkers }}
backend: "redis"
redis_pool:
redis_url: "{{ template "harbor.redisForJobservice" . }}"
redis_url: "{{ template "harbor.redis.urlForJobservice" . }}"
namespace: "harbor_job_service_namespace"
idle_timeout_second: 3600
job_loggers:
{{- if eq .Values.jobservice.jobLogger "file" }}
- name: "FILE"
......
......@@ -4,26 +4,46 @@ metadata:
name: "{{ template "harbor.jobservice" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
app: jobservice
component: jobservice
spec:
replicas: {{ .Values.jobservice.replicas }}
strategy:
type: {{ .Values.updateStrategy.type }}
{{- if eq .Values.updateStrategy.type "Recreate" }}
rollingUpdate: null
{{- end }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: jobservice
component: jobservice
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: jobservice
component: jobservice
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/jobservice/jobservice-cm.yaml") . | sha256sum }}
checksum/configmap-env: {{ include (print $.Template.BasePath "/jobservice/jobservice-cm-env.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.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 "/jobservice/jobservice-tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.jobservice.podAnnotations }}
{{ toYaml .Values.jobservice.podAnnotations | indent 8 }}
{{- end }}
spec:
securityContext:
fsGroup: 10000
{{- if .Values.jobservice.serviceAccountName }}
serviceAccountName: {{ .Values.jobservice.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: jobservice
image: {{ .Values.jobservice.image.repository }}:{{ .Values.jobservice.image.tag }}
......@@ -31,13 +51,15 @@ spec:
livenessProbe:
httpGet:
path: /api/v1/stats
port: 8080
initialDelaySeconds: 20
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.jobservice.containerPort" . }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/v1/stats
port: 8080
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.jobservice.containerPort" . }}
initialDelaySeconds: 20
periodSeconds: 10
{{- if .Values.jobservice.resources }}
......@@ -50,36 +72,55 @@ spec:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: "{{ template "harbor.jobservice" . }}"
key: secret
- name: CORE_URL
value: "http://{{ template "harbor.core" . }}"
- name: REGISTRY_CONTROLLER_URL
value: "http://{{ template "harbor.registry" . }}:8080"
- name: LOG_LEVEL
value: debug
{{- if .Values.internalTLS.enabled }}
- name: INTERNAL_TLS_ENABLED
value: "true"
- name: INTERNAL_TLS_KEY_PATH
value: /etc/harbor/ssl/jobservice/tls.key
- name: INTERNAL_TLS_CERT_PATH
value: /etc/harbor/ssl/jobservice/tls.crt
- name: INTERNAL_TLS_TRUST_CA_PATH
value: /etc/harbor/ssl/jobservice/ca.crt
{{- end }}
envFrom:
- configMapRef:
name: "{{ template "harbor.jobservice" . }}-env"
- secretRef:
name: "{{ template "harbor.jobservice" . }}"
ports:
- containerPort: 8080
- containerPort: {{ template "harbor.jobservice.containerPort" . }}
volumeMounts:
- name: jobservice-config
mountPath: /etc/jobservice/config.yml
subPath: config.yml
- name: data
- name: job-logs
mountPath: /var/log/jobs
{{- if .Values.internalTLS.enabled }}
- name: jobservice-internal-certs
mountPath: /etc/harbor/ssl/jobservice
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
- name: etc-localtime
mountPath: /etc/localtime
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
path: /etc/localtime
- name: jobservice-config
configMap:
name: "{{ template "harbor.jobservice" . }}"
- name: data
- name: job-logs
emptyDir: {}
{{- 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 }}
......
......@@ -6,4 +6,5 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
secret: {{ .Values.jobservice.secret | default (randAlphaNum 16) | b64enc | quote }}
JOBSERVICE_SECRET: {{ .Values.jobservice.secret | default (randAlphaNum 16) | b64enc | quote }}
REGISTRY_CREDENTIAL_PASSWORD: {{ .Values.registry.credentials.password | b64enc | quote }}
......@@ -6,8 +6,8 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- port: 80
targetPort: 8080
- port: {{ template "harbor.jobservice.servicePort" . }}
targetPort: {{ template "harbor.jobservice.containerPort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: jobservice
component: jobservice
{{- if and (ne .Values.expose.type "ingress") (not .Values.expose.tls.enabled) }}
{{- $scheme := (include "harbor.component.scheme" .) -}}
apiVersion: v1
kind: ConfigMap
metadata:
......@@ -8,6 +9,7 @@ metadata:
data:
nginx.conf: |+
worker_processes auto;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
......@@ -16,20 +18,25 @@ data:
}
http {
client_body_temp_path /tmp/client_body_temp;
proxy_temp_path /tmp/proxy_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
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;
upstream core {
server {{ template "harbor.core" . }};
server "{{ template "harbor.core" . }}:{{ template "harbor.core.servicePort" . }}";
}
upstream portal {
server {{ template "harbor.portal" . }};
server {{ template "harbor.portal" . }}:{{ template "harbor.portal.servicePort" . }};
}
log_format timed_combined '$remote_addr - '
log_format timed_combined '[$time_local]:$remote_addr - '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time $pipe';
......@@ -37,39 +44,51 @@ data:
access_log /dev/stdout timed_combined;
server {
listen 80;
listen 8080;
server_tokens off;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# Add extra headers
add_header X-Frame-Options DENY;
add_header Content-Security-Policy "frame-ancestors 'none'";
location / {
proxy_pass http://portal/;
proxy_pass {{ $scheme }}://portal/;
proxy_set_header Host $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 /api/ {
proxy_pass http://core/api/;
proxy_pass {{ $scheme }}://core/api/;
{{- if and .Values.internalTLS.enabled }}
proxy_ssl_verify off;
proxy_ssl_session_reuse on;
{{- end }}
proxy_set_header Host $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 /chartrepo/ {
proxy_pass http://core/chartrepo/;
proxy_pass {{ $scheme }}://core/chartrepo/;
{{- if and .Values.internalTLS.enabled }}
proxy_ssl_verify off;
proxy_ssl_session_reuse on;
{{- end }}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
......@@ -82,14 +101,14 @@ data:
}
location /c/ {
proxy_pass http://core/c/;
proxy_pass {{ $scheme }}://core/c/;
proxy_set_header Host $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;
}
......@@ -99,11 +118,11 @@ data:
}
location /v2/ {
proxy_pass http://core/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;
......@@ -111,22 +130,21 @@ data:
}
location /service/ {
proxy_pass http://core/service/;
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;
# 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 }}
\ No newline at end of file
{{- if and (ne .Values.expose.type "ingress") .Values.expose.tls.enabled }}
{{- $scheme := (include "harbor.component.scheme" .) -}}
apiVersion: v1
kind: ConfigMap
metadata:
......@@ -8,6 +9,7 @@ metadata:
data:
nginx.conf: |+
worker_processes auto;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
......@@ -16,17 +18,22 @@ data:
}
http {
client_body_temp_path /tmp/client_body_temp;
proxy_temp_path /tmp/proxy_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
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;
upstream core {
server {{ template "harbor.core" . }};
server "{{ template "harbor.core" . }}:{{ template "harbor.core.servicePort" . }}";
}
upstream portal {
server {{ template "harbor.portal" . }};
server "{{ template "harbor.portal" . }}:{{ template "harbor.portal.servicePort" . }}";
}
{{- if .Values.notary.enabled }}
......@@ -34,8 +41,8 @@ data:
server {{ template "harbor.notary-server" . }}:4443;
}
{{- end }}
log_format timed_combined 'remote_addr - '
log_format timed_combined '[$time_local]:$remote_addr - '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time $pipe';
......@@ -49,16 +56,16 @@ data:
# ssl
ssl_certificate /etc/nginx/cert/tls.crt;
ssl_certificate_key /etc/nginx/cert/tls.key;
# recommendations from https://raymii.org/s/tutorials/strong_ssl_security_on_nginx.html
ssl_protocols tlsv1.1 tlsv1.2;
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;
# disable any limits to avoid http 413 for large image uploads
client_max_body_size 0;
# required to avoid http 411: see issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
......@@ -78,56 +85,70 @@ data:
{{- end }}
server {
listen 443 ssl;
listen 8443 ssl;
# server_name harbordomain.com;
server_tokens off;
# SSL
ssl_certificate /etc/nginx/cert/tls.crt;
ssl_certificate_key /etc/nginx/cert/tls.key;
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1.1 TLSv1.2;
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;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
# Add extra headers
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header Content-Security-Policy "frame-ancestors 'none'";
location / {
proxy_pass http://portal/;
proxy_pass {{ $scheme }}://portal/;
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;
# Add Secure flag when serving HTTPS
proxy_cookie_path / "/; secure";
proxy_cookie_path / "/; HttpOnly; Secure";
proxy_buffering off;
proxy_request_buffering off;
}
location /api/ {
proxy_pass http://core/api/;
proxy_pass {{ $scheme }}://core/api/;
{{- if and .Values.internalTLS.enabled }}
proxy_ssl_verify off;
proxy_ssl_session_reuse on;
{{- end }}
proxy_set_header Host $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 /chartrepo/ {
proxy_pass http://core/chartrepo/;
proxy_pass {{ $scheme }}://core/chartrepo/;
{{- if and .Values.internalTLS.enabled }}
proxy_ssl_verify off;
proxy_ssl_session_reuse on;
{{- end }}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
......@@ -135,19 +156,23 @@ data:
# 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 /c/ {
proxy_pass http://core/c/;
proxy_pass {{ $scheme }}://core/c/;
proxy_set_header Host $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;
}
......@@ -157,11 +182,11 @@ data:
}
location /v2/ {
proxy_pass http://core/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;
......@@ -169,27 +194,28 @@ data:
}
location /service/ {
proxy_pass http://core/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 80;
listen 8080;
#server_name harbordomain.com;
return 301 https://$host$request_uri;
}
}
}
{{- end }}
\ No newline at end of file
{{- if ne .Values.expose.type "ingress" }}
apiVersion: extensions/v1beta1
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.nginx" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: nginx
component: nginx
spec:
replicas: 1
replicas: {{ .Values.nginx.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: nginx
component: nginx
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: nginx
component: nginx
annotations:
{{- if not .Values.expose.tls.enabled }}
checksum/configmap: {{ include (print $.Template.BasePath "/nginx/configmap-http.yaml") . | sha256sum }}
......@@ -30,20 +30,37 @@ spec:
{{ toYaml .Values.nginx.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- if .Values.nginx.serviceAccountName }}
serviceAccountName: {{ .Values.nginx.serviceAccountName }}
{{- end }}
securityContext:
fsGroup: 10000
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: nginx
image: "{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.tag }}"
imagePullPolicy: "{{ .Values.imagePullPolicy }}"
{{- $_ := set . "scheme" "HTTP" -}}
{{- $_ := set . "port" "8080" -}}
{{- if .Values.expose.tls.enabled }}
{{- $_ := set . "scheme" "HTTPS" -}}
{{- $_ := set . "port" "8443" -}}
{{- end }}
livenessProbe:
httpGet:
scheme: {{ .scheme }}
path: /
port: 80
initialDelaySeconds: 1
port: {{ .port }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
scheme: {{ .scheme }}
path: /
port: 80
port: {{ .port }}
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.nginx.resources }}
......@@ -51,8 +68,8 @@ spec:
{{ toYaml .Values.nginx.resources | indent 10 }}
{{- end }}
ports:
- containerPort: 80
- containerPort: 443
- containerPort: 8080
- containerPort: 8443
- containerPort: 4443
volumeMounts:
- name: config
......@@ -69,11 +86,7 @@ spec:
{{- if .Values.expose.tls.enabled }}
- name: certificate
secret:
{{- if .Values.expose.tls.secretName }}
secretName: {{ .Values.expose.tls.secretName }}
{{- else }}
secretName: {{ template "harbor.nginx" . }}
{{- end }}
secretName: {{ template "harbor.tlsSecretForNginx" . }}
{{- end }}
{{- with .Values.nginx.nodeSelector }}
nodeSelector:
......@@ -87,4 +100,4 @@ spec:
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}
\ No newline at end of file
{{- end }}
{{- if eq (include "harbor.autoGenCertForNginx" .) "true" }}
{{- $ca := genCA "harbor-ca" 365 }}
{{- $cn := (required "The \"expose.tls.commonName\" is required!" .Values.expose.tls.commonName) }}
{{- $cn := (required "The \"expose.tls.auto.commonName\" is required!" .Values.expose.tls.auto.commonName) }}
apiVersion: v1
kind: Secret
metadata:
......
......@@ -5,7 +5,6 @@ metadata:
{{- if eq .Values.expose.type "clusterIP" }}
{{- $clusterIP := .Values.expose.clusterIP }}
name: {{ $clusterIP.name }}
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
......@@ -13,11 +12,11 @@ spec:
ports:
- name: http
port: {{ $clusterIP.ports.httpPort }}
targetPort: 80
targetPort: 8080
{{- if .Values.expose.tls.enabled }}
- name: https
port: {{ $clusterIP.ports.httpsPort }}
targetPort: 443
targetPort: 8443
{{- end }}
{{- if .Values.notary.enabled }}
- name: notary
......@@ -34,14 +33,14 @@ spec:
ports:
- name: http
port: {{ $nodePort.ports.http.port }}
targetPort: 80
targetPort: 8080
{{- if $nodePort.ports.http.nodePort }}
nodePort: {{ $nodePort.ports.http.nodePort }}
{{- end }}
{{- if .Values.expose.tls.enabled }}
- name: https
port: {{ $nodePort.ports.https.port }}
targetPort: 443
targetPort: 8443
{{- if $nodePort.ports.https.nodePort }}
nodePort: {{ $nodePort.ports.https.nodePort }}
{{- end }}
......@@ -59,19 +58,27 @@ spec:
name: {{ $loadBalancer.name }}
labels:
{{ include "harbor.labels" . | indent 4 }}
{{- with $loadBalancer.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: LoadBalancer
{{- with $loadBalancer.sourceRanges }}
loadBalancerSourceRanges:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if $loadBalancer.IP }}
loadBalancerIP: {{ $loadBalancer.IP }}
{{- end }}
ports:
- name: http
port: {{ $loadBalancer.ports.httpPort }}
targetPort: 80
targetPort: 8080
{{- if .Values.expose.tls.enabled }}
- name: https
port: {{ $loadBalancer.ports.httpsPort }}
targetPort: 443
targetPort: 8443
{{- end }}
{{- if .Values.notary.enabled }}
- name: notary
......@@ -81,5 +88,5 @@ spec:
{{- end }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: nginx
{{- end }}
\ No newline at end of file
component: nginx
{{- end }}
{{ if .Values.notary.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: notary
data:
{{ $ca := genCA "harbor-notary-ca" 365 }}
{{ $cert := genSignedCert (include "harbor.notary-signer" .) nil nil 365 $ca }}
{{- if not .Values.notary.secretName }}
notary-signer-ca.crt: |
{{ $ca.Cert | indent 4 }}
notary-signer.crt: |
{{ $cert.Cert | indent 4 }}
notary-signer.key: |
{{ $cert.Key | indent 4 }}
{{- end }}
server-config.postgres.json: |
{
"server": {
"http_addr": ":4443"
},
"trust_service": {
"type": "remote",
"hostname": "{{ template "harbor.notary-signer" . }}",
"port": "7899",
{{- if not .Values.notary.secretName }}
"tls_ca_file": "./notary-signer-ca.crt",
{{- else }}
"tls_ca_file": "/etc/ssl/notary/cert/notary-signer-ca.crt",
{{- end }}
"key_algorithm": "ecdsa"
},
"logging": {
"level": "{{ .Values.logLevel }}"
},
"storage": {
"backend": "postgres",
"db_url": "{{ template "harbor.database.notaryServer" . }}"
},
"auth": {
"type": "token",
"options": {
"realm": "{{ .Values.externalURL }}/service/token",
"service": "harbor-notary",
"issuer": "harbor-token-issuer",
"rootcertbundle": "/root.crt"
}
}
}
signer-config.postgres.json: |
{
"server": {
"grpc_addr": ":7899",
{{- if not .Values.notary.secretName }}
"tls_cert_file": "./notary-signer.crt",
"tls_key_file": "./notary-signer.key"
{{- else }}
"tls_cert_file": "/etc/ssl/notary/cert/notary-signer.crt",
"tls_key_file": "/etc/ssl/notary/cert/notary-signer.key"
{{- end }}
},
"logging": {
"level": "{{ .Values.logLevel }}"
},
"storage": {
"backend": "postgres",
"db_url": "{{ template "harbor.database.notarySigner" . }}",
"default_alias": "defaultalias"
}
}
{{ 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 }}
......@@ -5,25 +5,34 @@ metadata:
name: {{ template "harbor.notary-server" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: notary-server
component: notary-server
spec:
replicas: {{ .Values.notary.server.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: notary-server
component: notary-server
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: notary-server
component: notary-server
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/notary/notary-cm.yaml") . | sha256sum }}
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:
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
image: {{ .Values.notary.server.image.repository }}:{{ .Values.notary.server.image.tag }}
......@@ -38,37 +47,38 @@ spec:
- name: DB_URL
value: {{ template "harbor.database.notaryServer" . }}
volumeMounts:
- name: notary-config
mountPath: /etc/notary
- name: etc-localtime
mountPath: /etc/localtime
- name: root-certificate
- name: config
mountPath: /etc/notary/server-config.postgres.json
subPath: server.json
- name: token-service-certificate
mountPath: /root.crt
subPath: tls.crt
{{- if .Values.notary.secretName }}
- name: notary-ca
mountPath: /etc/ssl/notary/cert/notary-signer-ca.crt
subPath: ca
{{- end }}
- name: signer-certificate
mountPath: /etc/ssl/notary/ca.crt
subPath: ca.crt
- name: etc-localtime
mountPath: /etc/localtime
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
- name: notary-config
configMap:
name: "{{ template "harbor.notary-server" . }}"
- name: root-certificate
path: /etc/localtime
- 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 }}
{{- if .Values.notary.secretName }}
- name: notary-ca
- name: signer-certificate
secret:
{{- if .Values.notary.secretName }}
secretName: {{ .Values.notary.secretName }}
{{- end }}
{{- else }}
secretName: {{ template "harbor.notary-server" . }}
{{- end }}
{{- with .Values.notary.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
......
......@@ -5,21 +5,30 @@ metadata:
name: {{ template "harbor.notary-signer" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: notary-signer
component: notary-signer
spec:
replicas: {{ .Values.notary.signer.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: notary-signer
component: notary-signer
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: notary-signer
component: notary-signer
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/notary/notary-cm.yaml") . | sha256sum }}
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
image: {{ .Values.notary.signer.image.repository }}:{{ .Values.notary.signer.image.tag }}
......@@ -36,33 +45,31 @@ spec:
- name: NOTARY_SIGNER_DEFAULTALIAS
value: defaultalias
volumeMounts:
- name: notary-config
mountPath: /etc/notary
- 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
- name: etc-localtime
mountPath: /etc/localtime
{{- if .Values.notary.secretName }}
- name: notary-cert
mountPath: /etc/ssl/notary/cert/notary-signer-ca.crt
subPath: ca
- name: notary-cert
mountPath: /etc/ssl/notary/cert/notary-signer.crt
subPath: crt
- name: notary-cert
mountPath: /etc/ssl/notary/cert/notary-signer.key
subPath: key
{{- end }}
mountPath: /etc/localtime
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
- name: notary-config
configMap:
name: "{{ template "harbor.notary-server" . }}"
{{- if .Values.notary.secretName }}
- name: notary-cert
path: /etc/localtime
- name: config
secret:
secretName: "{{ template "harbor.notary-server" . }}"
- name: signer-certificate
secret:
{{- if .Values.notary.secretName }}
secretName: {{ .Values.notary.secretName }}
{{- end }}
{{- else }}
secretName: {{ template "harbor.notary-server" . }}
{{- end }}
{{- with .Values.notary.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
......
......@@ -13,7 +13,7 @@ spec:
- port: 4443
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: notary-server
component: notary-server
---
apiVersion: v1
......@@ -27,5 +27,5 @@ spec:
- port: 7899
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: notary-signer
component: notary-signer
{{ end }}
\ No newline at end of file
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ template "harbor.portal" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
nginx.conf: |+
worker_processes auto;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
client_body_temp_path /tmp/client_body_temp;
proxy_temp_path /tmp/proxy_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
server {
{{- if .Values.internalTLS.enabled }}
listen {{ template "harbor.portal.containerPort" . }} ssl;
# SSL
ssl_certificate /etc/harbor/ssl/portal/tls.crt;
ssl_certificate_key /etc/harbor/ssl/portal/tls.key;
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1.2;
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;
{{- else }}
listen {{ template "harbor.portal.containerPort" . }};
{{- 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 / {
try_files $uri $uri/ /index.html;
}
location = /index.html {
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
}
}
......@@ -4,23 +4,35 @@ metadata:
name: "{{ template "harbor.portal" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
app: portal
component: portal
spec:
replicas: {{ .Values.portal.replicas }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: portal
component: portal
template:
metadata:
labels:
{{ include "harbor.matchLabels" . | indent 8 }}
app: portal
component: portal
annotations:
{{- 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 "/portal/tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.portal.podAnnotations }}
{{ toYaml .Values.portal.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.portal.serviceAccountName }}
serviceAccountName: {{ .Values.portal.serviceAccountName }}
{{- end }}
containers:
- name: portal
image: {{ .Values.portal.image.repository }}:{{ .Values.portal.image.tag }}
......@@ -32,24 +44,41 @@ spec:
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 1
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.portal.containerPort" . }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.portal.containerPort" . }}
initialDelaySeconds: 1
periodSeconds: 10
ports:
- containerPort: 80
- containerPort: {{ template "harbor.portal.containerPort" . }}
volumeMounts:
- name: portal-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
{{- if .Values.internalTLS.enabled }}
- name: portal-internal-certs
mountPath: /etc/harbor/ssl/portal
{{- end }}
- name: etc-localtime
mountPath: /etc/localtime
mountPath: /etc/localtime
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
path: /etc/localtime
- 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 }}
......
......@@ -5,12 +5,9 @@ metadata:
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
{{- if (eq .Values.expose.ingress.controller "gce") }}
type: NodePort
{{- end }}
ports:
- port: 80
targetPort: 80
- port: {{ template "harbor.portal.servicePort" . }}
targetPort: {{ template "harbor.portal.containerPort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: portal
component: portal
......@@ -10,5 +10,5 @@ spec:
- port: 6379
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: redis
component: redis
{{- end -}}
\ No newline at end of file
......@@ -6,24 +6,33 @@ metadata:
name: {{ template "harbor.redis" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
app: redis
component: redis
spec:
replicas: 1
serviceName: {{ template "harbor.redis" . }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: redis
component: redis
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: redis
component: redis
{{- if .Values.redis.podAnnotations }}
annotations:
{{ toYaml .Values.redis.podAnnotations | indent 8 }}
{{- end }}
spec:
securityContext:
fsGroup: 999
{{- if .Values.redis.internal.serviceAccountName }}
serviceAccountName: {{ .Values.redis.internal.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: redis
image: {{ .Values.redis.internal.image.repository }}:{{ .Values.redis.internal.image.tag }}
......@@ -31,7 +40,7 @@ spec:
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 1
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
tcpSocket:
......@@ -43,16 +52,24 @@ spec:
{{ toYaml .Values.redis.internal.resources | indent 10 }}
{{- end }}
volumeMounts:
- name: etc-localtime
mountPath: /etc/localtime
- name: data
mountPath: /var/lib/redis
- name: etc-localtime
mountPath: /etc/localtime
subPath: {{ $redis.subPath }}
{{- if not .Values.persistence.enabled }}
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
path: /etc/localtime
- name: data
emptyDir: {}
{{- else if $redis.existingClaim }}
volumes:
- name: data
persistentVolumeClaim:
claimName: {{ $redis.existingClaim }}
{{- end -}}
{{- with .Values.redis.internal.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
......@@ -65,4 +82,23 @@ spec:
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- end -}}
{{- if and .Values.persistence.enabled (not $redis.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: data
labels:
{{ include "harbor.labels" . | indent 8 }}
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 -}}
......@@ -8,7 +8,13 @@ data:
config.yml: |+
version: 0.1
log:
{{- if eq .Values.logLevel "warning" }}
level: warn
{{- else if eq .Values.logLevel "fatal" }}
level: error
{{- else }}
level: {{ .Values.logLevel }}
{{- end }}
fields:
service: registry
storage:
......@@ -47,9 +53,15 @@ data:
{{- if $storage.s3.encrypt }}
encrypt: {{ $storage.s3.encrypt }}
{{- end }}
{{- if $storage.s3.keyid }}
keyid: {{ $storage.s3.keyid }}
{{- end }}
{{- if $storage.s3.secure }}
secure: {{ $storage.s3.secure }}
{{- end }}
{{- if and $storage.s3.secure $storage.s3.skipverify }}
skipverify: {{ $storage.s3.skipverify }}
{{- end }}
{{- if $storage.s3.v4auth }}
v4auth: {{ $storage.s3.v4auth }}
{{- end }}
......@@ -62,6 +74,15 @@ data:
{{- if $storage.s3.storageclass }}
storageclass: {{ $storage.s3.storageclass }}
{{- end }}
{{- if $storage.s3.multipartcopychunksize }}
multipartcopychunksize: {{ $storage.s3.multipartcopychunksize }}
{{- end }}
{{- if $storage.s3.multipartcopymaxconcurrency }}
multipartcopymaxconcurrency: {{ $storage.s3.multipartcopymaxconcurrency }}
{{- end }}
{{- if $storage.s3.multipartcopythresholdsize }}
multipartcopythresholdsize: {{ $storage.s3.multipartcopythresholdsize }}
{{- end }}
{{- else if eq $type "swift" }}
swift:
authurl: {{ $storage.swift.authurl }}
......@@ -140,32 +161,64 @@ data:
redirect:
disable: {{ $storage.disableredirect }}
redis:
addr: "{{ template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}"
db: {{ template "harbor.redis.registryDatabaseIndex" . }}
addr: {{ template "harbor.redis.addr" . }}
{{- if eq "redis+sentinel" (include "harbor.redis.scheme" .) }}
sentinelMasterSet: {{ template "harbor.redis.masterSet" . }}
{{- end }}
db: {{ template "harbor.redis.dbForRegistry" . }}
password: {{ template "harbor.redis.password" . }}
readtimeout: 10s
writetimeout: 10s
dialtimeout: 10s
http:
addr: :5000
addr: :{{ template "harbor.registry.containerPort" . }}
relativeurls: {{ .Values.registry.relativeurls }}
{{- if .Values.internalTLS.enabled }}
tls:
certificate: /etc/harbor/ssl/registry/tls.crt
key: /etc/harbor/ssl/registry/tls.key
minimumtls: tls1.2
{{- end }}
# set via environment variable
# secret: placeholder
debug:
addr: localhost:5001
auth:
token:
issuer: harbor-token-issuer
realm: "{{ .Values.externalURL }}/service/token"
rootcertbundle: /etc/registry/root.crt
service: harbor-registry
htpasswd:
realm: harbor-registry-basic-realm
path: /etc/registry/passwd
validation:
disabled: true
notifications:
endpoints:
- name: harbor
disabled: false
url: http://{{ template "harbor.core" . }}/service/notifications
timeout: 3000ms
threshold: 5
backoff: 1s
compatibility:
schema1:
enabled: true
{{- if .Values.registry.middleware.enabled }}
{{- $middleware := .Values.registry.middleware }}
{{- $middlewareType := $middleware.type }}
{{- if eq $middlewareType "cloudFront" }}
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"
{{- $storage := .Values.persistence.imageChartStorage }}
apiVersion: apps/v1
kind: StatefulSet
kind: Deployment
metadata:
name: "{{ template "harbor.registry" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
app: registry
component: registry
spec:
replicas: {{ .Values.registry.replicas }}
serviceName: "{{ template "harbor.registry" . }}"
strategy:
type: {{ .Values.updateStrategy.type }}
{{- if eq .Values.updateStrategy.type "Recreate" }}
rollingUpdate: null
{{- end }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
app: registry
component: registry
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
app: registry
component: registry
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/registry/registry-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/registry/registry-secret.yaml") . | sha256sum }}
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.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 "/registry/registry-tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.registry.podAnnotations }}
{{ toYaml .Values.registry.podAnnotations | indent 8 }}
{{- end }}
spec:
tolerations:
- effect: NoSchedule
operator: Exists
securityContext:
fsGroup: 10000
{{- if .Values.registry.serviceAccountName }}
serviceAccountName: {{ .Values.registry.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: registry
image: {{ .Values.registry.registry.image.repository }}:{{ .Values.registry.registry.image.tag }}
......@@ -35,121 +51,240 @@ spec:
livenessProbe:
httpGet:
path: /
port: 5000
initialDelaySeconds: 1
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.registry.containerPort" . }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 5000
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.registry.containerPort" . }}
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.registry.registry.resources }}
resources:
{{ toYaml .Values.registry.resources | indent 10 }}
{{ toYaml .Values.registry.registry.resources | indent 10 }}
{{- end }}
args: ["serve", "/etc/registry/config.yml"]
envFrom:
- secretRef:
name: "{{ template "harbor.registry" . }}"
env:
{{- if has "registry" .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/registry/tls.key
- name: INTERNAL_TLS_CERT_PATH
value: /etc/harbor/ssl/registry/tls.crt
- name: INTERNAL_TLS_TRUST_CA_PATH
value: /etc/harbor/ssl/registry/ca.crt
{{- end }}
ports:
- containerPort: 5000
- containerPort: {{ template "harbor.registry.containerPort" . }}
- containerPort: 5001
volumeMounts:
{{- if eq $storage.type "filesystem" }}
- name: data
mountPath: /data
{{- end }}
- name: registry-data
mountPath: {{ .Values.persistence.imageChartStorage.filesystem.rootdirectory }}
subPath: {{ .Values.persistence.persistentVolumeClaim.registry.subPath }}
- name: registry-root-certificate
mountPath: /etc/registry/root.crt
subPath: tls.crt
- name: registry-htpasswd
mountPath: /etc/registry/passwd
subPath: passwd
- name: registry-config
mountPath: /etc/registry/config.yml
subPath: config.yml
{{- if .Values.internalTLS.enabled }}
- name: registry-internal-certs
mountPath: /etc/harbor/ssl/registry
{{- end }}
{{- if and .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs") }}
- name: gcs-key
mountPath: /etc/registry/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.registry.middleware.enabled }}
{{- if eq .Values.registry.middleware.type "cloudFront" }}
- name: cloudfront-key
mountPath: /etc/registry/pk.pem
subPath: pk.pem
{{- end }}
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
- name: etc-localtime
mountPath: /etc/localtime
mountPath: /etc/localtime
- name: registryctl
image: {{ .Values.registry.controller.image.repository }}:{{ .Values.registry.controller.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
livenessProbe:
httpGet:
path: /api/health
port: 8080
initialDelaySeconds: 1
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.registryctl.containerPort" . }}
initialDelaySeconds: 300
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/health
port: 8080
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.registryctl.containerPort" . }}
initialDelaySeconds: 1
periodSeconds: 10
{{- if .Values.registry.controller.resources }}
resources:
{{ toYaml .Values.registry.resources | indent 10 }}
args: ["serve", "/etc/registry/config.yml"]
{{ toYaml .Values.registry.controller.resources | indent 10 }}
{{- end }}
envFrom:
- secretRef:
name: "{{ template "harbor.registry" . }}"
env:
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: "{{ template "harbor.fullname" . }}-jobservice"
key: secret
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: {{ template "harbor.core" . }}
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: {{ template "harbor.jobservice" . }}
key: JOBSERVICE_SECRET
{{- if .Values.internalTLS.enabled }}
- name: INTERNAL_TLS_ENABLED
value: "true"
- name: INTERNAL_TLS_KEY_PATH
value: /etc/harbor/ssl/registry/tls.key
- name: INTERNAL_TLS_CERT_PATH
value: /etc/harbor/ssl/registry/tls.crt
- name: INTERNAL_TLS_TRUST_CA_PATH
value: /etc/harbor/ssl/registry/ca.crt
{{- end }}
ports:
- containerPort: 8080
- containerPort: {{ template "harbor.registryctl.containerPort" . }}
volumeMounts:
{{- if eq $storage.type "filesystem" }}
- name: data
mountPath: /data
{{- end }}
- 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 .Values.persistence.enabled (eq .Values.persistence.imageChartStorage.type "gcs") }}
- name: gcs-key
mountPath: /etc/registry/gcs-key.json
subPath: gcs-key.json
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
- name: etc-localtime
mountPath: /etc/localtime
{{- 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 }}
mountPath: /etc/localtime
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
- name: registry-htpasswd
secret:
secretName: {{ template "harbor.registry" . }}
items:
- key: REGISTRY_HTPASSWD
path: passwd
- name: registry-root-certificate
secret:
{{- if .Values.core.secretName }}
secretName: {{ .Values.core.secretName }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
- name: registry-config
configMap:
name: "{{ template "harbor.registry" . }}"
{{- if eq .Values.registry.storageSpec.type "hostPath" }}
- name: data
- name: registry-data
hostPath:
path: {{.Values.registry.storageSpec.hostPath.root | default "/data" }}/{{ .Release.Namespace }}/{{ .Release.Name }}/registry
{{- else if eq .Values.registry.storageSpec.type "emptyDir" }}
- name: data
- name: registry-data
emptyDir: {}
{{- end }}
{{- end }}
{{- if eq .Values.registry.storageSpec.type "volumeClaimTemplate" }}
volumeClaimTemplates:
- metadata:
name: "data"
name: registry-data
labels:
{{ include "harbor.labels" . | indent 8 }}
app: registry
spec:
{{ toYaml $.Values.registry.storageSpec.volumeClaimTemplate.spec | indent 6 }}
{{- end }}
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: registry-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.registry.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.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 }}
......@@ -6,8 +6,9 @@ metadata:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
REGISTRY_HTPASSWD: {{ .Values.registry.credentials.htpasswd | b64enc | quote }}
REGISTRY_HTTP_SECRET: {{ .Values.registry.secret | default (randAlphaNum 16) | b64enc | quote }}
REGISTRY_REDIS_PASSWORD: {{ (include "harbor.redis.rawPassword" .) | b64enc | quote }}
REGISTRY_REDIS_PASSWORD: {{ (include "harbor.redis.password" .) | b64enc | quote }}
{{- $storage := .Values.persistence.imageChartStorage }}
{{- $type := $storage.type }}
{{- if eq $type "azure" }}
......
......@@ -7,9 +7,9 @@ metadata:
spec:
ports:
- name: registry
port: 5000
port: {{ template "harbor.registry.servicePort" . }}
- name: controller
port: 8080
port: {{ template "harbor.registryctl.servicePort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
app: registry
\ No newline at end of file
component: registry
\ No newline at end of file
{{- if .Values.trivy.enabled }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "harbor.trivy" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
redisURL: {{ include "harbor.redis.urlForTrivy" . | b64enc }}
gitHubToken: {{ .Values.trivy.gitHubToken | default "" | b64enc | quote }}
{{- end }}
{{- if .Values.trivy.enabled }}
{{- $trivy := .Values.persistence.persistentVolumeClaim.trivy }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ template "harbor.trivy" . }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: trivy
spec:
replicas: {{ .Values.trivy.replicas }}
serviceName: {{ template "harbor.trivy" . }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: trivy
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: trivy
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/trivy/trivy-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 "/trivy/trivy-tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.trivy.podAnnotations }}
{{ toYaml .Values.trivy.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.trivy.serviceAccountName }}
serviceAccountName: {{ .Values.trivy.serviceAccountName }}
{{- end }}
securityContext:
runAsNonRoot: true
runAsUser: 10000
fsGroup: 10000
automountServiceAccountToken: false
containers:
- name: trivy
image: {{ .Values.trivy.image.repository }}:{{ .Values.trivy.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
securityContext:
privileged: false
allowPrivilegeEscalation: false
env:
{{- if has "trivy" .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 }}
- name: "SCANNER_LOG_LEVEL"
value: {{ .Values.logLevel | quote }}
- name: "SCANNER_TRIVY_CACHE_DIR"
value: "/home/scanner/.cache/trivy"
- name: "SCANNER_TRIVY_REPORTS_DIR"
value: "/home/scanner/.cache/reports"
- name: "SCANNER_TRIVY_DEBUG_MODE"
value: {{ .Values.trivy.debugMode | quote }}
- name: "SCANNER_TRIVY_VULN_TYPE"
value: {{ .Values.trivy.vulnType | quote }}
- name: "SCANNER_TRIVY_GITHUB_TOKEN"
valueFrom:
secretKeyRef:
name: {{ template "harbor.trivy" . }}
key: gitHubToken
- name: "SCANNER_TRIVY_SEVERITY"
value: {{ .Values.trivy.severity | quote }}
- name: "SCANNER_TRIVY_IGNORE_UNFIXED"
value: {{ .Values.trivy.ignoreUnfixed | default false | quote }}
- name: "SCANNER_TRIVY_SKIP_UPDATE"
value: {{ .Values.trivy.skipUpdate | default false | quote }}
- name: "SCANNER_TRIVY_INSECURE"
value: {{ .Values.trivy.insecure | default false | quote }}
- name: SCANNER_API_SERVER_ADDR
value: ":{{ template "harbor.trivy.containerPort" . }}"
{{- if .Values.internalTLS.enabled }}
- name: INTERNAL_TLS_ENABLED
value: "true"
- name: SCANNER_API_SERVER_TLS_KEY
value: /etc/harbor/ssl/trivy/tls.key
- name: SCANNER_API_SERVER_TLS_CERTIFICATE
value: /etc/harbor/ssl/trivy/tls.crt
{{- end }}
- name: "SCANNER_REDIS_URL"
valueFrom:
secretKeyRef:
name: {{ template "harbor.trivy" . }}
key: redisURL
- name: "SCANNER_STORE_REDIS_URL"
valueFrom:
secretKeyRef:
name: {{ template "harbor.trivy" . }}
key: redisURL
- name: "SCANNER_JOB_QUEUE_REDIS_URL"
valueFrom:
secretKeyRef:
name: {{ template "harbor.trivy" . }}
key: redisURL
ports:
- name: api-server
containerPort: {{ template "harbor.trivy.containerPort" . }}
volumeMounts:
- name: etc-localtime
mountPath: /etc/localtime
- name: data
mountPath: /home/scanner/.cache
subPath: {{ .Values.persistence.persistentVolumeClaim.trivy.subPath }}
readOnly: false
{{- if .Values.internalTLS.enabled }}
- name: trivy-internal-certs
mountPath: /etc/harbor/ssl/trivy
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 10 }}
{{- end }}
livenessProbe:
httpGet:
scheme: {{ include "harbor.component.scheme" . | upper }}
path: /probe/healthy
port: api-server
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 10
readinessProbe:
httpGet:
scheme: {{ include "harbor.component.scheme" . | upper }}
path: /probe/ready
port: api-server
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
resources:
{{ toYaml .Values.trivy.resources | indent 12 }}
{{- if or (or .Values.internalTLS.enabled .Values.caBundleSecretName) (or (not .Values.persistence.enabled) $trivy.existingClaim) }}
volumes:
- name: etc-localtime
hostPath:
path: /etc/localtime
{{- if .Values.internalTLS.enabled }}
- name: trivy-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.trivy.secretName" . }}
{{- end }}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- if not .Values.persistence.enabled }}
- name: "data"
emptyDir: {}
{{- else if $trivy.existingClaim }}
- name: "data"
persistentVolumeClaim:
claimName: {{ $trivy.existingClaim }}
{{- end }}
{{- end }}
{{- with .Values.trivy.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.trivy.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.trivy.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if and .Values.persistence.enabled (not $trivy.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: data
labels:
{{ include "harbor.labels" . | indent 8 }}
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 }}
apiVersion: v1
kind: Service
metadata:
name: "{{ template "harbor.trivy" . }}"
labels:
{{ include "harbor.labels" . | indent 4 }}
spec:
ports:
- name: api-server
protocol: TCP
port: {{ template "harbor.trivy.servicePort" . }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: trivy
{{ 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 test
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
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: false
imageChartStorage:
# s3 , filesystem
type: s3
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: 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: 2.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
\ No newline at end of file
......@@ -4,69 +4,91 @@ expose:
enabled: false
ingress:
hosts:
core: hub.test.wodcloud.com
notary: notary.test.wodcloud.com
core: hub.ywtest.wodcloud.com
notary: notary.ywtest.wodcloud.com
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:
name: harbor
ports:
httpPort: 80
httpsPort: 443
notaryPort: 4443
externalURL: https://hub.test.wodcloud.com
externalURL: https://hub.ywtest.wodcloud.com
internalTLS:
enabled: false
persistence:
enabled: true
enabled: false
# Define which storage backend is used for registry and chartmuseum to store
imageChartStorage:
# s3 , filesystem
disableredirect: false
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: /
#maxthreads: 100
imagePullPolicy: IfNotPresent
updateStrategy:
type: RollingUpdate
logLevel: info
harborAdminPassword: "spaceIN511"
secretKey: "IpTIscRIgmerlare"
secretKey: "not-a-secure-key"
proxy:
httpProxy:
httpsProxy:
noProxy: 127.0.0.1,localhost,.local,.internal
components:
- core
- jobservice
- clair
- trivy
portal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-portal
tag: v1.8.2
repository: reg.local:5000/wod/harbor-portal
tag: v2.1.0
replicas: 1
core:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-core
tag: v1.8.2
repository: reg.local:5000/wod/harbor-core
tag: v2.1.0
replicas: 1
startupProbe:
initialDelaySeconds: 10
jobservice:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-jobservice
tag: v1.8.2
repository: reg.local:5000/wod/harbor-jobservice
tag: v2.1.0
replicas: 1
maxJobWorkers: 10
jobLogger: file
nodeSelector:
harbor: enabled
registry:
registry:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/registry
tag: 2.7.1
resources:
limits:
memory: 4Gi
requests:
memory: 256Mi
nodeSelector:
harbor: enabled
repository: reg.local:5000/wod/registry-photon
tag: v2.1.0
controller:
image:
repository: reg.local:5000/wod/harbor-registryctl
tag: v2.1.0
replicas: 1
nodeSelector:
harbor: enabled
storageSpec:
# type: emptyDir , hostPath , volumeClaimTemplate
type: hostPath
......@@ -80,54 +102,87 @@ registry:
resources:
requests:
storage: 100Gi
selector: {}
controller:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-registryctl
tag: v1.8.2
replicas: 1
selector: {}
relativeurls: false
credentials:
username: "harbor_registry_user"
password: "harbor_registry_password"
htpasswd: "harbor_registry_user:$2y$10$9L4Tc0DJbFFMB6RdSCunrOpTHdwhid4ktBJmLD00bYgqkkGOvll3m"
middleware:
enabled: false
chartmuseum:
enabled: true
absoluteUrl: false
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/chartmuseum-photon
tag: v0.9.0-v1.8.2
repository: reg.local:5000/wod/chartmuseum-photon
tag: v2.1.0
replicas: 1
nodeSelector:
harbor: enabled
nodeSelector:
harbor: enabled
storageSpec:
type: hostPath
emptyDir: {}
hostPath:
root: /data
root: /data
clair:
enabled: true
clair:
image:
repository: reg.local:5000/wod/clair-photon
tag: v2.1.0
adapter:
image:
repository: reg.local:5000/wod/clair-adapter-photon
tag: v2.1.0
replicas: 1
updatersInterval: 12
nodeSelector:
harbor: enabled
trivy:
enabled: true
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/clair-photon
tag: v2.0.8-v1.8.2
repository: reg.local:5000/wod/trivy-adapter-photon
tag: v2.1.0
replicas: 1
debugMode: false
vulnType: "os,library"
severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
ignoreUnfixed: false
insecure: false
skipUpdate: false
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1
memory: 1Gi
notary:
enabled: true
server:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-server-photon
tag: v0.6.1-v1.8.2
repository: reg.local:5000/wod/notary-server-photon
tag: v2.1.0
replicas: 1
signer:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/notary-signer-photon
tag: v0.6.1-v1.8.2
repository: reg.local:5000/wod/notary-signer-photon
tag: v2.1.0
replicas: 1
database:
# if external database is used, set "type" to "external" and fill the connection informations in "external" section
type: internal
internal:
serviceAccountName: ""
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/harbor-db
tag: v1.8.2
repository: reg.local:5000/wod/harbor-db
tag: v2.1.0
password: "spaceIN511"
resources:
limits:
......@@ -140,7 +195,7 @@ database:
type: hostPath
emptyDir: {}
hostPath:
root: /data
root: /data
volumeClaimTemplate:
spec:
storageClassName: rook-ceph-block
......@@ -149,10 +204,19 @@ database:
requests:
storage: 20Gi
selector: {}
external:
host: "harbor-harbor-database.devops"
port: "5432"
username: "postgres"
password: "spaceIN511"
coreDatabase: "registry"
clairDatabase: "clair"
notaryServerDatabase: "notary_server"
notarySignerDatabase: "notary_signer"
redis:
type: internal
internal:
image:
repository: registry.cn-qingdao.aliyuncs.com/wod/redis
tag: 4.0.14-alpine
\ No newline at end of file
repository: reg.local:5000/wod/redis-photon
tag: v2.1.0
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: 2.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
\ No newline at end of file
expose:
# Set the way how to expose the service. Set the type as "ingress",
# "clusterIP", "nodePort" or "loadBalancer" and fill the information
# 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
# 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
# images. Refer to https://github.com/goharbor/harbor/issues/5291
# for the detail.
enabled: true
# Fill the name of secret if you want to use your own TLS certificate.
# The secret must contain keys named:
# "tls.crt" - the certificate
# "tls.key" - the private key
# "ca.crt" - the certificate of CA
# These files will be generated automatically if the "secretName" is not set
secretName: ""
# By default, the Notary service will use the same cert and key as
# described above. Fill the name of secret if you want to use a
# separated one. Only needed when the type is "ingress".
notarySecretName: ""
# The common name used to generate the certificate, it's necessary
# when the type isn't "ingress" and "secretName" is null
commonName: ""
# 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
......@@ -33,10 +41,10 @@ expose:
# 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"
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
......@@ -45,7 +53,7 @@ expose:
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
# The service port Notary listens on. Only needed when notary.enabled
# is set to true
notaryPort: 4443
nodePort:
......@@ -57,13 +65,13 @@ expose:
port: 80
# The node port Harbor listens on when serving with HTTP
nodePort: 30002
https:
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:
notary:
# The service port Notary listens on
port: 4443
# The node port Notary listens on
......@@ -78,40 +86,113 @@ expose:
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
# 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
# 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
#
# 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.
# 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",
# 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
# 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,
# 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
......@@ -133,7 +214,7 @@ persistence:
subPath: ""
accessMode: ReadWriteOnce
size: 1Gi
# If external database is used, the following settings for database will
# If external database is used, the following settings for database will
# be ignored
database:
existingClaim: ""
......@@ -141,7 +222,7 @@ persistence:
subPath: ""
accessMode: ReadWriteOnce
size: 1Gi
# If external Redis is used, the following settings for Redis will
# If external Redis is used, the following settings for Redis will
# be ignored
redis:
existingClaim: ""
......@@ -149,19 +230,30 @@ persistence:
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
# 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
# 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 type of storage: "filesystem", "azure", "gcs", "s3", "swift",
# 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
......@@ -189,10 +281,14 @@ persistence:
#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
......@@ -227,17 +323,61 @@ persistence:
imagePullPolicy: IfNotPresent
logLevel: debug
# 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: v1.8.2-dev
tag: dev
# set the service account to be used, default if left empty
serviceAccountName: ""
replicas: 1
# resources:
# requests:
......@@ -252,12 +392,14 @@ nginx:
portal:
image:
repository: goharbor/harbor-portal
tag: v1.8.2-dev
tag: dev
# set the service account to be used, default if left empty
serviceAccountName: ""
replicas: 1
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
......@@ -267,12 +409,17 @@ portal:
core:
image:
repository: goharbor/harbor-core
tag: v1.8.2-dev
tag: dev
# set the service account to be used, default if left empty
serviceAccountName: ""
replicas: 1
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
## Startup probe values
startupProbe:
initialDelaySeconds: 10
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
......@@ -289,19 +436,23 @@ core:
# "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: v1.8.2-dev
tag: dev
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
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
nodeSelector: {}
tolerations: []
affinity: {}
......@@ -313,10 +464,12 @@ jobservice:
secret: ""
registry:
# set the service account to be used, default if left empty
serviceAccountName: ""
registry:
image:
repository: goharbor/registry-photon
tag: v1.8.2-dev
tag: dev
# resources:
# requests:
# memory: 256Mi
......@@ -324,7 +477,8 @@ registry:
controller:
image:
repository: goharbor/harbor-registryctl
tag: v1.8.2-dev
tag: dev
# resources:
# requests:
# memory: 256Mi
......@@ -341,12 +495,36 @@ registry:
# 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: v1.8.2-dev
tag: dev
replicas: 1
# resources:
# requests:
......@@ -360,20 +538,85 @@ chartmuseum:
clair:
enabled: true
image:
repository: goharbor/clair-photon
tag: v1.8.2-dev
# set the service account to be used, default if left empty
serviceAccountName: ""
clair:
image:
repository: goharbor/clair-photon
tag: dev
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
adapter:
image:
repository: goharbor/clair-adapter-photon
tag: dev
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
replicas: 1
# The http(s) proxy used to update vulnerabilities database from internet
httpProxy:
httpsProxy:
# The interval of clair updaters, the unit is hour, set to 0 to
# The interval of clair updaters, the unit is hour, set to 0 to
# disable the updaters
updatersInterval: 12
# resources:
# requests:
# memory: 256Mi
# cpu: 100m
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: dev
# 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: {}
......@@ -383,18 +626,22 @@ clair:
notary:
enabled: true
server:
# set the service account to be used, default if left empty
serviceAccountName: ""
image:
repository: goharbor/notary-server-photon
tag: v1.8.2-dev
tag: dev
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: v1.8.2-dev
tag: dev
replicas: 1
# resources:
# requests:
......@@ -408,7 +655,7 @@ notary:
# 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 tls.ca, tls.crt and tls.key that
# 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: ""
......@@ -418,9 +665,11 @@ database:
# 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: v1.8.2-dev
tag: dev
# The initial superuser password for internal database
password: "changeit"
# resources:
......@@ -439,7 +688,21 @@ database:
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: {}
......@@ -448,9 +711,11 @@ redis:
# 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: v1.8.2-dev
tag: dev
# resources:
# requests:
# memory: 256Mi
......@@ -459,14 +724,20 @@ redis:
tolerations: []
affinity: {}
external:
host: "192.168.0.2"
port: "6379"
# 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: {}
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