# _helpers.tpl
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "artifactory-ha.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
The primary node name
*/}}
{{- define "artifactory-ha.primary.name" -}}
{{- $name := .Release.Name | trunc 15 -}}
{{- printf "%s-%s-primary" $name .Chart.Name | trunc 63 | trimSuffix "-" -}}

{{- end -}}

{{/*
The member node name
*/}}
{{- define "artifactory-ha.node.name" -}}
{{- $name := .Release.Name | trunc 15 -}}
{{- printf "%s-%s-member" $name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Expand the name nginx service.
*/}}
{{- define "artifactory-ha.nginx.name" -}}
{{- default .Values.nginx.name .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).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "artifactory-ha.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- 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).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "artifactory-ha.nginx.fullname" -}}
{{- if .Values.nginx.fullnameOverride -}}
{{- .Values.nginx.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nginx.name -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create the name of the service account to use
*/}}
{{- define "artifactory-ha.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{ default (include "artifactory-ha.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
{{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "artifactory-ha.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}} # artifactory-binarystore.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-bs
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
data:
  binarystore.xml: |-
{{- if eq .Values.artifactory.persistence.type "file-system" }}
    <!-- File system replication -->
    <config version="2">
        <chain>
            <provider id="cache-fs" type="cache-fs">
                <provider id="sharding-cluster" type="sharding-cluster">
                    <readBehavior>crossNetworkStrategy</readBehavior>
                    <writeBehavior>crossNetworkStrategy</writeBehavior>
                    <redundancy>{{ .Values.artifactory.persistence.redundancy }}</redundancy>
                    <lenientLimit>2</lenientLimit>
                    <minSpareUploaderExecutor>2</minSpareUploaderExecutor>
                    <sub-provider id="state-aware" type="state-aware"/>
                    <dynamic-provider id="remote" type="remote"/>
                    <property name="zones" value="local,remote"/>
                </provider>
            </provider>
        </chain>

        <!-- Shards add local file-system provider configuration -->
        <provider id="state-aware" type="state-aware">
            <fileStoreDir>shard-fs-1</fileStoreDir>
            <zone>local</zone>
        </provider>

        <!-- Shards dynamic remote provider configuration -->
        <provider id="remote" type="remote">
            <checkPeriod>30</checkPeriod>
            <serviceId>tester-remote1</serviceId>
            <timeout>10000</timeout>
            <zone>remote</zone>
            <property name="header.remote.block" value="true"/>
        </provider>
    </config>
{{- end }}

{{- if eq .Values.artifactory.persistence.type "google-storage" }}
    <!-- Google storage -->
    <config version="2">
        <chain>
            <provider id="sharding-cluster" type="sharding-cluster">
                <readBehavior>crossNetworkStrategy</readBehavior>
                <writeBehavior>crossNetworkStrategy</writeBehavior>
                <redundancy>{{ .Values.artifactory.persistence.redundancy }}</redundancy>
                <minSpareUploaderExecutor>2</minSpareUploaderExecutor>
                <sub-provider id="eventual-cluster" type="eventual-cluster">
                    <provider id="retry" type="retry">
                        <provider id="google-storage" type="google-storage"/>
                    </provider>
                </sub-provider>
                <dynamic-provider id="remote" type="remote"/>
                <property name="zones" value="local,remote"/>
            </provider>
        </chain>

        <!-- Set max cache-fs size -->
        <provider id="cache-fs" type="cache-fs">
            <maxCacheSize>50000000000</maxCacheSize>
        </provider>

        <provider id="eventual-cluster" type="eventual-cluster">
            <zone>local</zone>
        </provider>

        <provider id="remote" type="remote">
            <checkPeriod>30</checkPeriod>
            <timeout>10000</timeout>
            <zone>remote</zone>
        </provider>

        <provider id="file-system" type="file-system">
            <fileStoreDir>{{ .Values.artifactory.persistence.mountPath }}/data/filestore</fileStoreDir>
            <tempDir>/tmp</tempDir>
        </provider>

        <provider id="google-storage" type="google-storage">
            <providerId>google-cloud-storage</providerId>
            <endpoint>commondatastorage.googleapis.com</endpoint>
            <httpsOnly>false</httpsOnly>
            <bucketName>{{ .Values.artifactory.persistence.googleStorage.bucketName }}</bucketName>
            <identity>{{ .Values.artifactory.persistence.googleStorage.identity }}</identity>
            <credential>{{ .Values.artifactory.persistence.googleStorage.credential }}</credential>
            <path>{{ .Values.artifactory.persistence.googleStorage.path }}</path>
        </provider>
    </config>
{{- end }}

{{- if eq .Values.artifactory.persistence.type "aws-s3" }}
    <!-- AWS S3 -->
    <config version="2">
        <chain>
            <provider id="sharding-cluster" type="sharding-cluster">
                <readBehavior>crossNetworkStrategy</readBehavior>
                <writeBehavior>crossNetworkStrategy</writeBehavior>
                <redundancy>{{ .Values.artifactory.persistence.redundancy }}</redundancy>
                <minSpareUploaderExecutor>2</minSpareUploaderExecutor>
                <sub-provider id="eventual-cluster" type="eventual-cluster">
                    <provider id="retry" type="retry">
                        <provider id="s3" type="s3"/>
                    </provider>
                </sub-provider>
                <dynamic-provider id="remote" type="remote"/>
                <property name="zones" value="local,remote"/>
            </provider>
        </chain>

        <!-- Set max cache-fs size -->
        <provider id="cache-fs" type="cache-fs">
            <maxCacheSize>50000000000</maxCacheSize>
        </provider>

        <provider id="eventual-cluster" type="eventual-cluster">
            <zone>local</zone>
        </provider>

        <provider id="remote" type="remote">
            <checkPeriod>30</checkPeriod>
            <timeout>10000</timeout>
            <zone>remote</zone>
        </provider>

        <provider id="file-system" type="file-system">
            <fileStoreDir>{{ .Values.artifactory.persistence.mountPath }}/data/filestore</fileStoreDir>
            <tempDir>/tmp</tempDir>
        </provider>

        <provider id="s3" type="s3">
            <endpoint>http://s3.amazonaws.com</endpoint>
            <refreshCredentials>true</refreshCredentials>
            <testConnection>false</testConnection>
            <httpsOnly>false</httpsOnly>
            <region>{{ .Values.artifactory.persistence.awsS3.region }}</region>
            <bucketName>{{ .Values.artifactory.persistence.awsS3.bucketName }}</bucketName>
            <identity>{{ .Values.artifactory.persistence.awsS3.identity }}</identity>
            <credential>{{ .Values.artifactory.persistence.awsS3.credential }}</credential>
            <path>{{ .Values.artifactory.persistence.awsS3.path }}</path>
        </provider>
    </config>
{{- end }}
 # artifactory-nfs-pvc.yaml
{{- if eq .Values.artifactory.persistence.type "nfs" }}
### Artifactory HA data
apiVersion: v1
kind: PersistentVolume
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-data-pv
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
    id: {{ template "artifactory-ha.name" . }}-data-pv
    type: nfs-volume
spec:
  capacity:
    storage: {{ .Values.artifactory.persistence.nfs.capacity }}
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: {{ .Values.artifactory.persistence.nfs.ip }}
    path: "{{ .Values.artifactory.persistence.nfs.haDataMount }}"
    readOnly: false
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-data-pvc
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
    type: nfs-volume
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: ""
  resources:
    requests:
      storage: {{ .Values.artifactory.persistence.nfs.capacity }}
  selector:
    matchLabels:
      id: {{ template "artifactory-ha.name" . }}-data-pv
      app: {{ template "artifactory-ha.name" . }}
      release: {{ .Release.Name }}
---
### Artifactory HA backup
apiVersion: v1
kind: PersistentVolume
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-backup-pv
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
    id: {{ template "artifactory-ha.name" . }}-backup-pv
    type: nfs-volume
spec:
  capacity:
    storage: {{ .Values.artifactory.persistence.nfs.capacity }}
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: {{ .Values.artifactory.persistence.nfs.ip }}
    path: "{{ .Values.artifactory.persistence.nfs.haBackupMount }}"
    readOnly: false
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-backup-pvc
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
    type: nfs-volume
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: ""
  resources:
    requests:
      storage: {{ .Values.artifactory.persistence.nfs.capacity }}
  selector:
    matchLabels:
      id: {{ template "artifactory-ha.name" . }}-backup-pv
      app: {{ template "artifactory-ha.name" . }}
      release: {{ .Release.Name }}
{{- end }} # artifactory-node-statefulset.yaml
apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
  name: {{ template "artifactory-ha.node.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.node.name" . }}
  replicas: {{ .Values.artifactory.node.replicaCount }}
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: {{ template "artifactory-ha.name" . }}
      role: {{ template "artifactory-ha.node.name" . }}
      release: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ template "artifactory-ha.name" . }}
        role: {{ template "artifactory-ha.node.name" . }}
        component: {{ .Values.artifactory.name }}
        release: {{ .Release.Name }}
    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 }}
          until nc -z -w 2 {{ .Values.database.host }} {{ .Values.database.port }} && echo database ok; do
      {{- 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
        lifecycle:
          postStart:
            exec:
              command:
              - '/bin/sh'
              - '-c'
              - >
                {{- 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: '{{ .Values.database.type }}'
        - name: DB_HOST
          value: '{{ .Values.database.host }}'
        - name: DB_PORT
          value: '{{ .Values.database.port }}'
        - name: DB_USER
          value: '{{ .Values.database.user }}'
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "artifactory-ha.fullname" . }}
              key: db-password
      {{- end }}
        - name: EXTRA_JAVA_OPTIONS
          value: "
      {{- if .Values.artifactory.javaOpts.other }}
          {{ .Values.artifactory.javaOpts.other }}
      {{- end}}
      {{- if .Values.artifactory.node.javaOpts.other }}
          {{ .Values.artifactory.node.javaOpts.other }}
      {{- end}}
      {{- if .Values.artifactory.node.javaOpts.xms }}
          -Xms{{ .Values.artifactory.node.javaOpts.xms }}
      {{- end}}
      {{- if .Values.artifactory.node.javaOpts.xmx }}
          -Xmx{{ .Values.artifactory.node.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: {{ template "artifactory-ha.fullname" . }}
              key: master-key
        - name: HA_IS_PRIMARY
          value: "false"
        - name: HA_MEMBERSHIP_PORT
          value: "{{ .Values.artifactory.membershipPort }}"
        - name: HA_NODE_ID
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: ART_PRIMARY_BASE_URL
          value: 'http://{{ template "artifactory-ha.primary.name" . }}:8081/artifactory'
      {{- 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 }}
        volumeMounts:
        - name: volume
          mountPath: "{{ .Values.artifactory.persistence.mountPath }}"
      {{- 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.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.node.resources | indent 10 }}
        {{- if .Values.artifactory.readinessProbe.enabled }}
        readinessProbe:
          httpGet:
            path: '/artifactory/webapp/#/login'
            port: 8081
          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: 8081
          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.node.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.artifactory.node.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.artifactory.node.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 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: {}
      {{- else }}
  volumeClaimTemplates:
  - metadata:
      name: volume
    spec:
    {{- if .Values.artifactory.node.persistence.existingClaim }}
      selector:
        matchLabels:
          app: artifactory-ha-member
    {{- 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 }}
 # artifactory-plugin-inactiveservercleaner.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-isc
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
data:
  inactiveServerCleaner.groovy: |-
    import org.artifactory.state.ArtifactoryServerState
    import org.artifactory.storage.db.servers.service.ArtifactoryServersCommonService
    import org.artifactory.common.ConstantValues
    import org.slf4j.Logger

    import java.util.concurrent.TimeUnit

    jobs {
        clean(interval: 90000, delay: 900000) {
            runCleanupHAInactiveServers()
        }
    }

    executions {
        cleanHAInactiveServers() { params ->
            runCleanupHAInactiveServers()
        }
    }

    def runCleanupHAInactiveServers() {
        def artifactoryServersCommonService = ctx.beanForType(ArtifactoryServersCommonService)
        def artifactoryInactiveServerCleaner = new ArtifactoryInactiveServersCleaner(artifactoryServersCommonService, log)
        artifactoryInactiveServerCleaner.cleanInactiveArtifactoryServers()
    }

    public class ArtifactoryInactiveServersCleaner {

        private ArtifactoryServersCommonService artifactoryServersCommonService
        private Logger log

        ArtifactoryInactiveServersCleaner(ArtifactoryServersCommonService artifactoryServersCommonService, Logger log) {
            this.artifactoryServersCommonService = artifactoryServersCommonService
            this.log = log
        }

        def cleanInactiveArtifactoryServers() {
            log.info "Executing inactive artifactory servers cleaner plugin"
            List<String> allMembers = artifactoryServersCommonService.getAllArtifactoryServers()
            for (member in allMembers) {
                def heartbeat = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - member.getLastHeartbeat())
                def noHeartbeat = heartbeat > ConstantValues.haHeartbeatStaleIntervalSecs.getInt()
                if (member.getServerState() == ArtifactoryServerState.UNAVAILABLE || ( noHeartbeat && member.getServerState() != ArtifactoryServerState.CONVERTING && member.getServerState() != ArtifactoryServerState.STARTING )) {
                    try {
                        log.info "Inactive artifactory servers cleaning task found server ${member.serverId} to remove"
                        artifactoryServersCommonService.removeServer(member.serverId)

                    }catch (Exception e){
                        log.error "Error: Not able to remove ${member.serverId}, ${e.message}"
                    }
                }
            }
            log.info "No inactive servers found"
        }
    } # artifactory-primary-statefulset.yaml
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 }}
    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 }}
          until nc -z -w 2 {{ .Values.database.host }} {{ .Values.database.port }} && echo database ok; do
      {{- 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
        lifecycle:
          postStart:
            exec:
              command:
              - '/bin/sh'
              - '-c'
              - >
                {{- if .Values.artifactory.configMapName }}
                cp -Lrfv /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: '{{ .Values.database.type }}'
        - name: DB_HOST
          value: '{{ .Values.database.host }}'
        - name: DB_PORT
          value: '{{ .Values.database.port }}'
        - name: DB_USER
          value: '{{ .Values.database.user }}'
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ template "artifactory-ha.fullname" . }}
              key: db-password
      {{- 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: {{ template "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: 8081
          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: 8081
          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 }}
    {{- with .Values.artifactory.primary.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
    {{- 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: {}
      {{- 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 }}
 # artifactory-role.yaml
{{- if .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    component: {{ .Values.artifactory.name }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
  name: {{ template "artifactory-ha.fullname" . }}
rules:
{{ toYaml .Values.rbac.role.rules }}
{{- end }}
 # artifactory-rolebinding.yaml
{{- if .Values.rbac.create }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    component: {{ .Values.artifactory.name }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
  name: {{ template "artifactory-ha.fullname" . }}
subjects:
- kind: ServiceAccount
  name: {{ template "artifactory-ha.serviceAccountName" . }}
roleRef:
  kind: Role
  apiGroup: rbac.authorization.k8s.io
  name: {{ template "artifactory-ha.fullname" . }}
{{- end }}
 # artifactory-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: {{ template "artifactory-ha.fullname" . }}
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
type: Opaque
data:
  master-key: {{ .Values.artifactory.masterKey | b64enc | quote }}
{{- if .Values.database.password }}
  db-password: {{ .Values.database.password | b64enc | quote }}
{{- end }}
 # artifactory-service.yaml
# Service for all Artifactory cluster nodes.
apiVersion: v1
kind: Service
metadata:
  name: {{ template "artifactory-ha.fullname" . }}
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    component: {{ .Values.artifactory.name }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
spec:
  type: {{ .Values.artifactory.service.type }}
  ports:
  - port: {{ .Values.artifactory.externalPort }}
    targetPort: {{ .Values.artifactory.internalPort }}
    protocol: TCP
    name: http
  selector:
{{- if eq .Values.artifactory.service.pool "members" }}
    role: {{ template "artifactory-ha.node.name" . }}
{{- end }}
    app: {{ template "artifactory-ha.name" . }}
    component: "{{ .Values.artifactory.name }}"
    release: {{ .Release.Name }}
---
# Internal service for Artifactory primary node only!
# Used by member nodes to check readiness of primary node before starting up
apiVersion: v1
kind: Service
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:
  type: {{ .Values.artifactory.service.type }}
  ports:
  - port: {{ .Values.artifactory.externalPort }}
    targetPort: {{ .Values.artifactory.internalPort }}
    protocol: TCP
    name: http
  {{- if .Values.artifactory.replicator.enabled }}
  - port: {{ .Values.artifactory.externalPortReplicator }}
    targetPort: {{ .Values.artifactory.internalPortReplicator }}
    protocol: TCP
    name: replicator
  {{- end}}
  selector:
    role: {{ template "artifactory-ha.primary.name" . }}
    app: {{ template "artifactory-ha.name" . }}
    component: "{{ .Values.artifactory.name }}"
    release: {{ .Release.Name }}
 # artifactory-serviceaccount.yaml
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    component: {{ .Values.artifactory.name }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
  name: {{ template "artifactory-ha.serviceAccountName" . }}
{{- end }}
 # ingress.yaml
{{- if .Values.ingress.enabled -}}
{{- $serviceName := include "artifactory-ha.fullname" . -}}
{{- $servicePort := .Values.artifactory.externalPort -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ template "artifactory-ha.fullname" . }}
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
  annotations:
    {{- range $key, $value := .Values.ingress.annotations }}
      {{ $key }}: {{ $value | quote }}
    {{- end }}
spec:
  backend:
    serviceName: {{ $serviceName }}
    servicePort: {{ $servicePort }}
{{- if .Values.ingress.hosts }}
  rules:
  {{- range $host := .Values.ingress.hosts }}
  - host: {{ $host }}
    http:
      paths:
        - path: /
          backend:
            serviceName: {{ $serviceName }}
            servicePort: {{ $servicePort }}
  {{- end -}}
{{- end -}}
  {{- if .Values.ingress.tls }}
  tls:
{{ toYaml .Values.ingress.tls | indent 4 }}
  {{- end -}}
{{- end -}}
 # nginx-deployment.yaml
{{- if .Values.nginx.enabled -}}
{{- $serviceName := include "artifactory-ha.fullname" . -}}
{{- $servicePort := .Values.artifactory.externalPort -}}
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: {{ template "artifactory-ha.nginx.fullname" . }}
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
    component: {{ .Values.nginx.name }}
spec:
  replicas: {{ .Values.nginx.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "artifactory-ha.name" . }}
      release: {{ .Release.Name }}
      component: {{ .Values.nginx.name }}
  template:
    metadata:
      labels:
        app: {{ template "artifactory-ha.name" . }}
        component: {{ .Values.nginx.name }}
        release: {{ .Release.Name }}
    spec:
      serviceAccountName: {{ template "artifactory-ha.serviceAccountName" . }}
    {{- if .Values.imagePullSecrets }}
      imagePullSecrets:
      - name: {{ .Values.imagePullSecrets }}
    {{- end }}
      initContainers:
    {{- if .Values.nginx.persistence.enabled }}
      - name: "remove-lost-found"
        image: "{{ .Values.initContainerImage }}"
        imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
        command:
        - '/bin/sh'
        - '-c'
        - 'rm -rfv {{ .Values.nginx.persistence.mountPath }}/lost+found'
        volumeMounts:
        - mountPath: {{ .Values.nginx.persistence.mountPath | quote }}
          name: nginx-volume
    {{- end }}
      - name: "wait-for-artifactory"
        image: "{{ .Values.initContainerImage }}"
        command:
        - 'sh'
        - '-c'
        - >
          until nc -z -w 2 {{ $serviceName }} {{ $servicePort }} && echo artifactory ok; do
            sleep 2;
          done;
      containers:
      - name: {{ .Values.nginx.name }}
        image: '{{ .Values.nginx.image.repository }}:{{ default .Chart.AppVersion .Values.nginx.image.version }}'
        imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
        lifecycle:
          postStart:
            exec:
              command:
              - '/bin/sh'
              - '-c'
              - >
                {{- if .Values.nginx.customConfigMap }}
                cp -Lrf /tmp/nginx.conf /etc/nginx/nginx.conf;
                {{- end }}
                if [ -f /tmp/replicator-nginx.conf ]; then
                cp -fv /tmp/replicator-nginx.conf /etc/nginx/conf.d/replicator-nginx.conf;
                fi;
                if [ -f /tmp/ssl/*.crt ]; then
                rm -rf /var/opt/jfrog/nginx/ssl/example.*;
                cp -fv /tmp/ssl/* /var/opt/jfrog/nginx/ssl;
                fi;
                until [ -f /etc/nginx/conf.d/artifactory.conf ]; do sleep 1; done;
                if ! grep -q 'upstream' /etc/nginx/conf.d/artifactory.conf; then
                sed -i -e 's,proxy_pass .*,proxy_pass     http://{{ $serviceName }}:{{ $servicePort }}/artifactory/;,g' \
                    -e 's,server_name .*,server_name ~(?<repo>.+)\\.{{ $serviceName }} {{ $serviceName }};,g' \
                    /etc/nginx/conf.d/artifactory.conf;
                fi;
                if ! grep -q 'proxy_http_version' /etc/nginx/conf.d/artifactory.conf; then
                sed -i 's,\(proxy_next_upstream .*\),proxy_http_version  1.1;\n    \1,g' /etc/nginx/conf.d/artifactory.conf;
                fi;
                sleep 5; nginx -s reload; touch /var/log/nginx/conf.done
        env:
        - name: ART_BASE_URL
          {{- if .Values.nginx.env.artUrl }}
          value: {{ .Values.nginx.env.artUrl }}
          {{- else }}
          value: 'http://{{ $serviceName }}:{{ $servicePort }}/artifactory'
          {{- end }}
        - name: SSL
          value: "{{ .Values.nginx.env.ssl }}"
        - name: SKIP_AUTO_UPDATE_CONFIG
          value: "{{ .Values.nginx.env.skipAutoConfigUpdate }}"
        ports:
        - containerPort: {{ .Values.nginx.internalPortHttp }}
        - containerPort: {{ .Values.nginx.internalPortHttps }}
        {{- if .Values.artifactory.replicator.enabled }}
        - containerPort: {{ .Values.nginx.internalPortReplicator }}
        {{- end }}
        volumeMounts:
        - name: nginx-volume
          mountPath: {{ .Values.nginx.persistence.mountPath | quote }}
        {{- if .Values.artifactory.replicator.enabled }}
        - name: replicator-nginx-config
          mountPath: "/tmp/replicator-nginx.conf"
          subPath: replicator-nginx.conf
        {{- end }}
        {{- if .Values.nginx.tlsSecretName }}
        - name: ssl-secret-volume
          mountPath: "/tmp/ssl"
        {{- end }}
        {{- if .Values.nginx.customConfigMap }}
        - name: nginx-config
          mountPath: "/tmp/"
        {{- end }}
        resources:
{{ toYaml .Values.nginx.resources | indent 10 }}
        {{- if .Values.nginx.readinessProbe.enabled }}
        readinessProbe:
          httpGet:
            path: '/artifactory/webapp/#/login'
            port: 80
          initialDelaySeconds: {{ .Values.nginx.readinessProbe.initialDelaySeconds }}
          periodSeconds: {{ .Values.nginx.readinessProbe.periodSeconds }}
          timeoutSeconds: {{ .Values.nginx.readinessProbe.timeoutSeconds }}
          failureThreshold: {{ .Values.nginx.readinessProbe.failureThreshold }}
          successThreshold: {{ .Values.nginx.readinessProbe.successThreshold }}
        {{- end }}
        {{- if .Values.nginx.livenessProbe.enabled }}
        livenessProbe:
          httpGet:
            path: '/artifactory/webapp/#/login'
            port: 80
          initialDelaySeconds: {{ .Values.nginx.livenessProbe.initialDelaySeconds }}
          periodSeconds: {{ .Values.nginx.livenessProbe.periodSeconds }}
          timeoutSeconds: {{ .Values.nginx.livenessProbe.timeoutSeconds }}
          failureThreshold: {{ .Values.nginx.livenessProbe.failureThreshold }}
          successThreshold: {{ .Values.nginx.livenessProbe.successThreshold }}
        {{- end }}
    {{- with .Values.nginx.nodeSelector }}
      nodeSelector:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.nginx.affinity }}
      affinity:
{{ toYaml . | indent 8 }}
    {{- end }}
    {{- with .Values.nginx.tolerations }}
      tolerations:
{{ toYaml . | indent 8 }}
    {{- end }}
      volumes:
      {{- if .Values.artifactory.replicator.enabled }}
      - name: replicator-nginx-config
        configMap:
          name: {{ template "artifactory-ha.fullname" . }}-replicator-nginx-config
      {{- end}}
      {{- if .Values.nginx.customConfigMap }}
      - name: nginx-config
        configMap:
          name: {{ .Values.nginx.customConfigMap }}
      {{- end }}
      - name: nginx-volume
      {{- if .Values.nginx.persistence.enabled }}
        persistentVolumeClaim:
          claimName: {{ .Values.nginx.persistence.existingClaim | default (include "artifactory-ha.nginx.fullname" .) }}
      {{- else }}
        emptyDir: {}
      {{- end -}}
      {{- if .Values.nginx.tlsSecretName }}
      - name: ssl-secret-volume
        secret:
          secretName: {{ .Values.nginx.tlsSecretName }}
      {{- end }}
{{- end }}
 # nginx-pvc.yaml
{{- if and .Values.nginx.persistence.enabled (.Values.nginx.enabled ) }}
{{- if (not .Values.nginx.persistence.existingClaim) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {{ template "artifactory-ha.nginx.fullname" . }}
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  accessModes:
    - {{ .Values.nginx.persistence.accessMode | quote }}
  resources:
    requests:
      storage: {{ .Values.nginx.persistence.size | quote }}
{{- if .Values.nginx.persistence.storageClass }}
{{- if (eq "-" .Values.nginx.persistence.storageClass) }}
  storageClassName: ""
{{- else }}
  storageClassName: "{{ .Values.nginx.persistence.storageClass }}"
{{- end }}
{{- end }}
{{- end }}
{{- end }}
 # nginx-replicator-conf.yaml
{{- if .Values.artifactory.replicator.enabled -}}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-replicator-nginx-config
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
data:
  replicator-nginx.conf: |
      ## Artifactory replicator
      server {
        listen         {{ .Values.nginx.externalPortReplicator }};
        server_name    {{ include "artifactory-ha.fullname" . }};

        client_max_body_size 0;

        location / {
          proxy_read_timeout  900;
          proxy_pass_header   Server;
          proxy_pass          http://{{ include "artifactory-ha.primary.name" . }}:{{ .Values.nginx.internalPortReplicator }};
          proxy_http_version  1.1;
        }
      }
{{- end -}} # nginx-service.yaml
{{- if .Values.nginx.enabled -}}
apiVersion: v1
kind: Service
metadata:
  name: {{ template "artifactory-ha.nginx.fullname" . }}
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
    component: {{ .Values.nginx.name }}
spec:
  type: {{ .Values.nginx.service.type }}
{{- if eq .Values.nginx.service.type "LoadBalancer" }}
  {{ if .Values.nginx.service.loadBalancerIP -}}
  loadBalancerIP: {{ .Values.nginx.service.loadBalancerIP }}
  {{ end -}}
  externalTrafficPolicy: Local
{{- end }}
{{- if .Values.nginx.service.loadBalancerSourceRanges }}
  loadBalancerSourceRanges:
{{ toYaml .Values.nginx.service.loadBalancerSourceRanges | indent 4 }}
{{- end }}
  ports:
  {{- if .Values.artifactory.replicator.enabled }}
  - port: {{ .Values.nginx.externalPortReplicator }}
    targetPort: {{ .Values.nginx.internalPortReplicator }}
    protocol: TCP
    name: replicator
  {{- end }}
  - port: {{ .Values.nginx.externalPortHttp }}
    targetPort: {{ .Values.nginx.internalPortHttp }}
    protocol: TCP
    name: http
  - port: {{ .Values.nginx.externalPortHttps }}
    targetPort: {{ .Values.nginx.internalPortHttps }}
    protocol: TCP
    name: https
  selector:
    app: {{ template "artifactory-ha.name" . }}
    component: {{ .Values.nginx.name }}
    release: {{ .Release.Name }}
{{- end }} # replicator-configmap.yaml
{{- if .Values.artifactory.replicator.enabled -}}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ template "artifactory-ha.fullname" . }}-replicator-config
  labels:
    app: {{ template "artifactory-ha.name" . }}
    chart: {{ template "artifactory-ha.chart" . }}
    heritage: {{ .Release.Service }}
    release: {{ .Release.Name }}
data:
  replicator.yaml: |-
    externalUrl: {{ .Values.artifactory.replicator.publicUrl }}
    internalUrl: http://localhost:6061
    listenPort: 6061
{{- end -}}

# Default values for artifactory-ha.
# This is a YAML-formatted file.
# Beware when changing values here. You should know what you are doing!
# Access the values with {{ .Values.key.subkey }}

# Common
initContainerImage: "alpine:3.6"

# For supporting pulling from private registries
imagePullSecrets:

## Role Based Access Control
## Ref: https://kubernetes.io/docs/admin/authorization/rbac/
rbac:
  create: true
  role:
    ## Rules to create. It follows the role specification
    rules:
    - apiGroups:
      - ''
      resources:
      - services
      - endpoints
      - pods
      verbs:
      - get
      - watch
      - list

## Service Account
## Ref: https://kubernetes.io/docs/admin/service-accounts-admin/
##
serviceAccount:
  create: true
  ## The name of the ServiceAccount to use.
  ## If not set and create is true, a name is generated using the fullname template
  name:

ingress:
  enabled: false
  # Used to create an Ingress record.
  hosts:
  #  - artifactory.domain.example
  annotations:
  # kubernetes.io/ingress.class: nginx
  # kubernetes.io/tls-acme: "true"
  tls:
  # Secrets must be manually created in the namespace.
  # - secretName: chart-example-tls
  #   hosts:
  #     - artifactory.domain.example

# Database
## Configuration values for the postgresql dependency
## ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md
##
postgresql:
  enabled: true
  postgresDatabase: "artifactory"
  postgresUser: "artifactory"
  postgresPassword:
  postgresConfig:
    maxConnections: "1500"
  service:
    port: 5432
  persistence:
    enabled: true
    size: 50Gi
  resources: {}
  #  requests:
  #    memory: "512Mi"
  #    cpu: "100m"
  #  limits:
  #    memory: "1Gi"
  #    cpu: "500m"

## If NOT using the PostgreSQL in this chart (postgresql.enabled=false),
## you must specify the following database details
database:
  type:
  host:
  port:
  user:
  password:

# Artifactory
artifactory:
  name: artifactory-ha
  image:
    repository: "docker.bintray.io/jfrog/artifactory-pro"
    # Note that by default we use appVersion to get image tag
    # version: 6.2.0
    pullPolicy: IfNotPresent
  ## Artifactory requires a unique master key
  ## You can generate one with the command:
  ## 'openssl rand -hex 32'
  ## Pass it to helm with '--set artifactory.masterKey=${MASTER_KEY}'
  ## IMPORTANT: You should NOT use the example masterKey for a production deployment!
  masterKey: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

  ## Artifactory license secret.
  ## If artifactory.license.secret is passed, it will be mounted as
  ## ARTIFACTORY_HOME/etc/artifactory.cluster.license and loaded at run time.
  ## The dataKey should be the name of the secret data key created.
  license:
    secret:
    dataKey:
  ## Create configMap with artifactory.config.import.xml and security.import.xml and pass name of configMap in following parameter
  configMapName:

  ## Extra postStart command to install JDBC driver for MySql/MariaDb/Oracle
  # postStartCommand: "curl -L -o /opt/jfrog/artifactory/tomcat/lib/mysql-connector-java-5.1.41.jar https://jcenter.bintray.com/mysql/mysql-connector-java/5.1.41/mysql-connector-java-5.1.41.jar && chown 1030:1030 /opt/jfrog/artifactory/tomcat/lib/mysql-connector-java-5.1.41.jar"

  membershipPort: 10017
  externalPort: 8081
  internalPort: 8081
  internalPortReplicator: 6061
  externalPortReplicator: 6061
  uid: 1030
  ## The following settings are to configure the frequency of the liveness and readiness probes
  livenessProbe:
    enabled: true
    initialDelaySeconds: 180
    failureThreshold: 10
    timeoutSeconds: 10
    periodSeconds: 10
    successThreshold: 1

  readinessProbe:
    enabled: true
    initialDelaySeconds: 60
    failureThreshold: 10
    timeoutSeconds: 10
    periodSeconds: 10
    successThreshold: 1
  persistence:
    enabled: true
    local: false
    redundancy: 3
    mountPath: "/var/opt/jfrog/artifactory"
    accessMode: ReadWriteOnce
    size: 200Gi
    ## artifactory data Persistent Volume Storage Class
    ## If defined, storageClassName: <storageClass>
    ## If set to "-", storageClassName: "", which disables dynamic provisioning
    ## If undefined (the default) or set to null, no storageClassName spec is
    ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
    ##   GKE, AWS & OpenStack)
    ##
    # storageClass: "-"

    ## Set the persistence storage type. This will apply the matching binarystore.xml to Artifactory config
    ## Supported types are:
    ## file-system (default)
    ## nfs
    ## google-storage
    ## aws-s3
    type: file-system

    ## For artifactory.persistence.type nfs
    ## If using NFS as the shared storage, you must have a running NFS server that is accessible by your Kubernetes
    ## cluster nodes.
    ## Need to have the following set
    nfs:
      # Must pass actual IP of NFS server with '--set For artifactory.persistence.nfs.ip=${NFS_IP}'
      ip:
      haDataMount: "/data"
      haBackupMount: "/backup"
      dataDir: "/var/opt/jfrog/artifactory-ha"
      backupDir: "/var/opt/jfrog/artifactory-backup"
      capacity: 200Gi
    ## For artifactory.persistence.type google-storage
    googleStorage:
      # Set a unique bucket name
      bucketName: "artifactory-ha-gcp"
      identity:
      credential:
      path: "artifactory-ha/filestore"
    ## For artifactory.persistence.type aws-s3
    awsS3:
      # Set a unique bucket name
      bucketName: "artifactory-ha-aws"
      region:
      identity:
      credential:
      path: "artifactory-ha/filestore"
  service:
    name: artifactory
    type: ClusterIP
    ## Which nodes in the cluster should be in the external load balancer pool (have external traffic routed to them)
    ## Supported pool values
    ## members
    ## all
    pool: members

  ## The following Java options are passed to the java process running Artifactory.
  ## This will be passed to all cluster members. Primary and member nodes.
  javaOpts:
    other: "-Dartifactory.locking.provider.type=db"
  ## Artifactory Replicator is available only for Enterprise Plus
  replicator:
    enabled: false
    publicUrl:
  # Name of ConfigMap for Distribution Cert
  distributionCerts:

  ## Type specific configurations.
  ## There is a difference between the primary and the member nodes.
  ## Customising their resources and java parameters is done here.
  primary:
    name: artifactory-ha-primary
    persistence:
      ## Set existingClaim to true or false
      ## If true, you must prepare a PVC with the name e.g `artifactory-ha-primary`
      existingClaim: false
    ## Resources for the primary node
    resources: {}
    #  requests:
    #    memory: "1Gi"
    #    cpu: "500m"
    #  limits:
    #    memory: "2Gi"
    #    cpu: "1"
    ## The following Java options are passed to the java process running Artifactory primary node.
    ## You should set them according to the resources set above
    javaOpts: {}
    #  xms: "1g"
    #  xmx: "2g"
    #  other:
    nodeSelector: {}

    tolerations: []

    affinity: {}
  node:
    name: artifactory-ha-member
    persistence:
      ## Set existingClaim to true or false
      ## If true, you must prepare a PVC with the name e.g `artifactory-ha-member`
      existingClaim: false
    replicaCount: 2
    ## Resources for the member nodes
    resources: {}
    #  requests:
    #    memory: "1Gi"
    #    cpu: "500m"
    #  limits:
    #    memory: "2Gi"
    #    cpu: "1"
    ## The following Java options are passed to the java process running Artifactory member nodes.
    ## You should set them according to the resources set above
    javaOpts: {}
    #  xms: "1g"
    #  xmx: "2g"
    #  other:
    nodeSelector: {}

    tolerations: []

    affinity: {}

# Nginx
nginx:
  enabled: true
  name: nginx
  replicaCount: 1
  image:
    repository: "docker.bintray.io/jfrog/nginx-artifactory-pro"
    # Note that by default we use appVersion to get image tag
    # version: 6.2.0
    pullPolicy: IfNotPresent
  service:
    ## For minikube, set this to NodePort, elsewhere use LoadBalancer
    type: LoadBalancer
    ## For supporting whitelist on the Nginx LoadBalancer service
    ## Set this to a list of IP CIDR ranges
    ## Example: loadBalancerSourceRanges: ['10.10.10.5/32', '10.11.10.5/32']
    ## or pass from helm command line
    ## Example: helm install ... --set nginx.service.loadBalancerSourceRanges='{10.10.10.5/32,10.11.10.5/32}'
    loadBalancerSourceRanges: []
    ## Provide static ip address
    loadBalancerIP:
  externalPortHttp: 80
  internalPortHttp: 80
  externalPortHttps: 443
  internalPortHttps: 443
  internalPortReplicator: 6061
  externalPortReplicator: 6061
  ## The following settings are to configure the frequency of the liveness and readiness probes
  livenessProbe:
    enabled: true
    initialDelaySeconds: 100
    failureThreshold: 10
    timeoutSeconds: 10
    periodSeconds: 10
    successThreshold: 1

  readinessProbe:
    enabled: true
    initialDelaySeconds: 60
    failureThreshold: 10
    timeoutSeconds: 10
    periodSeconds: 10
    successThreshold: 1
  ## The SSL secret that will be used by the Nginx pod
  # tlsSecretName: chart-example-tls
  env:
    ssl: true
    # artUrl: "http://artifactory:8081/artifactory"
    skipAutoConfigUpdate: false
  ## Custom ConfigMap for nginx.conf
  customConfigMap:
  persistence:
    mountPath: "/var/opt/jfrog/nginx"
    enabled: false
    ## A manually managed Persistent Volume and Claim
    ## Requires persistence.enabled: true
    ## If defined, PVC must be created manually before volume will be bound
    # existingClaim:

    accessMode: ReadWriteOnce
    size: 5Gi
    ## nginx data Persistent Volume Storage Class
    ## If defined, storageClassName: <storageClass>
    ## If set to "-", storageClassName: "", which disables dynamic provisioning
    ## If undefined (the default) or set to null, no storageClassName spec is
    ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
    ##   GKE, AWS & OpenStack)
    ##
    # storageClass: "-"
  resources: {}
  #  requests:
  #    memory: "250Mi"
  #    cpu: "100m"
  #  limits:
  #    memory: "250Mi"
  #    cpu: "500m"

  nodeSelector: {}

  tolerations: []

  affinity: {}
