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