apiVersion: apps/v1beta2 kind: StatefulSet metadata: name: {{ template "artifactory-ha.primary.name" . }} labels: app: {{ template "artifactory-ha.name" . }} chart: {{ template "artifactory-ha.chart" . }} component: {{ .Values.artifactory.name }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} spec: serviceName: {{ template "artifactory-ha.primary.name" . }} replicas: 1 updateStrategy: type: RollingUpdate selector: matchLabels: app: {{ template "artifactory-ha.name" . }} role: {{ template "artifactory-ha.primary.name" . }} release: {{ .Release.Name }} template: metadata: labels: app: {{ template "artifactory-ha.name" . }} role: {{ template "artifactory-ha.primary.name" . }} component: {{ .Values.artifactory.name }} release: {{ .Release.Name }} annotations: checksum/binarystore: {{ include (print $.Template.BasePath "/artifactory-binarystore.yaml") . | sha256sum }} {{- range $key, $value := .Values.artifactory.annotations }} {{ $key }}: {{ $value | quote }} {{- end }} spec: serviceAccountName: {{ template "artifactory-ha.serviceAccountName" . }} {{- if .Values.imagePullSecrets }} imagePullSecrets: - name: {{ .Values.imagePullSecrets }} {{- end }} securityContext: runAsUser: {{ .Values.artifactory.uid }} fsGroup: {{ .Values.artifactory.uid }} initContainers: {{- if .Values.artifactory.persistence.enabled }} - name: "remove-lost-found" image: "{{ .Values.initContainerImage }}" imagePullPolicy: {{ .Values.artifactory.image.pullPolicy }} command: - 'sh' - '-c' - 'rm -rfv {{ .Values.artifactory.persistence.mountPath }}/lost+found' volumeMounts: - mountPath: {{ .Values.artifactory.persistence.mountPath | quote }} name: volume {{- end }} - name: "wait-for-db" image: "{{ .Values.initContainerImage }}" command: - 'sh' - '-c' - > {{- if .Values.postgresql.enabled }} until nc -z -w 2 {{ .Release.Name }}-postgresql {{ .Values.postgresql.service.port }} && echo database ok; do {{- else }} {{- if and .Values.database.host .Values.database.port }} until nc -z -w 2 {{ .Values.database.host }} {{ .Values.database.port }} && echo database ok; do {{- else }} until true; do {{- end }} {{- end }} sleep 2; done; containers: - name: {{ .Values.artifactory.name }} image: '{{ .Values.artifactory.image.repository }}:{{ default .Chart.AppVersion .Values.artifactory.image.version }}' imagePullPolicy: {{ .Values.artifactory.image.pullPolicy }} securityContext: allowPrivilegeEscalation: false {{- if .Values.artifactory.preStartCommand }} command: - '/bin/sh' - '-c' - > echo "Running custom preStartCommand command"; {{ .Values.artifactory.preStartCommand }}; /entrypoint-artifactory.sh {{- end }} lifecycle: postStart: exec: command: - '/bin/sh' - '-c' - > {{- if .Values.artifactory.configMapName }} cp -Lrf /bootstrap/* /artifactory_extra_conf/; {{- end }} {{- if .Values.artifactory.replicator.enabled }} mkdir -p {{ .Values.artifactory.persistence.mountPath }}/replicator/etc; cp -fv /tmp/replicator/replicator.yaml {{ .Values.artifactory.persistence.mountPath }}/replicator/etc/replicator.yaml; {{- end }} {{- if .Values.artifactory.distributionCerts }} mkdir -p {{ .Values.artifactory.persistence.mountPath }}/access/etc/keys/trusted; cp -fv /tmp/access/etc/keys/private.key {{ .Values.artifactory.persistence.mountPath }}/access/etc/keys; cp -fv /tmp/access/etc/keys/root.crt {{ .Values.artifactory.persistence.mountPath }}/access/etc/keys; cp -fv /tmp/access/etc/keys/root.crt {{ .Values.artifactory.persistence.mountPath }}/access/etc/keys/trusted; {{- end }} {{- if .Values.artifactory.postStartCommand }} {{ .Values.artifactory.postStartCommand }} {{- end }} env: {{- if .Values.postgresql.enabled }} - name: DB_TYPE value: 'postgresql' - name: DB_HOST value: '{{ .Release.Name }}-postgresql' - name: DB_PORT value: '{{ .Values.postgresql.service.port }}' - name: DB_USER value: '{{ .Values.postgresql.postgresUser }}' - name: DB_PASSWORD valueFrom: secretKeyRef: name: {{ .Release.Name }}-postgresql key: postgres-password {{- else }} - name: DB_TYPE value: '{{ required "Must set database.type when not using the PostgreSQL sub-chart (postgresql.enabled=false) " .Values.database.type }}' {{- if or .Values.database.url .Values.database.secrets.url }} - name: DB_URL {{- if .Values.database.url }} value: '{{.Values.database.url }}' {{- else }} valueFrom: secretKeyRef: name: {{ .Values.database.secrets.url.name }} key: {{ .Values.database.secrets.url.key }} {{- end }} {{- else }} - name: DB_HOST value: '{{ .Values.database.host }}' - name: DB_PORT value: '{{ .Values.database.port }}' {{- end }} {{- if .Values.database.secrets.user }} - name: DB_USER valueFrom: secretKeyRef: name: {{ .Values.database.secrets.user.name }} key: {{ .Values.database.secrets.user.key }} {{- end }} {{- if .Values.database.secrets.password }} - name: DB_PASSWORD valueFrom: secretKeyRef: name: {{ .Values.database.secrets.password.name }} key: {{ .Values.database.secrets.password.key }} {{- else }} {{- if and .Values.database.type .Values.database.user }} - name: DB_USER value: '{{ .Values.database.user }}' - name: DB_PASSWORD valueFrom: secretKeyRef: name: {{ template "artifactory-ha.fullname" . }} key: db-password {{- end }} {{- end }} {{- end }} - name: EXTRA_JAVA_OPTIONS value: " {{- if .Values.artifactory.javaOpts.other }} {{ .Values.artifactory.javaOpts.other }} {{- end}} {{- if .Values.artifactory.primary.javaOpts.other }} {{ .Values.artifactory.primary.javaOpts.other }} {{- end}} {{- if .Values.artifactory.primary.javaOpts.xms }} -Xms{{ .Values.artifactory.primary.javaOpts.xms }} {{- end}} {{- if .Values.artifactory.primary.javaOpts.xmx }} -Xmx{{ .Values.artifactory.primary.javaOpts.xmx }} {{- end}} {{- if .Values.artifactory.replicator.enabled }} -Dartifactory.releasebundle.feature.enabled=true {{- end }} " {{- if .Values.artifactory.replicator.enabled }} - name: START_LOCAL_REPLICATOR value: "true" {{- end }} - name: ARTIFACTORY_MASTER_KEY valueFrom: secretKeyRef: name: "{{ .Values.artifactory.masterKeySecretName | default (include "artifactory-ha.fullname" .) }}" key: master-key - name: HA_IS_PRIMARY value: "true" - name: HA_MEMBERSHIP_PORT value: "{{ .Values.artifactory.membershipPort }}" - name: HA_NODE_ID valueFrom: fieldRef: fieldPath: metadata.name {{- if eq .Values.artifactory.persistence.type "nfs" }} - name: HA_DATA_DIR value: "{{ .Values.artifactory.persistence.nfs.dataDir }}" - name: HA_BACKUP_DIR value: "{{ .Values.artifactory.persistence.nfs.backupDir }}" {{- end }} ports: - containerPort: {{ .Values.artifactory.internalPort }} {{- if .Values.artifactory.replicator.enabled }} - containerPort: {{ .Values.artifactory.internalPortReplicator }} {{- end }} volumeMounts: - name: volume mountPath: "{{ .Values.artifactory.persistence.mountPath }}" - name: artifactory-inactiveservercleaner mountPath: "/tmp/plugins/inactiveServerCleaner.groovy" subPath: inactiveServerCleaner.groovy {{- if eq .Values.artifactory.persistence.type "nfs" }} - name: artifactory-ha-data mountPath: "{{ .Values.artifactory.persistence.nfs.dataDir }}" - name: artifactory-ha-backup mountPath: "{{ .Values.artifactory.persistence.nfs.backupDir }}" {{- else }} - name: binarystore-xml mountPath: "/artifactory_extra_conf/binarystore.xml" subPath: binarystore.xml {{- end }} {{- if .Values.artifactory.configMapName }} - name: bootstrap-config mountPath: "/bootstrap/" {{- end }} {{- if .Values.artifactory.license.secret }} - name: artifactory-license mountPath: "/artifactory_extra_conf/artifactory.cluster.license" subPath: {{ .Values.artifactory.license.dataKey }} {{- end }} {{- if .Values.artifactory.distributionCerts }} - name: distribution-certs mountPath: "/tmp/access/etc/keys" {{- end }} {{- if .Values.artifactory.replicator.enabled }} - name: replicator-config mountPath: "/tmp/replicator/replicator.yaml" {{- end }} resources: {{ toYaml .Values.artifactory.primary.resources | indent 10 }} {{- if .Values.artifactory.readinessProbe.enabled }} readinessProbe: httpGet: path: '/artifactory/webapp/#/login' port: 8040 initialDelaySeconds: {{ .Values.artifactory.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.artifactory.readinessProbe.periodSeconds }} timeoutSeconds: {{ .Values.artifactory.readinessProbe.timeoutSeconds }} failureThreshold: {{ .Values.artifactory.readinessProbe.failureThreshold }} successThreshold: {{ .Values.artifactory.readinessProbe.successThreshold }} {{- end }} {{- if .Values.artifactory.livenessProbe.enabled }} livenessProbe: httpGet: path: '/artifactory/webapp/#/login' port: 8040 initialDelaySeconds: {{ .Values.artifactory.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.artifactory.livenessProbe.periodSeconds }} timeoutSeconds: {{ .Values.artifactory.livenessProbe.timeoutSeconds }} failureThreshold: {{ .Values.artifactory.livenessProbe.failureThreshold }} successThreshold: {{ .Values.artifactory.livenessProbe.successThreshold }} {{- end }} {{- with .Values.artifactory.primary.nodeSelector }} nodeSelector: {{ toYaml . | indent 8 }} {{- end }} {{- if .Values.artifactory.primary.affinity }} {{- with .Values.artifactory.primary.affinity }} affinity: {{ toYaml . | indent 8 }} {{- end }} {{- else if eq .Values.artifactory.primary.podAntiAffinity.type "soft" }} affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: topologyKey: {{ .Values.artifactory.primary.podAntiAffinity.topologyKey }} labelSelector: matchLabels: app: {{ template "artifactory-ha.name" . }} release: {{ .Release.Name }} {{- else if eq .Values.artifactory.primary.podAntiAffinity.type "hard" }} affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: {{ .Values.artifactory.primary.podAntiAffinity.topologyKey }} labelSelector: matchLabels: app: {{ template "artifactory-ha.name" . }} release: {{ .Release.Name }} {{- end }} {{- with .Values.artifactory.primary.tolerations }} tolerations: {{ toYaml . | indent 8 }} {{- end }} volumes: - name: binarystore-xml configMap: name: {{ template "artifactory-ha.fullname" . }}-bs {{- if .Values.artifactory.distributionCerts }} - name: distribution-certs configMap: name: {{ .Values.artifactory.distributionCerts }} {{- end }} {{- if .Values.artifactory.replicator.enabled }} - name: replicator-config configMap: name: {{ template "artifactory-ha.fullname" . }}-replicator-config {{- end }} {{- if .Values.artifactory.configMapName }} - name: bootstrap-config configMap: name: {{ .Values.artifactory.configMapName }} {{- end}} - name: artifactory-inactiveservercleaner configMap: name: {{ template "artifactory-ha.fullname" . }}-isc {{- if .Values.artifactory.license.secret }} - name: artifactory-license secret: secretName: {{ .Values.artifactory.license.secret }} {{- end }} {{- if eq .Values.artifactory.persistence.type "nfs" }} - name: artifactory-ha-data persistentVolumeClaim: claimName: {{ template "artifactory-ha.fullname" . }}-data-pvc - name: artifactory-ha-backup persistentVolumeClaim: claimName: {{ template "artifactory-ha.fullname" . }}-backup-pvc {{- end }} {{- if .Values.artifactory.persistence.local }} - name: volume emptyDir: sizeLimit: {{ .Values.artifactory.persistence.size }} {{- else }} volumeClaimTemplates: - metadata: name: volume spec: {{- if .Values.artifactory.primary.persistence.existingClaim }} selector: matchLabels: app: artifactory-ha-primary {{- else }} {{- if .Values.artifactory.persistence.storageClass }} {{- if (eq "-" .Values.artifactory.persistence.storageClass) }} storageClassName: "" {{- else }} storageClassName: "{{ .Values.artifactory.persistence.storageClass }}" {{- end }} {{- end }} accessModes: [ "{{ .Values.artifactory.persistence.accessMode }}" ] resources: requests: storage: {{ .Values.artifactory.persistence.size }} {{- end }} {{- end }}