mirror of
https://github.com/helm/charts.git
synced 2026-08-23 22:37:45 +00:00
Add initial checkin for openebs chart (#3879)
* Add initial checkin for openebs chart Signed-off-by: kmova <kiran.mova@openebs.io> * Use the template to define chart name Signed-off-by: kmova <kiran.mova@openebs.io> * update labels to follow helm best practicies Signed-off-by: kmova <kiran.mova@openebs.io> * update values to use camelCase Signed-off-by: kmova <kiran.mova@openebs.io> * follow chart conventions for rbac Signed-off-by: kmova <kiran.mova@openebs.io> * Update kubectl command to fetch pod status Signed-off-by: kmova <kiran.mova@openebs.io> * Update configuration, fix namespace condition Signed-off-by: kmova <kiran.mova@openebs.io> * remove blank line Signed-off-by: kmova <kiran.mova@openebs.io> * includes fixes for namespace and serviceaccount Signed-off-by: kmova <kiran.mova@openebs.io> * refactor affinity and update readme Signed-off-by: kmova <kiran.mova@openebs.io> * remove if blocks around serviceAccount Signed-off-by: kmova <kiran.mova@openebs.io> * use fullname in rbac and remove empty lines Signed-off-by: kmova <kiran.mova@openebs.io> * update maintainers section Signed-off-by: kmova <kiran.mova@openebs.io> * Remove storageclasses and set default sa to empty Signed-off-by: kmova <kiran.mova@openebs.io> * move the charts to stable Signed-off-by: kmova <kiran.mova@openebs.io>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
@@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
version: 0.5.3
|
||||
name: openebs
|
||||
appVersion: "0.5.3"
|
||||
description: Containerized Storage for Containers
|
||||
icon: https://raw.githubusercontent.com/openebs/chitrakala/master/OpenEBS%20logo/openebs%20logos-03.png
|
||||
home: http://www.openebs.io/
|
||||
keywords:
|
||||
- cloud-native-storage
|
||||
- block-storage
|
||||
- iSCSI
|
||||
- storage
|
||||
sources:
|
||||
- https://github.com/openebs/openebs
|
||||
maintainers:
|
||||
- name: kmova
|
||||
email: kiran.mova@openebs.io
|
||||
@@ -0,0 +1,62 @@
|
||||
OpenEBS
|
||||
=======
|
||||
|
||||
[OpenEBS](https://github.com/openebs/openebs) is an open source storage platform that provides persistent and containerized block storage for DevOps and container environments.
|
||||
|
||||
OpenEBS can be deployed on any Kubernetes cluster - either in cloud, on-premise or developer laptop (minikube). OpenEBS itself is deployed as just another container on your cluster, and enables storage services that can be designated on a per pod, application, cluster or container level.
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This chart bootstraps OpenEBS deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
|
||||
|
||||
## Prerequisites
|
||||
- Kubernetes 1.7.5+ with RBAC enabled
|
||||
- iSCSI PV support in the underlying infrastructure
|
||||
|
||||
## Installing OpenEBS
|
||||
```
|
||||
helm install incubator/openebs
|
||||
```
|
||||
|
||||
## Installing OpenEBS with the release name `my-release`:
|
||||
```
|
||||
helm install --name `my-release` incubator/openebs
|
||||
```
|
||||
|
||||
## To uninstall/delete the `my-release` deployment:
|
||||
```
|
||||
helm ls --all
|
||||
helm delete `my-release`
|
||||
```
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
The following tables lists the configurable parameters of the OpenEBS chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| ------------------------------------ | --------------------------------------------- | --------------------------------- |
|
||||
| `rbac.create` | Enable RBAC Resources | `true` |
|
||||
| `serviceAccount.create` | Specify if Service Account should be created | `true` |
|
||||
| `serviceAccount.name` | Specify the name of service account | `openebs-maya-operator` |
|
||||
| `image.pullPolicy` | Container pull policy | `IfNotPresent` |
|
||||
| `apiserver.image` | Docker Image for API Server | `openebs/m-apiserver` |
|
||||
| `apiserver.imageTag` | Docker Image Tag for API Server | `0.5.3` |
|
||||
| `apiserver.replicas` | Number of API Server Replicas | `1` |
|
||||
| `provisioner.image` | Docker Image for Provisioner | `openebs/openebs-k8s-provisioner` |
|
||||
| `provisioner.imageTag` | Docker Image Tag for Provisioner | `0.5.3` |
|
||||
| `provisioner.replicas` | Number of Provisioner Replicas | `1` |
|
||||
| `jiva.image` | Docker Image for Jiva | `openebs/jiva` |
|
||||
| `jiva.imageTag` | Docker Image Tag for Jiva | `0.5.3` |
|
||||
| `jiva.replicas` | Number of Jiva Replicas | `3` |
|
||||
|
||||
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`.
|
||||
|
||||
Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
|
||||
|
||||
```shell
|
||||
helm install --name `my-release` -f values.yaml incubator/openebs
|
||||
```
|
||||
|
||||
> **Tip**: You can use the default [values.yaml](values.yaml)
|
||||
@@ -0,0 +1,39 @@
|
||||
The OpenEBS has been installed. Check its status by running:
|
||||
kubectl get pods -n {{ .Release.Namespace }}
|
||||
|
||||
For dynamically creating OpenEBS Volumes, you will need to create StorageClass.
|
||||
|
||||
OpenEBS Storage class can be created using the following spec:
|
||||
---
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: openebs-standard
|
||||
provisioner: openebs.io/provisioner-iscsi
|
||||
parameters:
|
||||
openebs.io/storage-pool: "default"
|
||||
openebs.io/jiva-replica-count: "3"
|
||||
openebs.io/volume-monitor: "true"
|
||||
openebs.io/capacity: 5G
|
||||
---
|
||||
|
||||
And use this storage class "openebs-standard" in your PVC as shown below:
|
||||
---
|
||||
kind: PersistentVolumeClaim
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: demo-vol-claim
|
||||
spec:
|
||||
storageClassName: openebs-standard
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 4G
|
||||
---
|
||||
|
||||
For more information, please visit http://docs.openebs.io/.
|
||||
|
||||
Please note that, OpenEBS uses iSCSI for connecting applications with the
|
||||
OpenEBS Volumes and your nodes should have the iSCSI initiator installed.
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "openebs.name" -}}
|
||||
{{- default .Chart.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 "openebs.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 chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "openebs.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "openebs.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{ default (include "openebs.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,29 @@
|
||||
{{- if .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ template "openebs.fullname". }}
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["nodes","nodes/proxy"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["*"]
|
||||
resources: ["namespaces", "services", "pods", "deployments", "events", "endpoints"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["*"]
|
||||
resources: ["persistentvolumes","persistentvolumeclaims"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["storageclasses"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["*"]
|
||||
resources: ["storagepools"]
|
||||
verbs: ["get", "list"]
|
||||
- nonResourceURLs: ["/metrics"]
|
||||
verbs: ["get"]
|
||||
{{- end }}
|
||||
@@ -0,0 +1,19 @@
|
||||
{{- if .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ template "openebs.fullname". }}
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ template "openebs.fullname". }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "openebs.serviceAccountName". }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,27 @@
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
# name must match the spec fields below, and be in the form: <plural>.<group>
|
||||
name: storagepools.openebs.io
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
# group name to use for REST API: /apis/<group>/<version>
|
||||
group: openebs.io
|
||||
# version name to use for REST API: /apis/<group>/<version>
|
||||
version: v1alpha1
|
||||
# either Namespaced or Cluster
|
||||
scope: Cluster
|
||||
names:
|
||||
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
|
||||
plural: storagepools
|
||||
# singular name to be used as an alias on the CLI and for display
|
||||
singular: storagepool
|
||||
# kind is normally the CamelCased singular type. Your resource manifests use this.
|
||||
kind: StoragePool
|
||||
# shortNames allow shorter string to match your resource on the CLI
|
||||
shortNames:
|
||||
- sp
|
||||
@@ -0,0 +1,27 @@
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
# name must match the spec fields below, and be in the form: <plural>.<group>
|
||||
name: storagepoolclaims.openebs.io
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
# group name to use for REST API: /apis/<group>/<version>
|
||||
group: openebs.io
|
||||
# version name to use for REST API: /apis/<group>/<version>
|
||||
version: v1alpha1
|
||||
# either Namespaced or Cluster
|
||||
scope: Cluster
|
||||
names:
|
||||
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
|
||||
plural: storagepoolclaims
|
||||
# singular name to be used as an alias on the CLI and for display
|
||||
singular: storagepoolclaim
|
||||
# kind is normally the CamelCased singular type. Your resource manifests use this.
|
||||
kind: StoragePoolClaim
|
||||
# shortNames allow shorter string to match your resource on the CLI
|
||||
shortNames:
|
||||
- spc
|
||||
@@ -0,0 +1,57 @@
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ template "openebs.fullname" . }}-apiserver
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
component: apiserver
|
||||
spec:
|
||||
replicas: {{ .Values.apiserver.replicas }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
component: apiserver
|
||||
spec:
|
||||
serviceAccountName: {{ template "openebs.serviceAccountName". }}
|
||||
containers:
|
||||
- name: {{ template "openebs.name" . }}-apiserver
|
||||
image: "{{ .Values.apiserver.image }}:{{ .Values.apiserver.imageTag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.apiserver.ports.internalPort }}
|
||||
env:
|
||||
# OPENEBS_IO_KUBE_CONFIG enables maya api service to connect to K8s
|
||||
# based on this config. This is ignored if empty.
|
||||
# This is supported for maya api server version 0.5.2 onwards
|
||||
#- name: OPENEBS_IO_KUBE_CONFIG
|
||||
# value: "/home/ubuntu/.kube/config"
|
||||
# OPENEBS_IO_K8S_MASTER enables maya api service to connect to K8s
|
||||
# based on this address. This is ignored if empty.
|
||||
# This is supported for maya api server version 0.5.2 onwards
|
||||
#- name: OPENEBS_IO_K8S_MASTER
|
||||
# value: "http://172.28.128.3:8080"
|
||||
- name: OPENEBS_IO_JIVA_CONTROLLER_IMAGE
|
||||
value: "{{ .Values.jiva.image }}:{{ .Values.jiva.imageTag }}"
|
||||
- name: OPENEBS_IO_JIVA_REPLICA_IMAGE
|
||||
value: "{{ .Values.jiva.image }}:{{ .Values.jiva.imageTag }}"
|
||||
- name: OPENEBS_IO_VOLUME_MONITOR_IMAGE
|
||||
value: "{{ .Values.policies.monitoring.image }}:{{ .Values.policies.monitoring.imageTag }}"
|
||||
- name: OPENEBS_IO_JIVA_REPLICA_COUNT
|
||||
value: "{{ .Values.jiva.replicas }}"
|
||||
{{- if .Values.apiserver.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{ toYaml .Values.apiserver.nodeSelector | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.apiserver.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.apiserver.tolerations | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.apiserver.affinity }}
|
||||
affinity:
|
||||
{{ toYaml .Values.apiserver.affinity | indent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,69 @@
|
||||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ template "openebs.fullname" . }}-provisioner
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
component: provisioner
|
||||
spec:
|
||||
replicas: {{ .Values.provisioner.replicas }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
component: provisioner
|
||||
spec:
|
||||
serviceAccountName: {{ template "openebs.serviceAccountName". }}
|
||||
containers:
|
||||
- name: {{ template "openebs.name" . }}-provisioner
|
||||
image: "{{ .Values.provisioner.image }}:{{ .Values.provisioner.imageTag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
env:
|
||||
# OPENEBS_IO_K8S_MASTER enables openebs provisioner to connect to K8s
|
||||
# based on this address. This is ignored if empty.
|
||||
# This is supported for openebs provisioner version 0.5.2 onwards
|
||||
#- name: OPENEBS_IO_K8S_MASTER
|
||||
# value: "http://10.128.0.12:8080"
|
||||
# OPENEBS_IO_KUBE_CONFIG enables openebs provisioner to connect to K8s
|
||||
# based on this config. This is ignored if empty.
|
||||
# This is supported for openebs provisioner version 0.5.2 onwards
|
||||
#- name: OPENEBS_IO_KUBE_CONFIG
|
||||
# value: "/home/ubuntu/.kube/config"
|
||||
# OPENEBS_NAMESPACE is the namespace that this provisioner will
|
||||
# lookup to find maya api service
|
||||
- name: OPENEBS_NAMESPACE
|
||||
value: "{{ .Release.Namespace }}"
|
||||
- name: NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
# OPENEBS_MAYA_SERVICE_NAME provides the maya-apiserver K8s service name,
|
||||
# that provisioner should forward the volume creaet/delete requests.
|
||||
# If not present, "maya-apiserver-service" will be used for lookup.
|
||||
# This is supported for openebs provisioner version 0.5.3-RC1 onwards
|
||||
- name: OPENEBS_MAYA_SERVICE_NAME
|
||||
value: "{{ template "openebs.fullname" . }}-apiservice"
|
||||
# The following values will be set as annotations to the PV object.
|
||||
# Refer : https://github.com/openebs/external-storage/pull/15
|
||||
#- name: OPENEBS_MONITOR_URL
|
||||
# value: "{{ .Values.provisioner.monitorUrl }}"
|
||||
#- name: OPENEBS_MONITOR_VOLKEY
|
||||
# value: "{{ .Values.provisioner.monitorVolumeKey }}"
|
||||
#- name: MAYA_PORTAL_URL
|
||||
# value: "{{ .Values.provisioner.mayaPortalUrl }}"
|
||||
{{- if .Values.provisioner.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{ toYaml .Values.provisioner.nodeSelector | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.provisioner.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.provisioner.tolerations | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.provisioner.affinity }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.provisioner.affinity | indent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,20 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "openebs.fullname" . }}-apiservice
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
ports:
|
||||
- name: api
|
||||
port: {{ .Values.apiserver.ports.externalPort }}
|
||||
targetPort: {{ .Values.apiserver.ports.internalPort }}
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: {{ template "openebs.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
component: apiserver
|
||||
sessionAffinity: None
|
||||
@@ -0,0 +1,11 @@
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ template "openebs.serviceAccountName". }}
|
||||
labels:
|
||||
app: {{ template "openebs.name" . }}
|
||||
chart: {{ template "openebs.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Default values for openebs.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
rbac:
|
||||
# Specifies whether RBAC resources should be created
|
||||
create: true
|
||||
|
||||
serviceAccount:
|
||||
create: true
|
||||
name:
|
||||
|
||||
image:
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
apiserver:
|
||||
image: "openebs/m-apiserver"
|
||||
imageTag: "0.5.3"
|
||||
replicas: 1
|
||||
ports:
|
||||
externalPort: 5656
|
||||
internalPort: 5656
|
||||
nodeSelector: {}
|
||||
tolerations: {}
|
||||
affinity: {}
|
||||
|
||||
provisioner:
|
||||
image: "openebs/openebs-k8s-provisioner"
|
||||
imageTag: "0.5.3"
|
||||
replicas: 1
|
||||
nodeSelector: {}
|
||||
tolerations: {}
|
||||
affinity: {}
|
||||
|
||||
jiva:
|
||||
image: "openebs/jiva"
|
||||
imageTag: "0.5.3"
|
||||
replicas: 3
|
||||
|
||||
policies:
|
||||
monitoring:
|
||||
enabled: true
|
||||
image: "openebs/m-exporter"
|
||||
imageTag: "0.5.3"
|
||||
Reference in New Issue
Block a user