Features 11017 and 11018: setup of mgmt cluster and git repo

This change incorporates the changes to setup a mgmt cluster for
cloud-native operations in OSM following a GitOps model, which includes
the setup of an internal git repository.

Change-Id: If828d18ad64d852a9a89ec9ba7c2d3a96d281565
Signed-off-by: garciadeblas <gerardo.garciadeblas@telefonica.com>
diff --git a/installers/mgmt-cluster/minio/00-base-config.rc b/installers/mgmt-cluster/minio/00-base-config.rc
new file mode 100644
index 0000000..e4cf1d6
--- /dev/null
+++ b/installers/mgmt-cluster/minio/00-base-config.rc
@@ -0,0 +1,38 @@
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+# Location where credentials should be saved
+export CREDENTIALS_DIR=${CREDENTIALS_DIR:-../../../.credentials}; export CREDENTIALS_DIR=$(readlink -f "${CREDENTIALS_DIR}")
+
+# Minio version
+export MINIO_VERSION="${MINIO_VERSION:-v5.0.11}"
+
+# Minio tenant name
+export MINIO_TENANT_NAME=${MINIO_TENANT_NAME:-minio-osm-tenant}
+
+# Minio tenant capacity
+export MINIO_TENANT_CAPACITY=${MINIO_TENANT_CAPACITY:-10Gi}
+
+# Number of tenant servers
+export MINIO_TENANT_SERVERS=${MINIO_TENANT_SERVERS:-2}
+
+# Number of tenant volumes
+export MINIO_TENANT_VOLUMES=${MINIO_TENANT_VOLUMES:-4}
+
+# Expose with Ingress
+export MINIO_EXPOSE_CONSOLE=true
+export MINIO_EXPOSE_TENANT=true
diff --git a/installers/mgmt-cluster/minio/01-deploy-minio-operator.sh b/installers/mgmt-cluster/minio/01-deploy-minio-operator.sh
new file mode 100755
index 0000000..e87162b
--- /dev/null
+++ b/installers/mgmt-cluster/minio/01-deploy-minio-operator.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+set -e
+
+export HERE=$(dirname "$(readlink --canonicalize "$BASH_SOURCE")")
+source "${HERE}/library/functions.sh"
+source "${HERE}/library/trap.sh"
+
+############################################
+# Main script starts here
+############################################
+
+m "\nDeploying Minio Operator..."
+
+# Deploy Minio Operator
+MINIO_VERSION="${MINIO_VERSION:-v5.0.11}"
+TIMEOUT=120 # By default is 27. Since sometimes connection may be slow, here we allow more time
+kustomize build "github.com/minio/operator/resources/?timeout=${TIMEOUT}&ref=${MINIO_VERSION}" | \
+    # (optional) To allow deployments over single-node clusters
+    yq 'del(.spec.template.spec.affinity)' | \
+    # Deploy
+    kubectl apply -f -
+
+# Wait until completion
+kubectl rollout status deploy/minio-operator --namespace=minio-operator --watch --timeout=1h
diff --git a/installers/mgmt-cluster/minio/02-create-minio-tenant.sh b/installers/mgmt-cluster/minio/02-create-minio-tenant.sh
new file mode 100755
index 0000000..fa21b8c
--- /dev/null
+++ b/installers/mgmt-cluster/minio/02-create-minio-tenant.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+set -e
+
+export HERE=$(dirname "$(readlink --canonicalize "$BASH_SOURCE")")
+source "${HERE}/library/functions.sh"
+source "${HERE}/library/trap.sh"
+
+############################################
+# Main script starts here
+############################################
+
+# In case no arguments are passed, takes the value of the corresponding environment variables
+MINIO_TENANT_NAME=${1:-${MINIO_TENANT_NAME}}
+MINIO_TENANT_CAPACITY=${2:-${MINIO_TENANT_CAPACITY}}
+
+# Adjusts tenant sizes
+export MINIO_TENANT_SERVERS=${MINIO_TENANT_SERVERS:-4}
+export MINIO_TENANT_VOLUMES=${MINIO_TENANT_VOLUMES:-8}
+
+
+m "\nDeploying ${MINIO_TENANT_NAME} tenant..."
+
+# Create Minio tenant
+kubectl create ns ${MINIO_TENANT_NAME}
+OPTIONS=""
+# OPTIONS="--storage-class default"
+kubectl minio tenant create                     \
+    ${MINIO_TENANT_NAME}                        \
+    --servers          ${MINIO_TENANT_SERVERS}  \
+    --volumes          ${MINIO_TENANT_VOLUMES}  \
+    --capacity         ${MINIO_TENANT_CAPACITY} \
+    --namespace        ${MINIO_TENANT_NAME}     \
+    ${OPTIONS}                                  \
+    --output | \
+    # Fix malformed manifest with wrong fields
+    yq 'del(.spec.pools[0].volumeClaimTemplate.metadata.creationTimestamp)' | \
+    kubectl apply -f -
+
+# Wait until completion
+echo "Waiting for tenant's statefulset to be ready..."
+sleep 30    # To allow the statefulset object to exist
+kubectl rollout status sts/minio-osm-tenant-ss-0 --namespace=${MINIO_TENANT_NAME} --watch --timeout=1h
diff --git a/installers/mgmt-cluster/minio/03-deploy-ingress-for-minio.sh b/installers/mgmt-cluster/minio/03-deploy-ingress-for-minio.sh
new file mode 100755
index 0000000..5f2824e
--- /dev/null
+++ b/installers/mgmt-cluster/minio/03-deploy-ingress-for-minio.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+set -e
+
+export HERE=$(dirname "$(readlink --canonicalize "$BASH_SOURCE")")
+source "${HERE}/library/functions.sh"
+source "${HERE}/library/trap.sh"
+
+############################################
+# Main script starts here
+############################################
+
+# If there is no Ingress Controller, returns
+if [[ -z $(kubectl get svc/ingress-nginx-controller -n ingress-nginx 2> /dev/null) ]]
+then
+    echo "No Ingress controller installed. Exiting"
+    exit 1
+fi
+
+# Retrieve ports
+export MINIO_CONSOLE_HTTP_PORT=$(kubectl get svc/console -n minio-operator -o jsonpath='{.spec.ports[?(.name=="http")].port}')
+export MINIO_CONSOLE_HTTPS_PORT=$(kubectl get svc/console -n minio-operator -o jsonpath='{.spec.ports[?(.name=="https")].port}')
+export MINIO_TENANT_HTTPS_PORT=$(kubectl get svc/minio -n ${MINIO_TENANT_NAME} -o jsonpath='{.spec.ports[?(.name=="https-minio")].port}')
+
+# Determine Ingress host names
+INGRESS_IP=$(kubectl get svc/ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
+export MINIO_INGRESS_CONSOLE_HOST="console.s3.${INGRESS_IP}.nip.io"
+export MINIO_INGRESS_TENANT_HOST="${MINIO_TENANT_NAME}.s3.${INGRESS_IP}.nip.io"
+
+# Determine locations of TLS certificates for tenant's endpoint, if applicable
+export MINIO_TENANT_TLS_KEY="${CREDENTIALS_DIR}/tls.${MINIO_TENANT_NAME}.key"
+export MINIO_TENANT_TLS_CERT="${CREDENTIALS_DIR}/tls.${MINIO_TENANT_NAME}.cert"
+
+# If applicable, deploy Ingress to access Minio Console from outside
+if [[ "${MINIO_EXPOSE_CONSOLE}" == "true" ]]
+then
+    m "\nDeploying Ingress for Console..."
+    envsubst < ingress-manifests/console/ingress-console.yaml | \
+        kubectl apply -f -
+fi
+
+# If applicable, deploy Ingress to access the Minio Tenant from outside
+if [[ "${MINIO_EXPOSE_TENANT}" == "true" ]]
+then
+    m "\nDeploying Ingress for ${MINIO_TENANT_NAME} tenant..."
+
+    # Create self-signed certificate (comment if using pre-created certificate)
+    openssl req -x509 \
+        -nodes \
+        -days 365 \
+        -newkey rsa:2048 \
+        -keyout "${MINIO_TENANT_TLS_KEY}" \
+        -out "${MINIO_TENANT_TLS_CERT}" \
+        -subj "/CN=${MINIO_INGRESS_TENANT_HOST}/O=${MINIO_INGRESS_TENANT_HOST}" \
+        -addext "subjectAltName = DNS:${MINIO_INGRESS_TENANT_HOST}"
+
+    kubectl create secret tls nginx-tls \
+        --key "${MINIO_TENANT_TLS_KEY}" \
+        --cert "${MINIO_TENANT_TLS_CERT}" \
+        -n ${MINIO_TENANT_NAME}
+
+    envsubst < ingress-manifests/tenant/ingress-tenant.yaml | \
+        kubectl apply -f -
+
+    echo "${MINIO_TENANT_NAME} tenant exposed at https://${MINIO_INGRESS_TENANT_HOST}"
+fi
diff --git a/installers/mgmt-cluster/minio/04-get-minio-connection-info.rc b/installers/mgmt-cluster/minio/04-get-minio-connection-info.rc
new file mode 100644
index 0000000..d02e5af
--- /dev/null
+++ b/installers/mgmt-cluster/minio/04-get-minio-connection-info.rc
@@ -0,0 +1,62 @@
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+# Retrieves Minio connection info data
+
+# Internal services and ports
+export MINIO_INTERNAL_CONSOLE_HOST=console.minio-operator
+export MINIO_INTERNAL_TENANT_HOST=minio.${MINIO_TENANT_NAME}
+export MINIO_CONSOLE_HTTP_PORT=$(kubectl get svc/console -n minio-operator -o jsonpath='{.spec.ports[?(.name=="http")].port}')
+export MINIO_CONSOLE_HTTPS_PORT=$(kubectl get svc/console -n minio-operator -o jsonpath='{.spec.ports[?(.name=="https")].port}')
+export MINIO_TENANT_HTTPS_PORT=$(kubectl get svc/minio -n ${MINIO_TENANT_NAME} -o jsonpath='{.spec.ports[?(.name=="https-minio")].port}')
+# NOTE: There is no HTTP port for the Minio Tenant. For HTTP-like accesses, use the `--insecure` flag in Minio client.
+
+# Final Minio's Console HTTP service
+## In case it is behind an Ingress
+if [[ -n $(kubectl get ingress/minio-console-ingress -n minio-operator 2> /dev/null) ]]
+then
+    # Retrieves the external host name
+    INGRESS_IP=$(kubectl get svc/ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
+    export MINIO_INGRESS_CONSOLE_HOST="console.s3.${INGRESS_IP}.nip.io"
+
+    # Uses the external host name as the default console endpoint
+    export MINIO_CONSOLE_HOST=${MINIO_INGRESS_CONSOLE_HOST}
+## Otherwise just uses the internal service name
+else
+    export MINIO_CONSOLE_HOST=${MINIO_INTERNAL_CONSOLE_HOST}
+fi
+export MINIO_CONSOLE_URL="http://${MINIO_CONSOLE_HOST}"
+
+# Final Minio's Tenant HTTPS service
+## In case it is behind an Ingress
+if [[ -n $(kubectl get ingress/minio-tenant-ingress -n ${MINIO_TENANT_NAME} 2> /dev/null) ]]
+then
+    # Retrieves the external host name
+    INGRESS_IP=$(kubectl get svc/ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
+    export MINIO_INGRESS_TENANT_HOST="${MINIO_TENANT_NAME}.s3.${INGRESS_IP}.nip.io"
+
+    # Uses the external host name as the default console endpoint
+    export MINIO_TENANT_HOST=${MINIO_INGRESS_TENANT_HOST}
+## Otherwise just uses the internal service name
+else
+    export MINIO_TENANT_HOST=${MINIO_INTERNAL_TENANT_HOST}
+fi
+export MINIO_TENANT_URL="https://${MINIO_TENANT_HOST}"
+
+# Determine locations of TLS certificates for tenant's endpoint, if applicable
+export MINIO_TENANT_TLS_KEY="${CREDENTIALS_DIR}/tls.${MINIO_TENANT_NAME}.key"
+export MINIO_TENANT_TLS_CERT="${CREDENTIALS_DIR}/tls.${MINIO_TENANT_NAME}.cert"
diff --git a/installers/mgmt-cluster/minio/05-export-connection-info.sh b/installers/mgmt-cluster/minio/05-export-connection-info.sh
new file mode 100755
index 0000000..9524106
--- /dev/null
+++ b/installers/mgmt-cluster/minio/05-export-connection-info.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+set -e
+
+export HERE=$(dirname "$(readlink --canonicalize "$BASH_SOURCE")")
+source "${HERE}/library/functions.sh"
+source "${HERE}/library/trap.sh"
+
+############################################
+# Main script starts here
+############################################
+
+# In case no argument is passed, takes the value of the environment variable
+MINIO_TENANT_NAME=${1:-${MINIO_TENANT_NAME}}
+
+m "\nSaving Minio enviroment to credentials folder..."
+
+# Loads credentials into environment variables
+export MINIO_SA_TOKEN=$(kubectl -n minio-operator get secret console-sa-secret -o jsonpath="{.data.token}" | base64 -d)
+export MINIO_OSM_USERNAME=$(kubectl get secret ${MINIO_TENANT_NAME}-user-1 -n ${MINIO_TENANT_NAME} -o jsonpath='{.data.CONSOLE_ACCESS_KEY}' | base64 -d)
+export MINIO_OSM_PASSWORD=$(kubectl get secret ${MINIO_TENANT_NAME}-user-1 -n ${MINIO_TENANT_NAME} -o jsonpath='{.data.CONSOLE_SECRET_KEY}' | base64 -d)
+
+# Grants that all environment variables are defined
+export MINIO_INGRESS_CONSOLE_HOST=${MINIO_INGRESS_CONSOLE_HOST:-""}
+export MINIO_INGRESS_TENANT_HOST=${MINIO_INGRESS_TENANT_HOST:-""}
+
+# Saves locally to local environment at credentials folder
+cat << EOF > "${CREDENTIALS_DIR}/minio_environment.rc"
+# Minio credentials
+export MINIO_SA_TOKEN=${MINIO_SA_TOKEN}
+export MINIO_OSM_USERNAME=${MINIO_OSM_USERNAME}
+export MINIO_OSM_PASSWORD='${MINIO_OSM_PASSWORD}'
+
+# Minio Console endpoint(s)
+export MINIO_CONSOLE_URL=${MINIO_CONSOLE_URL}
+export MINIO_CONSOLE_HOST=${MINIO_CONSOLE_HOST}
+export MINIO_INTERNAL_CONSOLE_HOST=${MINIO_INTERNAL_CONSOLE_HOST}
+export MINIO_INGRESS_CONSOLE_HOST=${MINIO_INGRESS_CONSOLE_HOST}
+export MINIO_CONSOLE_HTTP_PORT=${MINIO_CONSOLE_HTTP_PORT}
+export MINIO_CONSOLE_HTTPS_PORT=${MINIO_CONSOLE_HTTPS_PORT}
+
+# Minio tenant endpoint(s)
+export MINIO_TENANT_URL=${MINIO_TENANT_URL}
+export MINIO_TENANT_HOST=${MINIO_TENANT_HOST}
+export MINIO_INTERNAL_TENANT_HOST=${MINIO_INTERNAL_TENANT_HOST}
+export MINIO_INGRESS_TENANT_HOST=${MINIO_INGRESS_TENANT_HOST}
+export MINIO_TENANT_HTTPS_PORT=${MINIO_TENANT_HTTPS_PORT}
+
+# Location of certificate and key for Minio's tenant enpoint
+export MINIO_TENANT_TLS_CERT='${MINIO_TENANT_TLS_CERT}'
+export MINIO_TENANT_TLS_KEY='${MINIO_TENANT_TLS_KEY}'
+EOF
diff --git a/installers/mgmt-cluster/minio/ALL-IN-ONE-Minio-install.sh b/installers/mgmt-cluster/minio/ALL-IN-ONE-Minio-install.sh
new file mode 100755
index 0000000..c3f586e
--- /dev/null
+++ b/installers/mgmt-cluster/minio/ALL-IN-ONE-Minio-install.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+set -e
+
+export HERE=$(dirname "$(readlink --canonicalize "$BASH_SOURCE")")
+source "${HERE}/library/functions.sh"
+source "${HERE}/library/trap.sh"
+
+
+############################################
+# Main script starts here
+############################################
+
+# Complete environment variables with sensible defaults, if needed
+source 00-base-config.rc
+
+# Install Minio operator
+./01-deploy-minio-operator.sh
+
+# Create Minio tenant
+./02-create-minio-tenant.sh
+
+# If applicable, deploy Ingress to provide external access
+./03-deploy-ingress-for-minio.sh
+
+# Retrieve URLs and credentials
+source 04-get-minio-connection-info.rc
+
+# Save credentials
+./05-export-connection-info.sh
diff --git a/installers/mgmt-cluster/minio/README.md b/installers/mgmt-cluster/minio/README.md
new file mode 100644
index 0000000..d32a26e
--- /dev/null
+++ b/installers/mgmt-cluster/minio/README.md
@@ -0,0 +1,215 @@
+<!--
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+implied.
+See the License for the specific language governing permissions and
+limitations under the License
+-->
+# How to install Minio
+
+- [How to install Minio](#how-to-install-minio)
+  - [0. Pre-requirements](#0-pre-requirements)
+  - [1. Installation](#1-installation)
+    - [1.1 Quickstart (recommended)](#11-quickstart-recommended)
+    - [1.2 Detailed procedure (useful for regenerating manifests with newer versions)](#12-detailed-procedure-useful-for-regenerating-manifests-with-newer-versions)
+    - [1.2.1 Minio Operator](#121-minio-operator)
+    - [2.1.2 Create a Minio Tenant](#212-create-a-minio-tenant)
+  - [3. Tests](#3-tests)
+    - [3.1 Access using Ingress (recommended)](#31-access-using-ingress-recommended)
+    - [3.2 Access using a port forward](#32-access-using-a-port-forward)
+    - [3.3 Tests from a container into the K8s cluster](#33-tests-from-a-container-into-the-k8s-cluster)
+  - [ANNEX A: How to set-up the local Minio CLI tools](#annex-a-how-to-set-up-the-local-minio-cli-tools)
+
+This procedure is based in the [Minio Operator guide](https://github.com/minio/operator/blob/master/README.md) and the [Guide to deploy a Deploy a MinIO Tenant](https://min.io/docs/minio/kubernetes/upstream/operations/install-deploy-manage/deploy-minio-tenant.html).
+
+## 0. Pre-requirements
+
+- Kubernetes cluster available.
+- Minio's `kubectl` plugin.
+- `mc` (Minio Client) tool installed.
+  - We will assume that the tool is renamed as `minioc` to avoid collisions with a pre-existing installation of the popular _Midnight Commander_.
+  - We will use the tool to validate that the installation has been successful.
+
+## 1. Installation
+
+### 1.1 Quickstart (recommended)
+
+```bash
+./ALL-IN-ONE-Minio-install.sh
+
+# (optional) To retrieve the environment variables
+source 00-base-config.rc
+source "${CREDENTIALS_DIR}/minio_environment.rc"
+```
+
+### 1.2 Detailed procedure (useful for regenerating manifests with newer versions)
+
+### 1.2.1 Minio Operator
+
+```bash
+VERSION=v5.0.11
+TIMEOUT=120 # By default is 27. Since sometimes connection may be slow, here we allow more time.
+kustomize build "github.com/minio/operator/resources/?timeout=${TIMEOUT}&ref=${VERSION}" > minio-operator.yaml
+
+# (optional) To allow deployments over single-node clusters
+yq -i 'del(.spec.template.spec.affinity)' minio-operator.yaml
+
+# Deploy
+kubectl apply -f minio-operator.yaml
+
+# Wait until completion
+kubectl rollout status deploy/minio-operator --namespace=minio-operator --watch --timeout=1h
+```
+
+Save SA token:
+
+```bash
+export MINIO_SA_TOKEN=$(kubectl -n minio-operator  get secret console-sa-secret -o jsonpath="{.data.token}" | base64 -d)
+```
+
+### 2.1.2 Create a Minio Tenant
+
+Deploy a tenant for OSM:
+
+```bash
+MINIO_TENANT_NAME=minio-osm-tenant
+MINIO_TENANT_CAPACITY=10Gi
+kubectl create ns ${MINIO_TENANT_NAME}
+kubectl minio tenant create                     \
+    ${MINIO_TENANT_NAME}                        \
+    --servers          4                        \
+    --volumes          8                        \
+    --capacity         ${MINIO_TENANT_CAPACITY} \
+    --namespace        ${MINIO_TENANT_NAME}     \
+    --storage-class    default                  \
+    --output > ${MINIO_TENANT_NAME}.yaml
+
+# Fix malformed manifest with wrong fields
+yq -i 'del(.spec.pools[0].volumeClaimTemplate.metadata.creationTimestamp)' ${MINIO_TENANT_NAME}.yaml
+
+kubectl apply -f ${MINIO_TENANT_NAME}.yaml
+```
+
+Save credentials:
+
+```bash
+export MINIO_OSM_USERNAME=$(kubectl get secret ${MINIO_TENANT_NAME}-user-1 -n ${MINIO_TENANT_NAME} -o jsonpath='{.data.CONSOLE_ACCESS_KEY}' | base64 -d)
+export MINIO_OSM_PASSWORD=$(kubectl get secret ${MINIO_TENANT_NAME}-user-1 -n ${MINIO_TENANT_NAME} -o jsonpath='{.data.CONSOLE_SECRET_KEY}' | base64 -d)
+```
+
+## 3. Tests
+
+### 3.1 Access using Ingress (recommended)
+
+Get the URL and the JWT token to access the Minio Operator Console with the browser:
+
+```bash
+# Open URL in browser using the JWT as access token
+echo "Console URL: ${MINIO_CONSOLE_URL}"
+echo -e "JWT token:\n${MINIO_SA_TOKEN}"
+```
+
+Then we can also test the tenant:
+
+```bash
+# Add alias to connect to the tenant
+ALIAS=osm
+echo "Minio Tenant URL: ${MINIO_TENANT_URL}"
+minioc alias set ${ALIAS} ${MINIO_TENANT_URL} ${MINIO_OSM_USERNAME} ${MINIO_OSM_PASSWORD} --insecure
+
+# Test
+minioc admin info ${ALIAS} --insecure
+
+# (optional) Delete the alias
+minioc alias remove ${ALIAS}
+```
+
+Note the use of the `--insecure` when the endpoint certificate is self-signed. **This will not be an issue from a container inside the cluster (using the internal DNS name) or when the certificate is signed by a CA**.
+
+### 3.2 Access using a port forward
+
+Access the Minio Operator Console:
+
+```bash
+# See SA Token, so that it can be used as JWT to access the Operator Console
+echo ${MINIO_SA_TOKEN}
+
+# Port forward to access from outside K8s
+kubectl port-forward svc/console -n minio-operator 9090:9090
+
+# Open in browser: http://localhost:9090
+```
+
+The we can test the health of the Minio tenant. First, we need to forward the port:
+
+```bash
+# Port forward to access from outside K8s
+kubectl port-forward svc/minio -n ${MINIO_TENANT_NAME} 4443:443
+```
+
+Then we test the tenant:
+
+```bash
+# Add alias to connect to the tenant
+ALIAS=osm
+MINIO_HOSTNAME=https://localhost:4443
+ACCESS_KEY=${MINIO_OSM_USERNAME}
+SECRET_KEY=${MINIO_OSM_PASSWORD}
+minioc alias set ${ALIAS} ${MINIO_HOSTNAME} ${ACCESS_KEY} ${SECRET_KEY} --insecure
+
+# Test
+minioc admin info ${ALIAS} --insecure
+
+# (optional) Delete the alias
+minioc alias remove ${ALIAS}
+```
+
+Note the use of the `--insecure`, since the endpoint certificate is not valid for a `localhost` endpoint. **This will not be an issue from a container inside the cluster**.
+
+### 3.3 Tests from a container into the K8s cluster
+
+Launch the container:
+
+```bash
+kubectl run -it --rm --image=alpine --env=ACCESS_KEY=${MINIO_OSM_USERNAME} --env=SECRET_KEY=${MINIO_OSM_PASSWORD} -- sh
+```
+
+Into the container:
+
+```bash
+# Install Minio client into the container
+apk add curl
+curl https://dl.min.io/client/mc/release/linux-amd64/mc -o minioc
+chmod +x minioc
+mv minioc /usr/local/bin/
+
+# Add alias to connect to the tenant
+ALIAS=osm
+MINIO_TENANT_NAME=minio-osm-tenant
+MINIO_HOSTNAME=https://minio.${MINIO_TENANT_NAME}
+minioc alias set ${ALIAS} ${MINIO_HOSTNAME} ${ACCESS_KEY} ${SECRET_KEY}
+
+# Test
+minioc admin info ${ALIAS}
+```
+
+## ANNEX A: How to set-up the local Minio CLI tools
+
+```bash
+# Minio kubectl plugin:
+curl https://github.com/minio/operator/releases/download/v5.0.12/kubectl-minio_5.0.12_linux_amd64 -Lo kubectl-minio
+chmod +x kubectl-minio
+sudo mv kubectl-minio /usr/local/bin/
+
+# Minio Client:
+curl https://dl.min.io/client/mc/release/linux-amd64/mc -o minioc
+chmod +x minioc
+sudo mv minioc /usr/local/bin/
+```
diff --git a/installers/mgmt-cluster/minio/ingress-manifests/console/ingress-console.yaml b/installers/mgmt-cluster/minio/ingress-manifests/console/ingress-console.yaml
new file mode 100644
index 0000000..5d3301e
--- /dev/null
+++ b/installers/mgmt-cluster/minio/ingress-manifests/console/ingress-console.yaml
@@ -0,0 +1,35 @@
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: minio-console-ingress
+  namespace: minio-operator
+spec:
+  ingressClassName: nginx
+  rules:
+  - host: ${MINIO_INGRESS_CONSOLE_HOST}
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: console
+            port:
+              number: ${MINIO_CONSOLE_HTTP_PORT}
diff --git a/installers/mgmt-cluster/minio/ingress-manifests/tenant/ingress-tenant.yaml b/installers/mgmt-cluster/minio/ingress-manifests/tenant/ingress-tenant.yaml
new file mode 100644
index 0000000..bd1be7e
--- /dev/null
+++ b/installers/mgmt-cluster/minio/ingress-manifests/tenant/ingress-tenant.yaml
@@ -0,0 +1,45 @@
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: minio-tenant-ingress
+  namespace: ${MINIO_TENANT_NAME}
+  annotations:
+    ## Comment if using a CA signed certificate
+    nginx.ingress.kubernetes.io/proxy-ssl-verify: "off"
+    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
+    nginx.ingress.kubernetes.io/rewrite-target: /
+    nginx.ingress.kubernetes.io/proxy-body-size: "0"
+spec:
+  ingressClassName: nginx
+  tls:
+  - hosts:
+      - ${MINIO_INGRESS_TENANT_HOST}
+    secretName: nginx-tls
+  rules:
+  - host: ${MINIO_INGRESS_TENANT_HOST}
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: minio
+            port:
+              number: ${MINIO_TENANT_HTTPS_PORT}
diff --git a/installers/mgmt-cluster/minio/library/functions.sh b/installers/mgmt-cluster/minio/library/functions.sh
new file mode 100755
index 0000000..638a1d2
--- /dev/null
+++ b/installers/mgmt-cluster/minio/library/functions.sh
@@ -0,0 +1,91 @@
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+BLUE='\033[0;34m'
+CYAN='\033[0;36m'
+RESET='\033[0m'
+
+# Colored messages (blue is the default)
+# Examples:
+#   m "hello world"
+#   m "hello world" "$GREEN"
+function m() {
+  local COLOR=${2:-$BLUE}
+  echo -e "$COLOR$1$RESET"
+}
+
+function copy_function() {
+  local ORIG_FUNC=$(declare -f $1)
+  local NEWNAME_FUNC="$2${ORIG_FUNC#$1}"
+  eval "$NEWNAME_FUNC"
+}
+
+function replace_text() {
+  local FILE=$1
+  local START=$2
+  local END=$3
+  local NEW=$4
+  local T=$(mktemp)
+  head -n $((START-1)) "$FILE" > "$T"
+  echo "$NEW" >> "$T"
+  tail -n +$((END+1)) "$FILE" >> "$T"
+  mv "$T" "$FILE"
+}
+
+function insert_text() {
+  local FILE=$1
+  local START=$2
+  local NEW=$3
+  local T=$(mktemp)
+  head -n $((START-1)) "$FILE" > "$T"
+  echo "$NEW" >> "$T"
+  tail -n +$START "$FILE" >> "$T"
+  mv "$T" "$FILE"
+}
+
+function remove_text() {
+  local FILE=$1
+  local START=$2
+  local END=$3
+  local T=$(mktemp)
+  head -n $((START-1)) "$FILE" > "$T"
+  tail -n +$((END+1)) "$FILE" >> "$T"
+  mv "$T" "$FILE"
+}
+
+function envsubst_cp() {
+  local FROM_FILE=$1
+  local TO_FILE=$2
+  mkdir --parents "$(dirname "$TO_FILE")"
+  cat "$FROM_FILE" | envsubst > "$TO_FILE"
+}
+
+function envsubst_dir() {
+  local FROM_DIR=$1
+  local TO_DIR=$2
+  rm --recursive --force "$TO_DIR"
+  mkdir --parents "$TO_DIR"
+  pushd "$FROM_DIR" > /dev/null
+  local F
+  find . -type f | while read F; do
+    envsubst_cp "$F" "$TO_DIR/$F"
+  done
+  popd > /dev/null
+}
diff --git a/installers/mgmt-cluster/minio/library/trap.sh b/installers/mgmt-cluster/minio/library/trap.sh
new file mode 100755
index 0000000..2a1156d
--- /dev/null
+++ b/installers/mgmt-cluster/minio/library/trap.sh
@@ -0,0 +1,48 @@
+#######################################################################################
+# Copyright ETSI Contributors and Others.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#######################################################################################
+
+function goodbye() {
+  local DURATION=$(date --date=@$(( "$(date +%s)" - "$TRAP_START_TIME" )) --utc +%T)
+  local CODE=$1
+  cd "$TRAP_DIR"
+  if [ "$CODE" == 0 ]; then
+    m "$(realpath --relative-to="$HERE" "$0") succeeded! $DURATION" "$GREEN"
+  elif [ "$CODE" == abort ]; then
+    m "Aborted $(realpath --relative-to="$HERE" "$0")! $DURATION" "$RED"
+  else
+    m "Oh no! $(realpath --relative-to="$HERE" "$0") failed! $DURATION" "$RED"
+  fi
+}
+
+function trap_EXIT() {
+  local ERR=$?
+  goodbye "$ERR"
+  exit "$ERR"
+}
+
+function trap_INT() {
+  goodbye abort
+  trap - EXIT
+  exit 1
+}
+
+TRAP_DIR=$PWD
+TRAP_START_TIME=$(date +%s)
+
+trap trap_INT INT
+
+trap trap_EXIT EXIT