diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..abc98e0f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +charts/* +requirements.lock \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..94c833358 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing to Helm Chart for Harbor + +Please follow [Harbor contributing guide](https://github.com/vmware/harbor/blob/master/CONTRIBUTING.md) to learn how to make code contribution. + +# Contributers + +Thanks very much to all contributers who submitted pull requests to Helm Chart for Harbor. + +- [Paul Czarkowski @paulczar](https://github.com/paulczar) +- [Luca Innocenti Mirri @lucaim](https://github.com/lucaim) +- [Steven Arnott @ArcticSnowman](https://github.com/ArcticSnowman) +- [Alex M @draeron](https://github.com/draeron) +- [SangJun Yun](https://github.com/YunSangJun) diff --git a/Chart.yaml b/Chart.yaml new file mode 100644 index 000000000..f28ab582f --- /dev/null +++ b/Chart.yaml @@ -0,0 +1,19 @@ +name: harbor +version: 0.2.0 +appVersion: 1.5.0 +description: An Enterprise-class Docker Registry by VMware +keywords: +- vmware +- docker +- registry +- harbor +home: https://github.com/vmware/harbor +icon: https://raw.githubusercontent.com/vmware/harbor/master/docs/img/harbor_logo.png +sources: +- https://github.com/vmware/harbor/tree/master/contrib/helm/harbor +maintainers: +- name: Jesse Hu + email: huh@vmware.com +- name: paulczar + email: username.taken@gmail.com +engine: gotpl diff --git a/README.md b/README.md new file mode 100644 index 000000000..0aa894b78 --- /dev/null +++ b/README.md @@ -0,0 +1,211 @@ +# Helm Chart for Harbor + +## Introduction + +This [Helm](https://github.com/kubernetes/helm) chart installs [Harbor](http://vmware.github.io/harbor/) in a Kubernetes cluster. Welcome to [contribute](CONTRIBUTING.md) to Helm Chart for Harbor. + +## Prerequisites + +- Kubernetes cluster 1.8+ with Beta APIs enabled +- Kubernetes Ingress Controller is enabled +- Helm CLI 2.8.0+ + +## Setup a Kubernetes cluster + +You can use any tools to setup a K8s cluster. +In this guide, we use [minikube](https://github.com/kubernetes/minikube) 0.25.0 to setup a K8s cluster as the dev/test env. +```bash +# Start minikube +minikube start --vm-driver=none +# Enable Ingress Controller +minikube addons enable ingress +``` +## Installing the Chart + +First install [Helm CLI](https://github.com/kubernetes/helm#install), then initialize Helm. +```bash +helm init +``` +Download Harbor helm chart code. +```bash +git clone https://github.com/vmware/harbor +cd harbor/contrib/helm/harbor +``` +Download external dependent charts required by Harbor chart. +```bash +helm dependency update +``` +Install the Harbor helm chart with a release name `my-release`: +```bash +helm install --debug --name my-release --set externalDomain=harbor.my.domain,externalPort=443 . +``` +**Note:** Make sure `harbor.my.domain` can be resolved to the K8s Ingress Controller IP on the machines where you run docker or access Harbor UI. +You can add `harbor.my.domain` and IP mapping in the DNS server, or in /etc/hosts, or use the FQDN `harbor..xip.io`. + +The command deploys Harbor on the Kubernetes cluster with the default configuration. +The [configuration](#configuration) section lists the parameters that can be configured in values.yaml or via '--set' flag during installation. + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```bash +helm delete my-release +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Configuration + +The following tables lists the configurable parameters of the Harbor chart and the default values. + +| Parameter | Description | Default | +| ----------------------- | ---------------------------------- | ----------------------- | +| **Harbor** | +| `persistence.enabled` | Persistent data | `true` | +| `externalProtocol` | The protocol Harbor serves with | `https` | +| `externalDomain` | Harbor will run on (https://`externalDomain`/). Recommend using K8s Ingress Controller FQDN as `externalDomain`, or make sure this FQDN resolves to the K8s Ingress Controller IP. | `harbor.my.domain` | +| `externalPort` | The external port Harbor serves on. Configure it with the port of Ingress controller if it is enabled | `32700` | +| `harborAdminPassword` | The password of system admin | `Harbor12345` | +| `authenticationMode` | The authentication mode: `db_auth` for local database, `ldap_auth` for LDAP | `db_auth` | +| `selfRegistration` | Allows users to register by themselves, otherwise only system administrators can add users | `on` | +| `email.host` | The hostname of email server | `smtp.mydomain.com` | +| `email.port` | The port of email server | `25` | +| `email.username` | The username of email server | `sample_admin@mydomain.com` | +| `email.password` | The password for email server | `password` | +| `email.ssl` | Whether use TLS | `false` | +| `email.insecure` | Whether the connection with email server is insecure | `false` | +| `email.from` | The from address shows when send email| `admin ` | +| `email.identity` | | | +| `ldap.url` | LDAP server URL for `ldap_auth` authentication | `ldaps://ldapserver` | +| `ldap.searchDN` | LDAP search DN | | +| `ldap.searchPassword` | LDAP search password | | +| `ldap.baseDN` | LDAP base DN | | +| `ldap.filter` | LDAP filter | `(objectClass=person)` | +| `ldap.uid` | LDAP UID | `uid` | +| `ldap.scope` | LDAP scope | `2` | +| `ldap.timeout` | LDAP timeout | `5` | +| `ldap.verifyCert` | Whether to verify HTTPS certificate | `true` | +| `secretkey` | The key used for encryption. Must be a string of 16 chars | `not-a-secure-key` | +| `harborImageTag` | The tag of Harbor images | `dev` | +| **Ingress** | +| `ingress.enabled` | Enable ingress objects | `true` | +| `ingress.tls.secretName` | Fill the secretName if you want to use the certificate of yourself when Harbor serves with HTTPS. A certificate will be generated automatically by the chart if leave it empty | | +| **Adminserver** | +| `adminserver.image.repository` | Repository for adminserver image | `vmware/harbor-adminserver` | +| `adminserver.image.tag` | Tag for adminserver image | `dev` | +| `adminserver.image.pullPolicy` | Pull Policy for adminserver image | `IfNotPresent` | +| `adminserver.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined | +| `adminserver.volumes` | used to create PVCs if persistence is enabled (see instructions in values.yaml) | see values.yaml | +| `adminserver.nodeSelector` | Node labels for pod assignment | `{}` | +| `adminserver.tolerations` | Tolerations for pod assignment | `[]` | +| `adminserver.affinity` | Node/Pod affinities | `{}` | +| **Jobservice** | +| `jobservice.image.repository` | Repository for jobservice image | `vmware/harbor-jobservice` | +| `jobservice.image.tag` | Tag for jobservice image | `dev` | +| `jobservice.image.pullPolicy` | Pull Policy for jobservice image | `IfNotPresent` | +| `jobservice.secret` | jobservice secret | `not-a-secure-secret` | +| `jobservice.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined | +| `jobservice.nodeSelector` | Node labels for pod assignment | `{}` | +| `jobservice.tolerations` | Tolerations for pod assignment | `[]` | +| `jobservice.affinity` | Node/Pod affinities | `{}` | +| **UI** | +| `ui.image.repository` | Repository for ui image | `vmware/harbor-ui` | +| `ui.image.tag` | Tag for ui image | `dev` | +| `ui.image.pullPolicy` | Pull Policy for ui image | `IfNotPresent` | +| `ui.secret` | ui secret | `not-a-secure-secret` | +| `ui.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined | +| `ui.nodeSelector` | Node labels for pod assignment | `{}` | +| `ui.tolerations` | Tolerations for pod assignment | `[]` | +| `ui.affinity` | Node/Pod affinities | `{}` | +| **Database** | +| `database.type` | If external database is used, set it to `external` | `internal` | +| `database.internal.image.repository` | Repository for database image | `vmware/harbor-db` | +| `database.internal.image.tag` | Tag for database image | `dev` | +| `database.internal.image.pullPolicy` | Pull Policy for database image | `IfNotPresent` | +| `database.internal.password` | The password for database | `changeit` | +| `database.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined | +| `database.internal.volumes` | The volume used to persistent data | +| `database.internal.nodeSelector` | Node labels for pod assignment | `{}` | +| `database.internal.tolerations` | Tolerations for pod assignment | `[]` | +| `database.internal.affinity` | Node/Pod affinities | `{}` | +| `database.external.host` | The hostname of external database | `192.168.0.1` | +| `database.external.port` | The port of external database | `5432` | +| `database.external.username` | The username of external database | `user` | +| `database.external.password` | The password of external database | `password` | +| `database.external.coreDatabase` | The database used by core service | `registry` | +| `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` | +| **Registry** | +| `registry.image.repository` | Repository for registry image | `vmware/registry-photon` | +| `registry.image.tag` | Tag for registry image | `dev` | +| `registry.image.pullPolicy` | Pull Policy for registry image | `IfNotPresent` | +| `registry.httpSecret` | registry secret | `not-a-secure-secret` | +| `registry.logLevel` | The log level | `info` | +| `registry.storage.type` | The storage used to store images: `filesystem`, `azure`, `gcs`, `s3`, `swift`, `oss` | `filesystem` | +| `registry.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined | +| `registry.volumes` | used to create PVCs if persistence is enabled (see instructions in values.yaml) | see values.yaml | +| `registry.nodeSelector` | Node labels for pod assignment | `{}` | +| `registry.tolerations` | Tolerations for pod assignment | `[]` | +| `registry.affinity` | Node/Pod affinities | `{}` | +| **Chartmuseum** | +| `chartmuseum.enabled` | Enable chartmusuem to store chart | `true` | +| `chartmuseum.image.repository` | Repository for chartmuseum image | `vmware/chartmuseum-photon` | +| `chartmuseum.image.tag` | Tag for chartmuseum image | `dev` | +| `chartmuseum.image.pullPolicy` | Pull Policy for chartmuseum image | `IfNotPresent` | +| `chartmuseum.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined | +| `chartmuseum.volumes` | used to create PVCs if persistence is enabled (see instructions in values.yaml) | see values.yaml | +| `chartmuseum.nodeSelector` | Node labels for pod assignment | `{}` | +| `chartmuseum.tolerations` | Tolerations for pod assignment | `[]` | +| `chartmuseum.affinity` | Node/Pod affinities | `{}` | +| **Clair** | +| `clair.enabled` | Enable Clair? | `true` | +| `clair.image.repository` | Repository for clair image | `vmware/clair-photon` | +| `clair.image.tag` | Tag for clair image | `dev` +| `clair.resources` | [resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) to allocate for container | undefined +| `clair.nodeSelector` | Node labels for pod assignment | `{}` | +| `clair.tolerations` | Tolerations for pod assignment | `[]` | +| `clair.affinity` | Node/Pod affinities | `{}` | +| **Redis** | +| `redis.usePassword` | Whether use password | `false` | +| `redis.password` | The password for Redis | `changeit` | +| `redis.cluster.enabled` | Enable Redis cluster | `false` | +| `redis.master.persistence.enabled` | Persistent data | `false` | +| `redis.external.enabled` | If an external Redis is used, set it to `true` | `false` | +| `redis.external.host` | The hostname of external Redis | `192.168.0.2` | +| `redis.external.port` | The port of external Redis | `6379` | +| `redis.external.databaseIndex` | The database index of external Redis | `0` | +| `redis.external.usePassword` | Whether use password for external Redis | `false` | +| `redis.external.password` | The password of external Redis | `changeit` | +| **Notary** | +| `notary.enabled` | Enable Notary? | `true` | +| `notary.server.image.repository` | Repository for notary server image | `vmware/notary-server-photon` | +| `notary.server.image.tag` | Tag for notary server image | `dev` +| `notary.signer.image.repository` | Repository for notary signer image | `vmware/notary-signer-photon` | +| `notary.signer.image.tag` | Tag for notary signer image | `dev` +| `notary.nodeSelector` | Node labels for pod assignment | `{}` | +| `notary.tolerations` | Tolerations for pod assignment | `[]` | +| `notary.affinity` | Node/Pod affinities | `{}` | + +## Persistence + +You need to create `StorageClass` before you can persist data in persistent volume. + +To create a `StorageClass`, set the following value in `values.yaml`: + +```yaml +persistence: + enabled: true + +``` + +Four PVCs will be created automatically: +- adminserver-config +- chartmuseum-data +- database-data +- registry-data + +All the created PVCs need to be removed manually after Helm deletes the Chart. + +When running a cluster without persistence, this Chart uses `emptyDir` as the temporary volumes. Data does not survive the termination of a pod. diff --git a/requirements.yaml b/requirements.yaml new file mode 100644 index 000000000..ba4799613 --- /dev/null +++ b/requirements.yaml @@ -0,0 +1,4 @@ +dependencies: +- name: redis + version: 3.2.5 + repository: https://kubernetes-charts.storage.googleapis.com diff --git a/templates/NOTES.txt b/templates/NOTES.txt new file mode 100644 index 000000000..ce1120810 --- /dev/null +++ b/templates/NOTES.txt @@ -0,0 +1,3 @@ +Please wait for several minutes for Harbor deployment to complete. +Then you should be able to visit the UI portal at {{ template "harbor.externalURL" . }}. +For more details, please visit https://github.com/vmware/harbor. \ No newline at end of file diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl new file mode 100644 index 000000000..9d8a5f573 --- /dev/null +++ b/templates/_helpers.tpl @@ -0,0 +1,194 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "harbor.name" -}} +{{- default "harbor" .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "harbor.fullname" -}} +{{- $name := default "harbor" .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* Helm required labels */}} +{{- define "harbor.labels" -}} +heritage: {{ .Release.Service }} +release: {{ .Release.Name }} +chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app: "{{ template "harbor.name" . }}" +{{- end -}} + +{{/* matchLabels */}} +{{- define "harbor.matchLabels" -}} +release: {{ .Release.Name }} +app: "{{ template "harbor.name" . }}" +{{- end -}} + +{{- define "harbor.externalURL" -}} +{{- if .Values.externalPort -}} +{{- printf "%s://%s:%s" .Values.externalProtocol .Values.externalDomain (toString .Values.externalPort) -}} +{{- else -}} +{{- printf "%s://%s" .Values.externalProtocol .Values.externalDomain -}} +{{- end -}} +{{- end -}} + +{{/* +Use *.domain.com as the Common Name in the certificate, +so it can match Harbor service FQDN and Notary service FQDN. +*/}} +{{- define "harbor.certCommonName" -}} +{{- $list := splitList "." .Values.externalDomain -}} +{{- $list := prepend (rest $list) "*" -}} +{{- $cn := join "." $list -}} +{{- printf "%s" $cn -}} +{{- end -}} + +{{/* The external FQDN of Notary server. */}} +{{- define "harbor.notaryFQDN" -}} +{{- printf "notary-%s" .Values.externalDomain -}} +{{- end -}} + +{{- define "harbor.notaryServiceName" -}} +{{- printf "%s-notary-server" (include "harbor.fullname" .) -}} +{{- end -}} + +{{- define "harbor.database.host" -}} + {{- if eq .Values.database.type "internal" -}} + {{- template "harbor.fullname" . }}-database + {{- else -}} + {{- .Values.database.external.host -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.port" -}} + {{- if eq .Values.database.type "internal" -}} + {{- printf "%s" "5432" -}} + {{- else -}} + {{- .Values.database.external.port -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.username" -}} + {{- if eq .Values.database.type "internal" -}} + {{- printf "%s" "postgres" -}} + {{- else -}} + {{- .Values.database.external.username -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.password" -}} + {{- if eq .Values.database.type "internal" -}} + {{- .Values.database.internal.password | b64enc | quote -}} + {{- else -}} + {{- .Values.database.external.password | b64enc | quote -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.rawPassword" -}} + {{- if eq .Values.database.type "internal" -}} + {{- .Values.database.internal.password -}} + {{- else -}} + {{- .Values.database.external.password -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.coreDatabase" -}} + {{- if eq .Values.database.type "internal" -}} + {{- printf "%s" "registry" -}} + {{- else -}} + {{- .Values.database.external.coreDatabase -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.clairDatabase" -}} + {{- if eq .Values.database.type "internal" -}} + {{- printf "%s" "postgres" -}} + {{- else -}} + {{- .Values.database.external.clairDatabase -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.notaryServerDatabase" -}} + {{- if eq .Values.database.type "internal" -}} + {{- printf "%s" "notaryserver" -}} + {{- else -}} + {{- .Values.database.external.notaryServerDatabase -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.notarySignerDatabase" -}} + {{- if eq .Values.database.type "internal" -}} + {{- printf "%s" "notarysigner" -}} + {{- else -}} + {{- .Values.database.external.notarySignerDatabase -}} + {{- end -}} +{{- end -}} + +{{- define "harbor.database.clair" -}} +postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.rawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.clairDatabase" . }}?sslmode=disable +{{- end -}} + +{{- define "harbor.database.notaryServer" -}} +postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.rawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.notaryServerDatabase" . }}?sslmode=disable +{{- end -}} + +{{- define "harbor.database.notarySigner" -}} +postgres://{{ template "harbor.database.username" . }}:{{ template "harbor.database.rawPassword" . }}@{{ template "harbor.database.host" . }}:{{ template "harbor.database.port" . }}/{{ template "harbor.database.notarySignerDatabase" . }}?sslmode=disable +{{- end -}} + +{{- define "harbor.redis.host" -}} + {{- if .Values.redis.external.enabled -}} + {{- .Values.redis.external.host -}} + {{- else -}} + {{- .Release.Name }}-redis-master + {{- end -}} +{{- end -}} + +{{- define "harbor.redis.port" -}} + {{- if .Values.redis.external.enabled -}} + {{- .Values.redis.external.port -}} + {{- else -}} + {{- .Values.redis.master.port }} + {{- end -}} +{{- end -}} + +{{- define "harbor.redis.databaseIndex" -}} + {{- if .Values.redis.external.enabled -}} + {{- .Values.redis.external.databaseIndex -}} + {{- else -}} + {{- printf "%s" "0" }} + {{- end -}} +{{- end -}} + +{{- define "harbor.redis.password" -}} + {{- if and .Values.redis.external.enabled .Values.redis.external.usePassword -}} + {{- .Values.redis.external.password -}} + {{- else if and (not .Values.redis.external.enabled) .Values.redis.usePassword -}} + {{- .Values.redis.password -}} + {{- end -}} +{{- end -}} + +{{/*the username redis is used for a placeholder as no username needed in redis*/}} +{{- define "harbor.redisForJobservice" -}} + {{- if and .Values.redis.external.enabled .Values.redis.external.usePassword -}} + redis:{{ template "harbor.redis.password" . }}@{{ template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}/{{ template "harbor.redis.databaseIndex" }} + {{- else if and (not .Values.redis.external.enabled) .Values.redis.usePassword -}} + redis:{{ template "harbor.redis.password" . }}@{{ template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}/{{ template "harbor.redis.databaseIndex" }} + {{- else }} + {{- template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}/{{ template "harbor.redis.databaseIndex" }} + {{- end -}} +{{- end -}} + +{{/* +host:port,pool_size,password +100 is the default value of pool size +*/}} +{{- define "harbor.redisForUI" -}} + {{- template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }},100,{{ template "harbor.redis.password" . }} +{{- end -}} diff --git a/templates/adminserver/adminserver-cm.yaml b/templates/adminserver/adminserver-cm.yaml new file mode 100644 index 000000000..b27488628 --- /dev/null +++ b/templates/adminserver/adminserver-cm.yaml @@ -0,0 +1,60 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ template "harbor.fullname" . }}-adminserver" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: adminserver +data: + POSTGRESQL_HOST: "{{ template "harbor.database.host" . }}" + POSTGRESQL_PORT: "{{ template "harbor.database.port" . }}" + POSTGRESQL_USERNAME: "{{ template "harbor.database.username" . }}" + POSTGRESQL_DATABASE: "{{ template "harbor.database.coreDatabase" . }}" + EMAIL_HOST: "{{ .Values.email.host }}" + EMAIL_PORT: "{{ .Values.email.port }}" + EMAIL_USR: "{{ .Values.email.username }}" + EMAIL_SSL: "{{ .Values.email.ssl }}" + EMAIL_FROM: "{{ .Values.email.from }}" + EMAIL_IDENTITY: "{{ .Values.email.identity }}" + EMAIL_INSECURE: "{{ .Values.email.insecure }}" + EXT_ENDPOINT: "{{ template "harbor.externalURL" . }}" + UI_URL: "http://{{ template "harbor.fullname" . }}-ui" + JOBSERVICE_URL: "http://{{ template "harbor.fullname" . }}-jobservice" + REGISTRY_URL: "http://{{ template "harbor.fullname" . }}-registry:5000" + TOKEN_SERVICE_URL: "http://{{ template "harbor.fullname" . }}-ui/service/token" + WITH_NOTARY: "{{ .Values.notary.enabled }}" + NOTARY_URL: "http://{{ template "harbor.notaryServiceName" . }}:4443" + LOG_LEVEL: "info" + IMAGE_STORE_PATH: "/" # This is a temporary hack. + AUTH_MODE: "{{ .Values.authenticationMode }}" + SELF_REGISTRATION: "{{ .Values.selfRegistration }}" + LDAP_URL: "{{ .Values.ldap.url }}" + LDAP_SEARCH_DN: "{{ .Values.ldap.searchDN }}" + LDAP_BASE_DN: "{{ .Values.ldap.baseDN }}" + LDAP_FILTER: "{{ .Values.ldap.filter }}" + LDAP_UID: "{{ .Values.ldap.uid }}" + LDAP_SCOPE: "{{ .Values.ldap.scope }}" + LDAP_TIMEOUT: "{{ .Values.ldap.timeout }}" + LDAP_VERIFY_CERT: "{{ .Values.ldap.verifyCert }}" + DATABASE_TYPE: "postgresql" + PROJECT_CREATION_RESTRICTION: "everyone" + VERIFY_REMOTE_CERT: "off" + MAX_JOB_WORKERS: "3" + TOKEN_EXPIRATION: "30" + CFG_EXPIRATION: "5" + GODEBUG: "netdns=cgo" + ADMIRAL_URL: "NA" + RESET: "false" + 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_URL: "http://{{ template "harbor.fullname" . }}-clair:6060" + UAA_ENDPOINT: "" + UAA_CLIENTID: "" + UAA_CLIENTSECRET: "" + UAA_VERIFY_CERT: "True" + REGISTRY_STORAGE_PROVIDER_NAME: "{{ .Values.registry.storage.type }}" + WITH_CHARTMUSEUM: "{{ .Values.chartmuseum.enabled }}" + CHART_REPOSITORY_URL: "http://{{ template "harbor.fullname" . }}-chartmuseum" \ No newline at end of file diff --git a/templates/adminserver/adminserver-secrets.yaml b/templates/adminserver/adminserver-secrets.yaml new file mode 100644 index 000000000..0d5a3dfcd --- /dev/null +++ b/templates/adminserver/adminserver-secrets.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Secret +metadata: + name: "{{ template "harbor.fullname" . }}-adminserver" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: adminserver +type: Opaque +data: + secretKey: {{ .Values.secretKey | b64enc | quote }} + EMAIL_PWD: {{ .Values.email.password | b64enc | quote }} + HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }} + POSTGRESQL_PASSWORD: {{ template "harbor.database.password" . }} + JOBSERVICE_SECRET: {{ .Values.jobservice.secret | b64enc | quote }} + UI_SECRET: {{ .Values.ui.secret | b64enc | quote }} +{{- if eq .Values.authenticationMode "ldap_auth" }} + LDAP_SEARCH_PWD: {{ .Values.ldap.searchPassword | b64enc | quote }} +{{- end }} +{{ if .Values.clair.enabled }} + CLAIR_DB_PASSWORD: {{ template "harbor.database.password" . }} +{{ end }} diff --git a/templates/adminserver/adminserver-ss.yaml b/templates/adminserver/adminserver-ss.yaml new file mode 100644 index 000000000..3032486ba --- /dev/null +++ b/templates/adminserver/adminserver-ss.yaml @@ -0,0 +1,86 @@ +apiVersion: apps/v1beta2 +kind: StatefulSet +metadata: + name: "{{ template "harbor.fullname" . }}-adminserver" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: adminserver +spec: + replicas: 1 + serviceName: "{{ template "harbor.fullname" . }}-adminserver" + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: adminserver + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: adminserver + spec: + containers: + - name: adminserver + image: "{{ .Values.adminserver.image.repository }}:{{ .Values.adminserver.image.tag }}" + imagePullPolicy: "{{ .Values.adminserver.image.pullPolicy }}" + resources: +{{ toYaml .Values.adminserver.resources | indent 10 }} + envFrom: + - configMapRef: + name: "{{ template "harbor.fullname" . }}-adminserver" + - secretRef: + name: "{{ template "harbor.fullname" . }}-adminserver" + env: + - name: PORT + value: "8080" + - name: JSON_CFG_STORE_PATH + value: /etc/adminserver/config/config.json + - name: KEY_PATH + value: /etc/adminserver/key + ports: + - containerPort: 8080 + volumeMounts: + - name: adminserver-config + mountPath: /etc/adminserver/config + - name: adminserver-key + mountPath: /etc/adminserver/key + subPath: key + volumes: + {{- if not .Values.persistence.enabled }} + - name: adminserver-config + emptyDir: {} + {{- end }} + - name: adminserver-key + secret: + secretName: "{{ template "harbor.fullname" . }}-adminserver" + items: + - key: secretKey + path: key + {{- with .Values.adminserver.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.adminserver.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.adminserver.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: adminserver-config + spec: + accessModes: [{{ .Values.adminserver.volumes.config.accessMode | quote }}] + {{- if .Values.adminserver.volumes.config.storageClass }} + {{- if (eq "-" .Values.adminserver.volumes.config.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.adminserver.volumes.config.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.adminserver.volumes.config.size | quote }} + {{- end -}} diff --git a/templates/adminserver/adminserver-svc.yaml b/templates/adminserver/adminserver-svc.yaml new file mode 100644 index 000000000..d613b71ab --- /dev/null +++ b/templates/adminserver/adminserver-svc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "harbor.fullname" . }}-adminserver" +spec: + ports: + - port: 80 + targetPort: 8080 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: adminserver \ No newline at end of file diff --git a/templates/chartmuseum/chartmuseum-cm.yaml b/templates/chartmuseum/chartmuseum-cm.yaml new file mode 100644 index 000000000..40cbab42c --- /dev/null +++ b/templates/chartmuseum/chartmuseum-cm.yaml @@ -0,0 +1,33 @@ +{{- if .Values.chartmuseum.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ template "harbor.fullname" . }}-chartmuseum" + labels: +{{ include "harbor.labels" . | indent 4 }} +data: + PORT: "9999" + CACHE: "redis" + CACHE_REDIS_ADDR: "{{ template "harbor.redis.host" }}:{{ template "harbor.redis.port" }}" + CACHE_REDIS_DB: "{{ template "harbor.redis.databaseIndex" }}" + BASIC_AUTH_USER: "chart_controller" + DEPTH: "1" + STORAGE: "local" + STORAGE_LOCAL_ROOTDIR: "/chart_storage" + DEBUG: "false" + LOG_JSON: "true" + DISABLE_METRICS: "false" + DISABLE_API: "false" + DISABLE_STATEFILES: "false" + ALLOW_OVERWRITE: "true" + CHART_URL: + AUTH_ANONYMOUS_GET: "false" + TLS_CERT: + TLS_KEY: + CONTEXT_PATH: + INDEX_LIMIT: "0" + MAX_STORAGE_OBJECTS: "0" + MAX_UPLOAD_SIZE: "20971520" + CHART_POST_FORM_FIELD_NAME: "chart" + PROV_POST_FORM_FIELD_NAME: "prov" +{{- end }} \ No newline at end of file diff --git a/templates/chartmuseum/chartmuseum-secret.yaml b/templates/chartmuseum/chartmuseum-secret.yaml new file mode 100644 index 000000000..8266171e0 --- /dev/null +++ b/templates/chartmuseum/chartmuseum-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.chartmuseum.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: "{{ template "harbor.fullname" . }}-chartmuseum" + labels: +{{ include "harbor.labels" . | indent 4 }} +type: Opaque +data: + CACHE_REDIS_PASSWORD: "{{ template "harbor.redis.password" }}" + BASIC_AUTH_PASS: {{ .Values.ui.secret | b64enc | quote }} +{{- end }} \ No newline at end of file diff --git a/templates/chartmuseum/chartmuseum-ss.yaml b/templates/chartmuseum/chartmuseum-ss.yaml new file mode 100644 index 000000000..38963cc85 --- /dev/null +++ b/templates/chartmuseum/chartmuseum-ss.yaml @@ -0,0 +1,72 @@ +{{- if .Values.chartmuseum.enabled }} +apiVersion: apps/v1beta2 +kind: StatefulSet +metadata: + name: "{{ template "harbor.fullname" . }}-chartmuseum" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: chartmuseum +spec: + replicas: 1 + serviceName: "{{ template "harbor.fullname" . }}-chartmuseum" + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: chartmuseum + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: chartmuseum + spec: + containers: + - name: chartmuseum + image: {{ .Values.chartmuseum.image.repository }}:{{ .Values.chartmuseum.image.tag }} + imagePullPolicy: {{ .Values.chartmuseum.image.pullPolicy }} + resources: +{{ toYaml .Values.chartmuseum.resources | indent 10 }} + envFrom: + - configMapRef: + name: "{{ template "harbor.fullname" . }}-chartmuseum" + - secretRef: + name: "{{ template "harbor.fullname" . }}-chartmuseum" + ports: + - containerPort: 9999 + # TODO: update it after moving the storage out of registry scope + {{- if (.Values.persistence.enabled) and eq .Values.registry.storage.type "filesystem" }} + volumeMounts: + - name: chartmuseum-data + mountPath: /chart_storage + {{- end }} + {{- with .Values.chartmuseum.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.chartmuseum.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.chartmuseum.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if (.Values.persistence.enabled) and eq .Values.registry.storage.type "filesystem" }} + volumeClaimTemplates: + - metadata: + name: chartmuseum-data + labels: +{{ include "harbor.labels" . | indent 8 }} + spec: + accessModes: [{{ .Values.chartmuseum.volumes.data.accessMode | quote }}] + {{- if .Values.chartmuseum.volumes.data.storageClass }} + {{- if (eq "-" .Values.chartmuseum.volumes.data.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.chartmuseum.volumes.data.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.chartmuseum.volumes.data.size | quote }} + {{- end -}} +{{- end }} \ No newline at end of file diff --git a/templates/chartmuseum/chartmuseum-svc.yaml b/templates/chartmuseum/chartmuseum-svc.yaml new file mode 100644 index 000000000..664d8ce2f --- /dev/null +++ b/templates/chartmuseum/chartmuseum-svc.yaml @@ -0,0 +1,15 @@ +{{- if .Values.chartmuseum.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "harbor.fullname" . }}-chartmuseum" + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 80 + targetPort: 9999 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: chartmuseum +{{- end }} \ No newline at end of file diff --git a/templates/clair/clair-cm.yaml b/templates/clair/clair-cm.yaml new file mode 100644 index 000000000..8d223f42c --- /dev/null +++ b/templates/clair/clair-cm.yaml @@ -0,0 +1,35 @@ +{{ if .Values.clair.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "harbor.fullname" . }}-clair + labels: +{{ include "harbor.labels" . | indent 4 }} + component: 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: 12h + + notifier: + attempts: 3 + renotifyinterval: 2h + http: + endpoint: "http://{{ template "harbor.fullname" . }}-ui/service/notifications/clair" +{{ end }} diff --git a/templates/clair/clair-dpl.yaml b/templates/clair/clair-dpl.yaml new file mode 100644 index 000000000..02a79d5e6 --- /dev/null +++ b/templates/clair/clair-dpl.yaml @@ -0,0 +1,53 @@ +{{ if .Values.clair.enabled }} +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: {{ template "harbor.fullname" . }}-clair + labels: +{{ include "harbor.labels" . | indent 4 }} + component: clair +spec: + replicas: 1 + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: clair + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: clair + spec: + containers: + - name: clair + image: {{ .Values.clair.image.repository }}:{{ .Values.clair.image.tag }} + imagePullPolicy: {{ .Values.clair.image.pullPolicy }} + args: ["-insecure-tls", "-config", "/etc/clair/config.yaml"] + resources: +{{ toYaml .Values.clair.resources | indent 10 }} + ports: + - containerPort: 6060 + volumeMounts: + - name: clair-config + mountPath: /etc/clair/config.yaml + subPath: config.yaml + volumes: + - name: clair-config + configMap: + name: "{{ template "harbor.fullname" . }}-clair" + items: + - key: config.yaml + path: config.yaml + {{- with .Values.clair.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.clair.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.clair.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} +{{ end }} diff --git a/templates/clair/clair-svc.yaml b/templates/clair/clair-svc.yaml new file mode 100644 index 000000000..5b305a367 --- /dev/null +++ b/templates/clair/clair-svc.yaml @@ -0,0 +1,17 @@ +{{ if .Values.clair.enabled }} +# clair host isn't configurable yet. this creates a service +# to get it working for now. +# see https://github.com/vmware/harbor/issues/3250 +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "harbor.fullname" . }}-clair" + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 6060 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: clair +{{ end }} diff --git a/templates/database/database-secret.yaml b/templates/database/database-secret.yaml new file mode 100644 index 000000000..0e2e2fec2 --- /dev/null +++ b/templates/database/database-secret.yaml @@ -0,0 +1,11 @@ +{{- if eq .Values.database.type "internal" -}} +apiVersion: v1 +kind: Secret +metadata: + name: "{{ template "harbor.fullname" . }}-database" + labels: +{{ include "harbor.labels" . | indent 4 }} +type: Opaque +data: + POSTGRES_PASSWORD: {{ template "harbor.database.password" . }} +{{- end -}} diff --git a/templates/database/database-ss.yaml b/templates/database/database-ss.yaml new file mode 100644 index 000000000..ab85fb32d --- /dev/null +++ b/templates/database/database-ss.yaml @@ -0,0 +1,77 @@ +{{- if eq .Values.database.type "internal" -}} +apiVersion: apps/v1beta2 +kind: StatefulSet +metadata: + name: "{{ template "harbor.fullname" . }}-database" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: database +spec: + replicas: 1 + serviceName: "{{ template "harbor.fullname" . }}-database" + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: database + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: database + spec: + initContainers: + - name: "remove-lost-found" + image: "busybox:1.25.0" + command: ["rm", "-Rf", "/var/lib/postgresql/data/lost+found"] + volumeMounts: + - name: database-data + mountPath: /var/lib/postgresql/data + containers: + - name: database + image: {{ .Values.database.internal.image.repository }}:{{ .Values.database.internal.image.tag }} + imagePullPolicy: {{ .Values.database.internal.image.pullPolicy }} + resources: +{{ toYaml .Values.database.internal.resources | indent 10 }} + envFrom: + - secretRef: + name: "{{ template "harbor.fullname" . }}-database" + volumeMounts: + - name: database-data + mountPath: /var/lib/postgresql/data + {{- if not .Values.persistence.enabled }} + volumes: + - name: "database-data" + emptyDir: {} + {{- end -}} + {{- with .Values.database.internal.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.database.internal.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.database.internal.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: "database-data" + labels: +{{ include "harbor.labels" . | indent 8 }} + spec: + accessModes: [{{ .Values.database.internal.volumes.data.accessMode | quote }}] + {{- if .Values.database.internal.volumes.data.storageClass }} + {{- if (eq "-" .Values.database.internal.volumes.data.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.database.internal.volumes.data.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.database.internal.volumes.data.size | quote }} + {{- end -}} + {{- end -}} diff --git a/templates/database/database-svc.yaml b/templates/database/database-svc.yaml new file mode 100644 index 000000000..900d329dd --- /dev/null +++ b/templates/database/database-svc.yaml @@ -0,0 +1,14 @@ +{{- if eq .Values.database.type "internal" -}} +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "harbor.fullname" . }}-database" + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 5432 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: database +{{- end -}} \ No newline at end of file diff --git a/templates/ingress/ingress.yaml b/templates/ingress/ingress.yaml new file mode 100644 index 000000000..523e2c727 --- /dev/null +++ b/templates/ingress/ingress.yaml @@ -0,0 +1,37 @@ +{{ if .Values.ingress.enabled }} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: "{{ template "harbor.fullname" . }}-ingress" + labels: +{{ include "harbor.labels" . | indent 4 }} + annotations: +{{ toYaml .Values.ingress.annotations | indent 4 }} +spec: +{{ if eq .Values.externalProtocol "https" }} + tls: + - hosts: + - "{{ .Values.externalDomain }}" + - "{{ template "harbor.notaryFQDN" . }}" + {{ if eq .Values.ingress.tls.secretName "" }} + secretName: "{{ template "harbor.fullname" . }}-ingress" + {{ else }} + secretName: {{ .Values.ingress.tls.secretName }} + {{ end }} +{{ end }} + rules: + - host: "{{ .Values.externalDomain }}" + http: + paths: + - path: / + backend: + serviceName: {{ template "harbor.fullname" . }}-ui + servicePort: 80 + - host: "{{ template "harbor.notaryFQDN" . }}" + http: + paths: + - path: / + backend: + serviceName: {{ template "harbor.notaryServiceName" . }} + servicePort: 4443 +{{ end }} \ No newline at end of file diff --git a/templates/ingress/secret.yaml b/templates/ingress/secret.yaml new file mode 100644 index 000000000..33d13ee36 --- /dev/null +++ b/templates/ingress/secret.yaml @@ -0,0 +1,19 @@ +{{ if eq .Values.externalProtocol "https" }} +{{ if .Values.ingress.enabled }} +{{ if eq .Values.ingress.tls.secretName "" }} +{{ $ca := genCA "harbor-ca" 3650 }} +{{ $cert := genSignedCert (include "harbor.certCommonName" .) nil nil 3650 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: "{{ template "harbor.fullname" . }}-ingress" + labels: +{{ include "harbor.labels" . | indent 4 }} +type: kubernetes.io/tls +data: + tls.crt: {{ .Values.tlsCrt | default $cert.Cert | b64enc | quote }} + tls.key: {{ .Values.tlsKey | default $cert.Key | b64enc | quote }} + ca.crt: {{ .Values.caCrt | default $ca.Cert | b64enc | quote }} +{{ end }} +{{ end }} +{{ end }} \ No newline at end of file diff --git a/templates/jobservice/jobservice-cm.yaml b/templates/jobservice/jobservice-cm.yaml new file mode 100644 index 000000000..b52c03fed --- /dev/null +++ b/templates/jobservice/jobservice-cm.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ template "harbor.fullname" . }}-jobservice" + labels: +{{ include "harbor.labels" . | indent 4 }} +data: + config.yml: |+ + protocol: "http" + port: 8080 + worker_pool: + workers: {{ .Values.jobservice.maxWorkers }} + backend: "redis" + redis_pool: + redis_url: "{{ template "harbor.redisForJobservice" . }}" + namespace: "harbor_job_service_namespace" + logger: + path: "/var/log/jobs" + level: "INFO" + archive_period: 14 #days + admin_server: "http://{{ template "harbor.fullname" . }}-adminserver" diff --git a/templates/jobservice/jobservice-dpl.yaml b/templates/jobservice/jobservice-dpl.yaml new file mode 100644 index 000000000..e7755250b --- /dev/null +++ b/templates/jobservice/jobservice-dpl.yaml @@ -0,0 +1,59 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: "{{ template "harbor.fullname" . }}-jobservice" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: jobservice +spec: + replicas: 1 + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: jobservice + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: jobservice + spec: + containers: + - name: jobservice + image: {{ .Values.jobservice.image.repository }}:{{ .Values.jobservice.image.tag }} + imagePullPolicy: {{ .Values.jobservice.image.pullPolicy }} + resources: +{{ toYaml .Values.jobservice.resources | indent 10 }} + envFrom: + - secretRef: + name: "{{ template "harbor.fullname" . }}-jobservice" + env: + - name: LOG_LEVEL + value: debug + - name: GODEBUG + value: netdns=cgo + ports: + - containerPort: 8080 + volumeMounts: + - name: jobservice-config + mountPath: /etc/jobservice/config.yml + subPath: config.yml + - name: job-logs + mountPath: /var/log/jobs + volumes: + - name: jobservice-config + configMap: + name: "{{ template "harbor.fullname" . }}-jobservice" + - name: job-logs + emptyDir: {} + {{- with .Values.jobservice.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.jobservice.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.jobservice.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} diff --git a/templates/jobservice/jobservice-secrets.yaml b/templates/jobservice/jobservice-secrets.yaml new file mode 100644 index 000000000..64264802c --- /dev/null +++ b/templates/jobservice/jobservice-secrets.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: "{{ template "harbor.fullname" . }}-jobservice" + labels: +{{ include "harbor.labels" . | indent 4 }} +type: Opaque +data: + secretKey: {{ .Values.secretKey | b64enc | quote }} + JOBSERVICE_SECRET: {{ .Values.jobservice.secret | b64enc | quote }} + UI_SECRET: {{ .Values.ui.secret | b64enc | quote }} \ No newline at end of file diff --git a/templates/jobservice/jobservice-svc.yaml b/templates/jobservice/jobservice-svc.yaml new file mode 100644 index 000000000..0dd1462bc --- /dev/null +++ b/templates/jobservice/jobservice-svc.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "harbor.fullname" . }}-jobservice" + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 80 + targetPort: 8080 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: jobservice diff --git a/templates/notary/notary-cm.yaml b/templates/notary/notary-cm.yaml new file mode 100644 index 000000000..520de9af9 --- /dev/null +++ b/templates/notary/notary-cm.yaml @@ -0,0 +1,63 @@ +{{ if .Values.notary.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "harbor.fullname" . }}-notary + labels: +{{ include "harbor.labels" . | indent 4 }} + component: notary +data: + {{ $ca := genCA "harbor-notary-ca" 3650 }} + {{ $cert := genSignedCert (printf "%s-notary-signer" (include "harbor.fullname" .)) nil nil 3650 $ca }} + notary-signer-ca.crt: | +{{ .Values.notary.signer.caCrt | default $ca.Cert | indent 4 }} + notary-signer.crt: | +{{ .Values.notary.signer.tlsCrt | default $cert.Cert | indent 4 }} + notary-signer.key: | +{{ .Values.notary.signer.tlsKey | default $cert.Key | indent 4 }} + server-config.postgres.json: | + { + "server": { + "http_addr": ":4443" + }, + "trust_service": { + "type": "remote", + "hostname": "{{ template "harbor.fullname" . }}-notary-signer", + "port": "7899", + "tls_ca_file": "./notary-signer-ca.crt", + "key_algorithm": "ecdsa" + }, + "logging": { + "level": "debug" + }, + "storage": { + "backend": "postgres", + "db_url": "{{ template "harbor.database.notaryServer" . }}" + }, + "auth": { + "type": "token", + "options": { + "realm": "{{ template "harbor.externalURL" . }}/service/token", + "service": "harbor-notary", + "issuer": "harbor-token-issuer", + "rootcertbundle": "/root.crt" + } + } + } + signer-config.postgres.json: | + { + "server": { + "grpc_addr": ":7899", + "tls_cert_file": "./notary-signer.crt", + "tls_key_file": "./notary-signer.key" + }, + "logging": { + "level": "debug" + }, + "storage": { + "backend": "postgres", + "db_url": "{{ template "harbor.database.notarySigner" . }}", + "default_alias": "defaultalias" + } + } +{{ end }} diff --git a/templates/notary/notary-server.yaml b/templates/notary/notary-server.yaml new file mode 100644 index 000000000..db5e28696 --- /dev/null +++ b/templates/notary/notary-server.yaml @@ -0,0 +1,57 @@ +{{ if .Values.notary.enabled }} +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: {{ template "harbor.fullname" . }}-notary-server + labels: +{{ include "harbor.labels" . | indent 4 }} + component: notary-server +spec: + replicas: 1 + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: notary-server + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: notary-server + spec: + containers: + - name: notary-server + image: {{ .Values.notary.server.image.repository }}:{{ .Values.notary.server.image.tag }} + imagePullPolicy: {{ .Values.notary.server.image.pullPolicy }} + resources: +{{ toYaml .Values.notary.server.resources | indent 10 }} + env: + - name: MIGRATIONS_PATH + value: migrations/server/postgresql + - name: DB_URL + value: {{ template "harbor.database.notaryServer" . }} + volumeMounts: + - name: notary-config + mountPath: /etc/notary + - name: root-certificate + mountPath: /root.crt + subPath: tokenServiceRootCertBundle + volumes: + - name: notary-config + configMap: + name: "{{ template "harbor.fullname" . }}-notary" + - name: root-certificate + secret: + secretName: "{{ template "harbor.fullname" . }}-ui" + {{- with .Values.notary.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.notary.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.notary.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} +{{ end }} diff --git a/templates/notary/notary-signer.yaml b/templates/notary/notary-signer.yaml new file mode 100644 index 000000000..1fedd705c --- /dev/null +++ b/templates/notary/notary-signer.yaml @@ -0,0 +1,41 @@ +{{ if .Values.notary.enabled }} +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: {{ template "harbor.fullname" . }}-notary-signer + labels: +{{ include "harbor.labels" . | indent 4 }} + component: notary-signer +spec: + replicas: 1 + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: notary-signer + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: notary-signer + spec: + containers: + - name: notary-signer + image: {{ .Values.notary.signer.image.repository }}:{{ .Values.notary.signer.image.tag }} + imagePullPolicy: {{ .Values.notary.signer.image.pullPolicy }} + resources: +{{ toYaml .Values.notary.signer.resources | indent 10 }} + env: + - name: MIGRATIONS_PATH + value: migrations/signer/postgresql + - name: DB_URL + value: {{ template "harbor.database.notarySigner" . }} + - name: NOTARY_SIGNER_DEFAULTALIAS + value: {{ .Values.notary.signer.env.NOTARY_SIGNER_DEFAULTALIAS }} + volumeMounts: + - name: notary-config + mountPath: /etc/notary + volumes: + - name: notary-config + configMap: + name: "{{ template "harbor.fullname" . }}-notary" +{{ end }} diff --git a/templates/notary/notary-svc.yaml b/templates/notary/notary-svc.yaml new file mode 100644 index 000000000..613ede94d --- /dev/null +++ b/templates/notary/notary-svc.yaml @@ -0,0 +1,28 @@ +{{ if .Values.notary.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "harbor.notaryServiceName" . }} + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 4443 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: notary-server + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ template "harbor.fullname" . }}-notary-signer + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 7899 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: notary-signer +{{ end }} \ No newline at end of file diff --git a/templates/registry/registry-cm.yaml b/templates/registry/registry-cm.yaml new file mode 100644 index 000000000..d579f1cf4 --- /dev/null +++ b/templates/registry/registry-cm.yaml @@ -0,0 +1,162 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ template "harbor.fullname" . }}-registry" + labels: +{{ include "harbor.labels" . | indent 4 }} +data: + config.yml: |+ + version: 0.1 + log: + level: {{ .Values.registry.logLevel }} + fields: + service: registry + storage: + {{- $storage := .Values.registry.storage }} + {{- $type := $storage.type }} + {{- if eq $type "filesystem" }} + filesystem: + rootdirectory: {{ $storage.filesystem.rootdirectory }} + {{- if $storage.filesystem.maxthreads }} + maxthreads: {{ $storage.filesystem.maxthreads }} + {{- end }} + {{- else if eq $type "azure" }} + azure: + accountname: {{ $storage.azure.accountname }} + container: {{ $storage.azure.container }} + {{- if $storage.azure.realm }} + realm: {{ $storage.azure.realm }} + {{- end }} + {{- else if eq $type "gcs" }} + gcs: + bucket: {{ $storage.gcs.bucket }} + {{- if $storage.gcs.rootdirectory }} + rootdirectory: {{ $storage.gcs.rootdirectory }} + {{- end }} + {{- if $storage.gcs.chunksize }} + chunksize: {{ $storage.gcs.chunksize }} + {{- end }} + {{- else if eq $type "s3" }} + s3: + region: {{ $storage.s3.region }} + bucket: {{ $storage.s3.bucket }} + {{- if $storage.s3.regionendpoint }} + regionendpoint: {{ $storage.s3.regionendpoint }} + {{- end }} + {{- if $storage.s3.encrypt }} + encrypt: {{ $storage.s3.encrypt }} + {{- end }} + {{- if $storage.s3.secure }} + secure: {{ $storage.s3.secure }} + {{- end }} + {{- if $storage.s3.v4auth }} + v4auth: {{ $storage.s3.v4auth }} + {{- end }} + {{- if $storage.s3.chunksize }} + chunksize: {{ $storage.s3.chunksize }} + {{- end }} + {{- if $storage.s3.rootdirectory }} + rootdirectory: {{ $storage.s3.rootdirectory }} + {{- end }} + {{- if $storage.s3.storageclass }} + storageclass: {{ $storage.s3.storageclass }} + {{- end }} + {{- else if eq $type "swift" }} + swift: + authurl: {{ $storage.swift.authurl }} + username: {{ $storage.swift.username }} + container: {{ $storage.swift.container }} + {{- if $storage.swift.region }} + region: {{ $storage.swift.region }} + {{- end }} + {{- if $storage.swift.tenant }} + tenant: {{ $storage.swift.tenant }} + {{- end }} + {{- if $storage.swift.tenantid }} + tenantid: {{ $storage.swift.tenantid }} + {{- end }} + {{- if $storage.swift.domain }} + domain: {{ $storage.swift.domain }} + {{- end }} + {{- if $storage.swift.domainid }} + domainid: {{ $storage.swift.domainid }} + {{- end }} + {{- if $storage.swift.trustid }} + trustid: {{ $storage.swift.trustid }} + {{- end }} + {{- if $storage.swift.insecureskipverify }} + insecureskipverify: {{ $storage.swift.insecureskipverify }} + {{- end }} + {{- if $storage.swift.chunksize }} + chunksize: {{ $storage.swift.chunksize }} + {{- end }} + {{- if $storage.swift.prefix }} + prefix: {{ $storage.swift.prefix }} + {{- end }} + {{- if $storage.swift.authversion }} + authversion: {{ $storage.swift.authversion }} + {{- end }} + {{- if $storage.swift.endpointtype }} + endpointtype: {{ $storage.swift.endpointtype }} + {{- end }} + {{- if $storage.swift.tempurlcontainerkey }} + tempurlcontainerkey: {{ $storage.swift.tempurlcontainerkey }} + {{- end }} + {{- if $storage.swift.tempurlmethods }} + tempurlmethods: {{ $storage.swift.tempurlmethods }} + {{- end }} + {{- else if eq $type "oss" }} + oss: + accesskeyid: {{ $storage.oss.accesskeyid }} + region: {{ $storage.oss.region }} + bucket: {{ $storage.oss.bucket }} + {{- if $storage.oss.endpoint }} + endpoint: {{ $storage.oss.endpoint }} + {{- end }} + {{- if $storage.oss.internal }} + internal: {{ $storage.oss.internal }} + {{- end }} + {{- if $storage.oss.encrypt }} + encrypt: {{ $storage.oss.encrypt }} + {{- end }} + {{- if $storage.oss.secure }} + secure: {{ $storage.oss.secure }} + {{- end }} + {{- if $storage.oss.chunksize }} + chunksize: {{ $storage.oss.chunksize }} + {{- end }} + {{- if $storage.oss.rootdirectory }} + rootdirectory: {{ $storage.oss.rootdirectory }} + {{- end }} + {{- end }} + cache: + layerinfo: redis + maintenance: + uploadpurging: + enabled: false + delete: + enabled: true + redis: + addr: "{{ template "harbor.redis.host" . }}:{{ template "harbor.redis.port" . }}" + password: {{ template "harbor.redis.password" . }} + db: {{ template "harbor.redis.databaseIndex" . }} + http: + addr: :5000 + # set via environment variable + # secret: placeholder + debug: + addr: localhost:5001 + auth: + token: + issuer: harbor-token-issuer + realm: "{{ template "harbor.externalURL" . }}/service/token" + rootcertbundle: /etc/registry/root.crt + service: harbor-registry + notifications: + endpoints: + - name: harbor + disabled: false + url: http://{{ template "harbor.fullname" . }}-ui/service/notifications + timeout: 3000ms + threshold: 5 + backoff: 1s diff --git a/templates/registry/registry-secret.yaml b/templates/registry/registry-secret.yaml new file mode 100644 index 000000000..e13dbfdbf --- /dev/null +++ b/templates/registry/registry-secret.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Secret +metadata: + name: "{{ template "harbor.fullname" . }}-registry" + labels: +{{ include "harbor.labels" . | indent 4 }} +type: Opaque +data: + httpSecret: {{ .Values.registry.httpSecret | b64enc | quote }} + {{- $storage := .Values.registry.storage }} + {{- $type := $storage.type }} + {{- if eq $type "azure" }} + accountkey: {{ $storage.azure.accountkey | b64enc | quote }} + {{- else if eq $type "s3" }} + {{- if $storage.s3.accesskey }} + accesskey: {{ $storage.s3.accesskey | b64enc | quote }} + {{- end }} + {{- if $storage.s3.secretkey }} + secretkey: {{ $storage.s3.secretkey | b64enc | quote }} + {{- end }} + {{- else if eq $type "swift" }} + password: {{ $storage.swift.password }} + {{- if $storage.swift.secretkey }} + secretkey: {{ $storage.swift.secretkey }} + {{- end }} + {{- if $storage.swift.accesskey }} + accesskey: {{ $storage.swift.accesskey }} + {{- end }} + {{- else if eq $type "oss" }} + accesskeysecret: {{ $storage.oss.accesskeysecret }} + {{- end }} \ No newline at end of file diff --git a/templates/registry/registry-ss.yaml b/templates/registry/registry-ss.yaml new file mode 100644 index 000000000..3f47313a1 --- /dev/null +++ b/templates/registry/registry-ss.yaml @@ -0,0 +1,135 @@ +apiVersion: apps/v1beta2 +kind: StatefulSet +metadata: + name: "{{ template "harbor.fullname" . }}-registry" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: registry +spec: + replicas: 1 + serviceName: "{{ template "harbor.fullname" . }}-registry" + selector: + matchLabels: +{{ include "harbor.matchLabels" . | indent 6 }} + component: registry + template: + metadata: + labels: +{{ include "harbor.labels" . | indent 8 }} + component: registry + spec: + containers: + - name: registry + image: {{ .Values.registry.image.repository }}:{{ .Values.registry.image.tag }} + imagePullPolicy: {{ .Values.registry.image.pullPolicy }} + resources: +{{ toYaml .Values.registry.resources | indent 10 }} + args: ["serve", "/etc/registry/config.yml"] + env: + - name: REGISTRY_HTTP_SECRET + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: httpSecret + {{- $storage := .Values.registry.storage }} + {{- $type := $storage.type }} + {{- if eq $type "azure" }} + - name: REGISTRY_STORAGE_AZURE_ACCOUNTKEY + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: accountkey + {{- else if eq $type "s3" }} + {{- if $storage.s3.accesskey }} + - name: REGISTRY_STORAGE_S3_ACCESSKEY + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: accesskey + {{- end }} + {{- if $storage.s3.secretkey }} + - name: REGISTRY_STORAGE_S3_SECRETKEY + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: secretkey + {{- end }} + {{- else if eq $type "swift" }} + - name: REGISTRY_STORAGE_SWIFT_PASSWORD + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: password + {{- if $storage.swift.secretkey }} + - name: REGISTRY_STORAGE_SWIFT_SECRETKEY + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: secretkey + {{- end }} + {{- if $storage.swift.accesskey }} + - name: REGISTRY_STORAGE_SWIFT_ACCESSKEY + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: accesskey + {{- end }} + {{- else if eq $type "oss" }} + - name: REGISTRY_STORAGE_OSS_ACCESSKEYSECRET + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-registry" + key: accesskeysecret + {{- end }} + ports: + - containerPort: 5000 + - containerPort: 5001 + volumeMounts: + {{- if (.Values.persistence.enabled) and eq .Values.registry.storage.type "filesystem" }} + - name: registry-data + mountPath: {{ .Values.registry.storage.filesystem.rootdirectory }} + {{- end }} + - name: registry-root-certificate + mountPath: /etc/registry/root.crt + subPath: tokenServiceRootCertBundle + - name: registry-config + mountPath: /etc/registry/config.yml + subPath: config.yml + volumes: + - name: registry-root-certificate + secret: + secretName: "{{ template "harbor.fullname" . }}-ui" + - name: registry-config + configMap: + name: "{{ template "harbor.fullname" . }}-registry" + {{- with .Values.registry.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.registry.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.registry.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if (.Values.persistence.enabled) and eq .Values.registry.storage.type "filesystem" }} + volumeClaimTemplates: + - metadata: + name: registry-data + labels: +{{ include "harbor.labels" . | indent 8 }} + spec: + accessModes: [{{ .Values.registry.volumes.data.accessMode | quote }}] + {{- if .Values.registry.volumes.data.storageClass }} + {{- if (eq "-" .Values.registry.volumes.data.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.registry.volumes.data.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.registry.volumes.data.size | quote }} + {{- end }} diff --git a/templates/registry/registry-svc.yaml b/templates/registry/registry-svc.yaml new file mode 100644 index 000000000..13f956091 --- /dev/null +++ b/templates/registry/registry-svc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "harbor.fullname" . }}-registry" + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 5000 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: registry \ No newline at end of file diff --git a/templates/ui/ui-cm.yaml b/templates/ui/ui-cm.yaml new file mode 100644 index 000000000..6cd0b05d6 --- /dev/null +++ b/templates/ui/ui-cm.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: "{{ template "harbor.fullname" . }}-ui" + labels: +{{ include "harbor.labels" . | indent 4 }} +data: + app.conf: |+ + appname = Harbor + runmode = prod + enablegzip = true + + [prod] + httpport = 8080 diff --git a/templates/ui/ui-dpl.yaml b/templates/ui/ui-dpl.yaml new file mode 100644 index 000000000..cf2a9afb9 --- /dev/null +++ b/templates/ui/ui-dpl.yaml @@ -0,0 +1,106 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: "{{ template "harbor.fullname" . }}-ui" + labels: +{{ include "harbor.labels" . | indent 4 }} + component: ui +spec: + replicas: 1 + template: + metadata: + labels: +{{ include "harbor.matchLabels" . | indent 8 }} + component: ui + spec: + containers: + - name: ui + image: {{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag }} + imagePullPolicy: {{ .Values.ui.image.pullPolicy }} + env: + - name: UI_SECRET + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-ui" + key: secret + - name: JOBSERVICE_SECRET + valueFrom: + secretKeyRef: + name: "{{ template "harbor.fullname" . }}-ui" + key: jobserviceSecret + - name: _REDIS_URL + value: {{ template "harbor.redisForUI" . }} + - name: GODEBUG + value: netdns=cgo + - name: LOG_LEVEL + value: debug + - name: CONFIG_PATH + value: /etc/ui/app.conf + - name: ENABLE_HARBOR_SCAN_ON_PUSH + value: "1" + - name: ADMINSERVER_URL + value: "http://{{ template "harbor.fullname" . }}-adminserver" + - name: CHART_CACHE_DRIVER + value: "redis" + ports: + - containerPort: 8080 + volumeMounts: + - name: ui-config + mountPath: /etc/ui/app.conf + subPath: app.conf + - name: ui-secrets-key + mountPath: /etc/ui/key + subPath: key + - name: ui-secrets-private-key + mountPath: /etc/ui/private_key.pem + subPath: tokenServicePrivateKey + {{- if eq .Values.externalProtocol "https" }} + {{- if .Values.ingress.enabled }} + {{- if eq .Values.ingress.tls.secretName "" }} + - name: ca-download + mountPath: /etc/ui/ca/ca.crt + subPath: ca.crt + {{- end }} + {{- end }} + {{- end }} + - name: psc + mountPath: /etc/ui/token + volumes: + - name: ui-config + configMap: + name: "{{ template "harbor.fullname" . }}-ui" + - name: ui-secrets-key + secret: + secretName: "{{ template "harbor.fullname" . }}-ui" + items: + - key: secretKey + path: key + - name: ui-secrets-private-key + secret: + secretName: "{{ template "harbor.fullname" . }}-ui" + {{- if eq .Values.externalProtocol "https" }} + {{- if .Values.ingress.enabled }} + {{- if eq .Values.ingress.tls.secretName "" }} + - name: ca-download + secret: + secretName: "{{ template "harbor.fullname" . }}-ingress" + items: + - key: ca.crt + path: ca.crt + {{- end }} + {{- end }} + {{- end }} + - name: psc + emptyDir: {} + {{- with .Values.ui.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.ui.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.ui.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} diff --git a/templates/ui/ui-secrets.yaml b/templates/ui/ui-secrets.yaml new file mode 100644 index 000000000..743354398 --- /dev/null +++ b/templates/ui/ui-secrets.yaml @@ -0,0 +1,15 @@ +{{- $cert := genSelfSignedCert "harbor" nil nil 365 }} +apiVersion: v1 +kind: Secret +metadata: + name: "{{ template "harbor.fullname" . }}-ui" + labels: +{{ include "harbor.labels" . | indent 4 }} +type: Opaque +data: + secretKey: {{ .Values.secretKey | b64enc | quote }} + secret: {{ .Values.ui.secret | b64enc | quote }} + jobserviceSecret: {{ .Values.jobservice.secret | b64enc | quote }} + tokenServiceRootCertBundle: {{ $cert.Cert | b64enc | quote }} + tokenServicePrivateKey: {{ $cert.Key | b64enc | quote }} + \ No newline at end of file diff --git a/templates/ui/ui-svc.yaml b/templates/ui/ui-svc.yaml new file mode 100644 index 000000000..e74ce16c0 --- /dev/null +++ b/templates/ui/ui-svc.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: "{{ template "harbor.fullname" . }}-ui" + labels: +{{ include "harbor.labels" . | indent 4 }} +spec: + ports: + - port: 80 + targetPort: 8080 + selector: +{{ include "harbor.matchLabels" . | indent 4 }} + component: ui diff --git a/values.yaml b/values.yaml new file mode 100644 index 000000000..9d20540fa --- /dev/null +++ b/values.yaml @@ -0,0 +1,296 @@ +persistence: + enabled: true +externalProtocol: https +# The FQDN for Harbor service +externalDomain: harbor.my.domain +# The Port for Harbor service, leave empty if the service +# is to be bound to port 80/443 +externalPort: 32700 +harborAdminPassword: Harbor12345 +authenticationMode: "db_auth" +selfRegistration: "on" +ldap: + url: "ldaps://ldapserver" + searchDN: "" + searchPassword: "" + baseDN: "" + filter: "(objectClass=person)" + uid: "uid" + scope: "2" + timeout: "5" + verifyCert: "True" +email: + host: "smtp.mydomain.com" + port: "25" + username: "sample_admin@mydomain.com" + password: "password" + ssl: "false" + insecure: "false" + from: "admin " + identity: "" + +# The secret key used for encryption. Must be a string of 16 chars. +secretKey: not-a-secure-key + +# These annotations allow the registry to work behind the nginx +# ingress controller. +ingress: + enabled: true + annotations: + ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" + ingress.kubernetes.io/proxy-body-size: "0" + nginx.ingress.kubernetes.io/proxy-body-size: "0" + tls: + # Fill the secretName if you want to use the certificate of + # yourself when Harbor serves with HTTPS. A certificate will + # be generated automatically by the chart if leave it empty + secretName: "" + +# The tag for Harbor docker images. +harborImageTag: &harbor_image_tag dev + +adminserver: + image: + repository: goharbor/harbor-adminserver + tag: *harbor_image_tag + pullPolicy: IfNotPresent + volumes: + config: + # storageClass: "-" + accessMode: ReadWriteOnce + size: 1Gi + # resources: + # requests: + # memory: 256Mi + # cpu: 100m + nodeSelector: {} + tolerations: [] + affinity: {} + +jobservice: + image: + repository: goharbor/harbor-jobservice + tag: *harbor_image_tag + pullPolicy: IfNotPresent + secret: not-a-secure-secret + maxWorkers: 50 +# resources: +# requests: +# memory: 256Mi +# cpu: 100m + nodeSelector: {} + tolerations: [] + affinity: {} + +ui: + image: + repository: goharbor/harbor-ui + tag: *harbor_image_tag + pullPolicy: IfNotPresent + secret: not-a-secure-secret +# resources: +# requests: +# memory: 256Mi +# cpu: 100m + nodeSelector: {} + tolerations: [] + affinity: {} + +# TODO: change the style to be same with redis +database: + # if external database is used, set "type" to "external" + # and fill the connection informations in "external" section + type: internal + internal: + image: + repository: goharbor/harbor-db + tag: *harbor_image_tag + pullPolicy: IfNotPresent + # the superuser password of database + password: "changeit" + volumes: + data: + # storageClass: "-" + accessMode: ReadWriteOnce + size: 1Gi + # resources: + # requests: + # memory: 256Mi + # cpu: 100m + nodeSelector: {} + tolerations: [] + affinity: {} + external: + host: "192.168.0.1" + port: "5432" + username: "user" + password: "password" + coreDatabase: "registry" + clairDatabase: "clair" + notaryServerDatabase: "notary_server" + notarySignerDatabase: "notary_signer" + +registry: + image: + repository: goharbor/registry-photon + tag: dev + pullPolicy: IfNotPresent + httpSecret: not-a-secure-secret + logLevel: info + storage: + # specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift", + # "oss" and fill the information needed in the corresponding section + type: filesystem + filesystem: + rootdirectory: /var/lib/registry + #maxthreads: 100 + azure: + accountname: accountname + accountkey: base64encodedaccountkey + container: containername + #realm: core.windows.net + gcs: + bucket: bucketname + # TODO: support the keyfile of gcs + #keyfile: /path/to/keyfile + #rootdirectory: /gcs/object/name/prefix + #chunksize: 5242880 + s3: + region: us-west-1 + bucket: bucketname + #accesskey: awsaccesskey + #secretkey: awssecretkey + #regionendpoint: http://myobjects.local + #encrypt: false + #keyid: mykeyid + #secure: true + #v4auth: true + #chunksize: 5242880 + #rootdirectory: /s3/object/name/prefix + #storageclass: STANDARD + swift: + authurl: https://storage.myprovider.com/v3/auth + username: username + password: password + container: containername + #region: fr + #tenant: tenantname + #tenantid: tenantid + #domain: domainname + #domainid: domainid + #trustid: trustid + #insecureskipverify: false + #chunksize: 5M + #prefix: + #secretkey: secretkey + #accesskey: accesskey + #authversion: 3 + #endpointtype: public + #tempurlcontainerkey: false + #tempurlmethods: + oss: + accesskeyid: accesskeyid + accesskeysecret: accesskeysecret + region: regionname + bucket: bucketname + #endpoint: endpoint + #internal: false + #encrypt: false + #secure: true + #chunksize: 10M + #rootdirectory: rootdirectory + ## Persist data to a persistent volume + volumes: + data: + # storageClass: "-" + accessMode: ReadWriteOnce + size: 5Gi + # resources: + # requests: + # memory: 256Mi + # cpu: 100m + nodeSelector: {} + tolerations: [] + affinity: {} + +chartmuseum: + enabled: true + image: + repository: goharbor/chartmuseum-photon + tag: dev + pullPolicy: IfNotPresent + volumes: + data: + # storageClass: "-" + accessMode: ReadWriteOnce + size: 5Gi + # resources: + # requests: + # memory: 256Mi + # cpu: 100m + nodeSelector: {} + tolerations: [] + affinity: {} + +clair: + enabled: true + image: + repository: goharbor/clair-photon + tag: dev + pullPolicy: IfNotPresent + volumes: + pgData: + # storageClass: "-" + accessMode: ReadWriteOnce + size: 1Gi + # resources: + # requests: + # memory: 256Mi + # cpu: 100m + nodeSelector: {} + tolerations: [] + affinity: {} + +redis: + # if external Redis is used, set "external.enabled" to "true" + # and fill the connection informations in "external" section. + # or the internal Redis will be used + usePassword: false + password: "changeit" + cluster: + enabled: false + master: + persistence: +# TODO: There is a perm issue: Can't open the append-only file: Permission denied +# TODO: Setting it to false is a temp workaround. Will re-visit this problem. + enabled: false + external: + enabled: false + host: "192.168.0.2" + port: "6379" + databaseIndex: "0" + usePassword: false + password: "changeit" + +notary: + enabled: true + server: + image: + repository: goharbor/notary-server-photon + tag: dev + pullPolicy: IfNotPresent + signer: + image: + repository: goharbor/notary-signer-photon + tag: dev + pullPolicy: IfNotPresent + env: + NOTARY_SIGNER_DEFAULTALIAS: defaultalias + # The TLS certificate for Notary Signer. Will auto generate them if unspecified here. + caCrt: + tlsCrt: + tlsKey: + nodeSelector: {} + tolerations: [] + affinity: {}