mirror of
https://github.com/helm/charts.git
synced 2026-08-23 22:37:45 +00:00
Better resource management for Artifactory (#3021)
* Better resource management for Artifactory (#1) * Update Artifactory version * Add resources requests and limits to all pods * Ability to set whitelist on Nginx LoadBalancer service * Support setting a custom artifactory service name (that will also be set in nginx config) * Add new parameters to README * Fix artifactory replicas reference. Hardcode database replicas to 1 * Use resource memory requests and limits in Artifactory java options * Add readinessProbe to Artifactory * Add readme on creating a Kubernetes Docker registry secret and passing it to helm * Update Artifactory Chart version to 6.2.3 * Comment out the default resources and update README on how to use them * Set Artifactory version 5.6.3 * Remove default values for Nginx resources from README
This commit is contained in:
committed by
k8s-ci-robot
parent
38995da7ba
commit
ee20ea3ab8
@@ -1,8 +1,8 @@
|
||||
apiVersion: v1
|
||||
name: artifactory
|
||||
home: https://www.jfrog.com/artifactory/
|
||||
version: 6.2.2
|
||||
appVersion: 5.6.2
|
||||
version: 6.2.3
|
||||
appVersion: 5.6.3
|
||||
description: Universal Repository Manager supporting all major packaging formats,
|
||||
build tools and CI servers.
|
||||
keywords:
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
## Chart Details
|
||||
This chart will do the following:
|
||||
|
||||
* Deploy Artifactory-Oss
|
||||
* Deploy Artifactory-Pro
|
||||
* Deploy Artifactory-Pro (or OSS if set custom image)
|
||||
* Deploy a PostgreSQL database
|
||||
* Deploy an Nginx server
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
@@ -37,6 +38,31 @@ $ helm upgrade artifactory --namespace artifactory stable/artifactory
|
||||
|
||||
This will apply any configuration changes on your existing deployment.
|
||||
|
||||
### Artifactory memory and CPU resources
|
||||
The Artifactory Helm chart comes with support for configured resource requests and limits to Artifactory, Nginx and PostgreSQL. By default, these settings are commented out.
|
||||
It is **highly** recommended to set these so you have full control of the allocated resources and limits.
|
||||
Artifactory java memory parameters can (and should) also be set to match the allocated resources with `artifactory.javaOpts.xms` and `artifactory.javaOpts.xmx`.
|
||||
```bash
|
||||
# Example of setting resource requests and limits to all pods (including passing java memory settings to Artifactory)
|
||||
$ helm install --name artifactory \
|
||||
--set artifactory.resources.requests.cpu="500m" \
|
||||
--set artifactory.resources.limits.cpu="2" \
|
||||
--set artifactory.resources.requests.memory="1Gi" \
|
||||
--set artifactory.resources.limits.memory="4Gi" \
|
||||
--set artifactory.javaOpts.xms="1g" \
|
||||
--set artifactory.javaOpts.xmx="4g" \
|
||||
--set database.resources.requests.cpu="200m" \
|
||||
--set database.resources.limits.cpu="1" \
|
||||
--set database.resources.requests.memory="500Mi" \
|
||||
--set database.resources.limits.memory="1Gi" \
|
||||
--set nginx.resources.requests.cpu="100m" \
|
||||
--set nginx.resources.limits.cpu="250m" \
|
||||
--set nginx.resources.requests.memory="250Mi" \
|
||||
--set nginx.resources.limits.memory="500Mi" \
|
||||
stable/artifactory
|
||||
```
|
||||
Get more details on configuring Artifactory in the [official documentation](https://www.jfrog.com/confluence/).
|
||||
|
||||
### Customizing Database password
|
||||
You can override the specified database password (set in [values.yaml](values.yaml)), by passing it as a parameter in the install command line
|
||||
```bash
|
||||
@@ -49,22 +75,35 @@ You can customise other parameters in the same way, by passing them on `helm ins
|
||||
```bash
|
||||
$ helm delete --purge artifactory
|
||||
```
|
||||
|
||||
This will completely delete your Artifactory Pro deployment.
|
||||
**IMPORTANT:** This will also delete your data volumes. You will loose all data!
|
||||
|
||||
|
||||
### Custom Docker registry for your images
|
||||
If you need to pull your Docker images from a private registry, you need to create a
|
||||
[Kubernetes Docker registry secret](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) and pass it to helm
|
||||
```bash
|
||||
# Create a Docker registry secret called 'regsecret'
|
||||
$ kubectl create secret docker-registry regsecret --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
|
||||
```
|
||||
Once created, you pass it to `helm`
|
||||
```bash
|
||||
$ helm install --name artifactory --set imagePullSecrets=regsecret stable/artifactory
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The following tables lists the configurable parameters of the artifactory chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|---------------------------|-----------------------------------|----------------------------------------------------------|
|
||||
| `database.name` | Database name | `postgresql` |
|
||||
| `database.replicaCount` | Database replica count | `1` |
|
||||
| `database.env.type` | Database type | `postgresql` |
|
||||
| `database.env.name` | Database name | `artifactory` |
|
||||
| `database.env.user` | Database username | `artifactory` |
|
||||
| `database.env.pass` | Database password | `Randomly generated` |
|
||||
| `imagePullSecrets` | Docker registry pull secret | |
|
||||
| `database.name` | Database name | `postgresql` |
|
||||
| `database.replicaCount` | Database replica count | `1` |
|
||||
| `database.env.type` | Database type | `postgresql` |
|
||||
| `database.env.name` | Database name | `artifactory` |
|
||||
| `database.env.user` | Database username | `artifactory` |
|
||||
| `database.env.pass` | Database password | `Randomly generated` |
|
||||
| `database.image.repository` | Database container image | `docker.bintray.io/postgres` |
|
||||
| `database.image.version` | Database container image tag | `9.5.2` |
|
||||
| `database.image.pullPolicy` | Container pull policy | `IfNotPresent` |
|
||||
@@ -74,12 +113,17 @@ The following tables lists the configurable parameters of the artifactory chart
|
||||
| `database.persistence.mountPath` | Database persistence volume mount path | `"/var/lib/postgresql/data"` |
|
||||
| `database.persistence.enabled` | Database persistence volume enabled | `true` |
|
||||
| `database.persistence.accessMode` | Database persistence volume access mode | `ReadWriteOnce` |
|
||||
| `database.persistence.size` | Database persistence volume size | `10Gi` |
|
||||
| `database.persistence.size` | Database persistence volume size | `10Gi` |
|
||||
| `database.resources.requests.memory` | Database initial memory request | |
|
||||
| `database.resources.requests.cpu` | Database initial cpu request | |
|
||||
| `database.resources.limits.memory` | Database memory limit | |
|
||||
| `database.resources.limits.cpu` | Database cpu limit | |
|
||||
| `artifactory.name` | Artifactory name | `artifactory` |
|
||||
| `artifactory.replicaCount` | Replica count for Artifactory deployment| `1` |
|
||||
| `artifactory.image.pullPolicy` | Container pull policy | `IfNotPresent` |
|
||||
| `artifactory.image.repository` | Container image | `docker.bintray.io/jfrog/artifactory-pro` |
|
||||
| `artifactory.image.version` | Container image tag | `5.6.2` |
|
||||
| `artifactory.image.version` | Container image tag | `5.6.3` |
|
||||
| `artifactory.service.name`| Artifactory service name to be set in Nginx configuration | `artifactory` |
|
||||
| `artifactory.service.type`| Artifactory service type | `ClusterIP` |
|
||||
| `artifactory.externalPort` | Artifactory service external port | `8081` |
|
||||
| `artifactory.internalPort` | Artifactory service internal port | `8081` |
|
||||
@@ -87,12 +131,20 @@ The following tables lists the configurable parameters of the artifactory chart
|
||||
| `artifactory.persistence.enabled` | Artifactory persistence volume enabled | `true` |
|
||||
| `artifactory.persistence.accessMode` | Artifactory persistence volume access mode | `ReadWriteOnce` |
|
||||
| `artifactory.persistence.size` | Artifactory persistence volume size | `20Gi` |
|
||||
| `artifactory.resources.requests.memory` | Artifactory initial memory request | |
|
||||
| `artifactory.resources.requests.cpu` | Artifactory initial cpu request | |
|
||||
| `artifactory.resources.limits.memory` | Artifactory memory limit | |
|
||||
| `artifactory.resources.limits.cpu` | Artifactory cpu limit | |
|
||||
| `artifactory.javaOpts.xms` | Artifactory java Xms size | |
|
||||
| `artifactory.javaOpts.xmx` | Artifactory java Xms size | |
|
||||
| `artifactory.javaOpts.other` | Artifactory additional java options | |
|
||||
| `nginx.name` | Nginx name | `nginx` |
|
||||
| `nginx.replicaCount` | Nginx replica count | `1` |
|
||||
| `nginx.image.repository` | Container image | `docker.bintray.io/jfrog/nginx-artifactory-pro` |
|
||||
| `nginx.image.pullPolicy` | Container pull policy | `IfNotPresent` |
|
||||
| `nginx.image.version` | Container image tag | `5.6.2` |
|
||||
| `nginx.image.version` | Container image tag | `5.6.3` |
|
||||
| `nginx.service.type`| Nginx service type | `LoadBalancer` |
|
||||
| `nginx.service.loadBalancerSourceRanges`| Nginx service array of IP CIDR ranges to whitelist (only when service type is LoadBalancer) | |
|
||||
| `nginx.externalPortHttp` | Nginx service external port | `80` |
|
||||
| `nginx.internalPortHttp` | Nginx service internal port | `80` |
|
||||
| `nginx.externalPortHttps` | Nginx service external port | `443` |
|
||||
@@ -103,6 +155,10 @@ The following tables lists the configurable parameters of the artifactory chart
|
||||
| `nginx.persistence.enabled` | Nginx persistence volume enabled | `true` |
|
||||
| `nginx.persistence.accessMode` | Nginx persistence volume access mode | `ReadWriteOnce` |
|
||||
| `nginx.persistence.size` | Nginx persistence volume size | `5Gi` |
|
||||
| `nginx.resources.requests.memory` | Nginx initial memory request | |
|
||||
| `nginx.resources.requests.cpu` | Nginx initial cpu request | |
|
||||
| `nginx.resources.limits.memory` | Nginx memory limit | |
|
||||
| `nginx.resources.limits.cpu` | Nginx cpu limit | |
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ metadata:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
replicas: {{ .Values.artReplicaCount }}
|
||||
replicas: {{ .Values.artifactory.replicaCount }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
@@ -17,17 +17,27 @@ spec:
|
||||
component: "{{ .Values.artifactory.name }}"
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.imagePullSecrets }}
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: "remove-lost-found"
|
||||
image: "{{ .Values.initContainerImage }}"
|
||||
imagePullPolicy: {{ .Values.artifactory.image.pullPolicy }}
|
||||
command:
|
||||
- "rm"
|
||||
- "-rf"
|
||||
- "{{ .Values.artifactory.persistence.mountPath }}/lost+found"
|
||||
- 'sh'
|
||||
- '-c'
|
||||
- 'rm -rfv {{ .Values.artifactory.persistence.mountPath }}/lost+found'
|
||||
volumeMounts:
|
||||
- mountPath: {{ .Values.artifactory.persistence.mountPath | quote }}
|
||||
name: artifactory-volume
|
||||
- name: "wait-for-db"
|
||||
image: "{{ .Values.initContainerImage }}"
|
||||
command:
|
||||
- 'sh'
|
||||
- '-c'
|
||||
- 'until nc -z -w 2 {{ template "artifactory.database.name" . }} {{ .Values.database.externalPort }} && echo database ok; do sleep 2; done'
|
||||
containers:
|
||||
- name: {{ .Values.artifactory.name }}
|
||||
image: "{{ .Values.artifactory.image.repository }}:{{ .Values.artifactory.image.version }}"
|
||||
@@ -44,11 +54,38 @@ spec:
|
||||
key: artifactory-database-password
|
||||
- name: DB_HOST
|
||||
value: {{ template "artifactory.database.name" . }}
|
||||
- name: EXTRA_JAVA_OPTIONS
|
||||
value: "
|
||||
{{- if .Values.artifactory.javaOpts.other }}
|
||||
{{ .Values.artifactory.javaOpts.other }}
|
||||
{{- end}}
|
||||
{{- if .Values.artifactory.javaOpts.xms }}
|
||||
-Xms{{ .Values.artifactory.javaOpts.xms }}
|
||||
{{- end}}
|
||||
{{- if .Values.artifactory.javaOpts.xmx }}
|
||||
-Xmx{{ .Values.artifactory.javaOpts.xmx }}
|
||||
{{- end}}
|
||||
"
|
||||
ports:
|
||||
- containerPort: {{ .Values.artifactory.internalPort }}
|
||||
volumeMounts:
|
||||
- mountPath: {{ .Values.artifactory.persistence.mountPath | quote }}
|
||||
name: artifactory-volume
|
||||
- name: artifactory-volume
|
||||
mountPath: {{ .Values.artifactory.persistence.mountPath | quote }}
|
||||
resources:
|
||||
{{ toYaml .Values.artifactory.resources | indent 10 }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: '/artifactory/webapp/#/login'
|
||||
port: 8081
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: '/artifactory/webapp/#/login'
|
||||
port: 8081
|
||||
initialDelaySeconds: 180
|
||||
periodSeconds: 10
|
||||
volumes:
|
||||
- name: artifactory-volume
|
||||
{{- if .Values.artifactory.persistence.enabled }}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "artifactory.artifactory.name" . }}
|
||||
name: {{ .Values.artifactory.service.name }}
|
||||
labels:
|
||||
app: {{ template "artifactory.name" . }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
|
||||
@@ -17,14 +17,18 @@ spec:
|
||||
component: "{{ .Values.nginx.name }}"
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.imagePullSecrets }}
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: "remove-lost-found"
|
||||
image: "{{ .Values.initContainerImage }}"
|
||||
imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
|
||||
command:
|
||||
- "rm"
|
||||
- "-rf"
|
||||
- "{{ .Values.nginx.persistence.mountPath }}/lost+found"
|
||||
- '/bin/sh'
|
||||
- '-c'
|
||||
- 'rm -rfv {{ .Values.nginx.persistence.mountPath }}/lost+found'
|
||||
volumeMounts:
|
||||
- mountPath: {{ .Values.nginx.persistence.mountPath | quote }}
|
||||
name: nginx-volume
|
||||
@@ -32,17 +36,31 @@ spec:
|
||||
- name: {{ .Values.nginx.name }}
|
||||
image: "{{ .Values.nginx.image.repository }}:{{ .Values.nginx.image.version }}"
|
||||
imagePullPolicy: {{ .Values.nginx.image.pullPolicy }}
|
||||
lifecycle:
|
||||
postStart:
|
||||
exec:
|
||||
command:
|
||||
- '/bin/sh'
|
||||
- '-c'
|
||||
- >
|
||||
until [ -f /etc/nginx/conf.d/artifactory.conf ]; do sleep 1; done;
|
||||
sed -i -e 's,proxy_pass .*,proxy_pass {{ .Values.nginx.env.artUrl }}/;,g' \
|
||||
-e 's,server_name .*,server_name ~(?<repo>.+)\\.{{ .Values.artifactory.service.name }} {{ .Values.artifactory.service.name }};,g' \
|
||||
/etc/nginx/conf.d/artifactory.conf;
|
||||
sleep 5; nginx -s reload; touch /var/log/nginx/conf.done
|
||||
env:
|
||||
- name: ART_BASE_URL
|
||||
value: {{ .Values.nginx.env.artUrl }}
|
||||
value: "{{ .Values.nginx.env.artUrl }}"
|
||||
- name: SSL
|
||||
value: "{{ .Values.nginx.env.ssl }}"
|
||||
ports:
|
||||
- containerPort: {{ .Values.nginx.internalPortHttp }}
|
||||
- containerPort: {{ .Values.nginx.internalPortHttps }}
|
||||
volumeMounts:
|
||||
- mountPath: {{ .Values.nginx.persistence.mountPath | quote }}
|
||||
name: nginx-volume
|
||||
- name: nginx-volume
|
||||
mountPath: {{ .Values.nginx.persistence.mountPath | quote }}
|
||||
resources:
|
||||
{{ toYaml .Values.nginx.resources | indent 10 }}
|
||||
volumes:
|
||||
- name: nginx-volume
|
||||
{{- if .Values.nginx.persistence.enabled }}
|
||||
|
||||
@@ -10,6 +10,13 @@ metadata:
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
type: {{ .Values.nginx.service.type }}
|
||||
{{- if eq .Values.nginx.service.type "LoadBalancer" }}
|
||||
externalTrafficPolicy: Local
|
||||
{{- end }}
|
||||
{{- if .Values.nginx.service.loadBalancerSourceRanges }}
|
||||
loadBalancerSourceRanges:
|
||||
{{ toYaml .Values.nginx.service.loadBalancerSourceRanges | indent 4 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- port: {{ .Values.nginx.externalPortHttp }}
|
||||
targetPort: {{ .Values.nginx.internalPortHttp }}
|
||||
|
||||
@@ -9,7 +9,7 @@ metadata:
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
@@ -22,9 +22,9 @@ spec:
|
||||
image: "{{ .Values.initContainerImage }}"
|
||||
imagePullPolicy: "{{ .Values.database.image.pullPolicy }}"
|
||||
command:
|
||||
- "rm"
|
||||
- "-rf"
|
||||
- "{{ .Values.database.persistence.mountPath }}/lost+found"
|
||||
- 'sh'
|
||||
- '-c'
|
||||
- 'rm -rf {{ .Values.database.persistence.mountPath }}/lost+found'
|
||||
volumeMounts:
|
||||
- mountPath: {{ .Values.database.persistence.mountPath | quote }}
|
||||
name: postgresql-volume
|
||||
@@ -47,6 +47,26 @@ spec:
|
||||
volumeMounts:
|
||||
- mountPath: {{ .Values.database.persistence.mountPath | quote }}
|
||||
name: postgresql-volume
|
||||
resources:
|
||||
{{ toYaml .Values.database.resources | indent 10 }}
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- exec pg_isready
|
||||
initialDelaySeconds: 60
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- exec pg_isready
|
||||
initialDelaySeconds: 30
|
||||
timeoutSeconds: 3
|
||||
periodSeconds: 5
|
||||
volumes:
|
||||
- name: postgresql-volume
|
||||
{{- if .Values.database.persistence.enabled }}
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
# Access the values with {{ .Values.key.subkey }}
|
||||
|
||||
# Common
|
||||
initContainerImage: "busybox:1.26.2"
|
||||
initContainerImage: "alpine:3.6"
|
||||
|
||||
# For supporting pulling from private registries
|
||||
imagePullSecrets:
|
||||
|
||||
# Database
|
||||
database:
|
||||
name: postgresql
|
||||
replicaCount: 1
|
||||
env:
|
||||
type: postgresql
|
||||
name: artifactory
|
||||
@@ -37,6 +39,13 @@ database:
|
||||
## GKE, AWS & OpenStack)
|
||||
##
|
||||
# storageClass: "-"
|
||||
resources: {}
|
||||
# requests:
|
||||
# memory: "512Mi"
|
||||
# cpu: "100m"
|
||||
# limits:
|
||||
# memory: "1Gi"
|
||||
# cpu: "500m"
|
||||
|
||||
# Artifactory
|
||||
artifactory:
|
||||
@@ -45,9 +54,10 @@ artifactory:
|
||||
image:
|
||||
# repository: "docker.bintray.io/jfrog/artifactory-oss"
|
||||
repository: "docker.bintray.io/jfrog/artifactory-pro"
|
||||
version: 5.6.2
|
||||
version: 5.6.3
|
||||
pullPolicy: IfNotPresent
|
||||
service:
|
||||
name: artifactory
|
||||
type: ClusterIP
|
||||
externalPort: 8081
|
||||
internalPort: 8081
|
||||
@@ -64,6 +74,21 @@ artifactory:
|
||||
## GKE, AWS & OpenStack)
|
||||
##
|
||||
# storageClass: "-"
|
||||
## Uncomment the following resources definitions or pass them from command line
|
||||
## to control the cpu and memory resources allocated by the Kubernetes cluster
|
||||
resources: {}
|
||||
# requests:
|
||||
# memory: "1Gi"
|
||||
# cpu: "500m"
|
||||
# limits:
|
||||
# memory: "2Gi"
|
||||
# cpu: "1"
|
||||
## The following Java options are passed to the java process running Artifactory.
|
||||
## You should set them according to the resources set above
|
||||
javaOpts: {}
|
||||
# xms: "1g"
|
||||
# xmx: "2g"
|
||||
# other: ""
|
||||
|
||||
# Nginx
|
||||
nginx:
|
||||
@@ -71,11 +96,17 @@ nginx:
|
||||
replicaCount: 1
|
||||
image:
|
||||
repository: "docker.bintray.io/jfrog/nginx-artifactory-pro"
|
||||
version: 5.6.2
|
||||
version: 5.6.3
|
||||
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: []
|
||||
externalPortHttp: 80
|
||||
internalPortHttp: 80
|
||||
externalPortHttps: 443
|
||||
@@ -96,3 +127,10 @@ nginx:
|
||||
## GKE, AWS & OpenStack)
|
||||
##
|
||||
# storageClass: "-"
|
||||
resources: {}
|
||||
# requests:
|
||||
# memory: "250Mi"
|
||||
# cpu: "100m"
|
||||
# limits:
|
||||
# memory: "250Mi"
|
||||
# cpu: "500m"
|
||||
|
||||
Reference in New Issue
Block a user