Commit 5c05180a authored by Javier Velázquez's avatar Javier Velázquez
Browse files

Merge branch 'feat/19-helm-chart-for-nsc-component' into 'develop'

Resolve "Helm Chart for NSC component"

See merge request !40
parents 3434f4ee ec9860fb
Loading
Loading
Loading
Loading
Loading
+51 −4
Original line number Diff line number Diff line
@@ -165,19 +165,66 @@ In the `src/config/.env.example` file, several constants can be adjusted to cust

## Usage

To use the NSC, just build the image an run it in a container following these steps:
To use the NSC, just build the image and run it in a container following these steps:

1. **Deploy**
    ```
    - Deploy as a local Docker container:
      ```bash
      ./deploy.sh
      ```
    - Deploy to Kubernetes using Helm:
      ```bash
      ./deploy.sh --helm
      ```

2. **Send Slice Requests**:

    Send slice requests via **API** (/nsc) or **WebUI** (/webui)
    Send slice requests via **API** (`/nsc`) or **WebUI** (`/webui`).

### Kubernetes Deployment with Helm

You can deploy the Network Slice Controller (NSC) to a Kubernetes cluster using the provided Helm chart.

#### Prerequisites
- A Kubernetes cluster (e.g., Minikube, Kind, or a remote cluster)
- [Helm v3](https://helm.sh/docs/intro/install/) installed
- Docker image built and loaded into the cluster or registered in a registry.

#### Installation

1. **Deploy using the Deployment Script (Recommended)**:
    ```bash
    ./deploy.sh --helm
    ```

2. **Alternatively, deploy manually**:
    ```bash
    # Build Docker Image
    docker build -t nsc:latest .
    
    # Install with default values
    helm install nsc ./helm/nsc
    
    # Or override configuration variables on install
    helm install nsc ./helm/nsc --set config.dummyMode=true --set secretConfig.apiPassword=mysecurepassword
    ```


#### Configuration
You can customize the deployment by modifying the [values.yaml](file:///c:/Users/id03125/OneDrive%20-%20Telefonica/Trabajo/Network%20slicing/Network%20Slice%20Controller/nsc/helm/nsc/values.yaml) file or by using the `--set` option on the CLI. Key variables include:
- `service.port`: Port to expose the NSC (default: `8085`).
- `config.*`: Application configuration variables matching the parameters in `.env` (e.g., `config.loggingLevel`, `config.tfsIp`, `config.dummyMode`).
- `secretConfig.apiUsername` and `secretConfig.apiPassword`: Basic auth credentials for the API.

#### Uninstallation
To remove the deployed chart:
    ```bash
    helm uninstall nsc
    ```

## Available branches and releases


[![Latest Release](https://labs.etsi.org/rep/tfs/nsc/-/badges/release.svg)](https://labs.etsi.org/rep/tfs/nsc/-/releases)

- The branch `main` ([![pipeline status](https://labs.etsi.org/rep/tfs/nsc/badges/main/pipeline.svg)](https://labs.etsi.org/rep/tfs/nsc/-/commits/main) [![coverage report](https://labs.etsi.org/rep/tfs/nsc/badges/main/coverage.svg)](https://labs.etsi.org/rep/tfs/nsc/-/commits/main)), points always to the latest stable version of the TeraFlowSDN Network Slice Controller (NSC).
+2 −1
Original line number Diff line number Diff line
@@ -34,7 +34,8 @@ from src.database.alert_db import init_db as init_alert
# /nsc       → Swagger UI
# /swaggerui → Swagger UI static assets (flask-restx)
# /swagger   → swagger.json spec file (flask-restx)
UNAUTHENTICATED_PREFIXES = ("/nsc", "/swaggerui", "/swagger")
# /webui     → WebUI login page
UNAUTHENTICATED_PREFIXES = ("/nsc", "/swaggerui", "/swagger", "/webui")


def _unauthorized_response():
+118 −8
Original line number Diff line number Diff line
@@ -19,6 +19,46 @@
# Container name
CONTAINER_NAME=nsc

# Default deployment mode is Docker container
DEPLOY_MODE="docker"

# Help message
show_help() {
    echo "Usage: ./deploy.sh [OPTIONS]"
    echo "Options:"
    echo "  --helm, -k, --kubernetes    Deploy using Helm on Kubernetes"
    echo "  -h, --help                  Show this help message"
}

# Helper to read values from .env with fallback to .env.example
get_env_val() {
    local key=$1
    local default=$2
    local val=""

    # 1. Try to read from root .env
    if [ -f .env ]; then
        val=$(grep "^${key}=" .env | cut -d '=' -f2- | tr -d '\r')
    fi

    # 2. If not found, try to read from src/config/.env.example
    if [ -z "$val" ] && [ -f src/config/.env.example ]; then
        val=$(grep "^${key}=" src/config/.env.example | cut -d '=' -f2- | tr -d '\r')
    fi

    # 3. Return the value or the hardcoded default
    echo "${val:-$default}"
}

# Parse arguments
while [[ "$#" -gt 0 ]]; do
    case $1 in
        --helm|-k|--kubernetes) DEPLOY_MODE="helm"; shift ;;
        -h|--help) show_help; exit 0 ;;
        *) echo "Unknown parameter: $1"; show_help; exit 1 ;;
    esac
done

# Verify if docker is active
if ! docker info > /dev/null 2>&1; then
    echo "Error: Docker not running. Please, restart Docker service and try again."
@@ -52,14 +92,84 @@ else
    cp src/config/.env.example .env
fi

# Read NSC_PORT from .env
NSC_PORT=$(grep '^NSC_PORT=' .env | cut -d '=' -f2)
# Read all variables from .env
NSC_PORT=$(get_env_val "NSC_PORT" "8085")
LOGGING_LEVEL=$(get_env_val "LOGGING_LEVEL" "INFO")
DUMP_TEMPLATES=$(get_env_val "DUMP_TEMPLATES" "false")
NRP_ENABLED=$(get_env_val "NRP_ENABLED" "false")
PLANNER_ENABLED=$(get_env_val "PLANNER_ENABLED" "false")
PLANNER_TYPE=$(get_env_val "PLANNER_TYPE" "ENERGY")
PCE_EXTERNAL=$(get_env_val "PCE_EXTERNAL" "false")
HRAT_IP=$(get_env_val "HRAT_IP" "10.0.0.1")
E2E_OPTICAL_IP=$(get_env_val "E2E_OPTICAL_IP" "127.0.0.1")
SUBSCRIBE_ALERTS=$(get_env_val "SUBSCRIBE_ALERTS" "false")
SUBSCRIBE_ALERTS_URL=$(get_env_val "SUBSCRIBE_ALERTS_URL" "")
DUMMY_MODE=$(get_env_val "DUMMY_MODE" "true")
TFS_IP=$(get_env_val "TFS_IP" "127.0.0.1")
UPLOAD_TYPE=$(get_env_val "UPLOAD_TYPE" "WEBUI")
TFS_L2VPN_SUPPORT=$(get_env_val "TFS_L2VPN_SUPPORT" "false")
IXIA_IP=$(get_env_val "IXIA_IP" "127.0.0.1")
TFS_E2E_IP=$(get_env_val "TFS_E2E_IP" "127.0.0.1")
WEBUI_DEPLOY=$(get_env_val "WEBUI_DEPLOY" "false")
RESTCONF_IP=$(get_env_val "RESTCONF_IP" "127.0.0.1")
SDN_CONTROLLER_TYPE=$(get_env_val "SDN_CONTROLLER_TYPE" "TFS")
DATAPLANE_SUPPORT=$(get_env_val "DATAPLANE_SUPPORT" "FRR")
SDN_SUBSCRIPTION_PERIOD=$(get_env_val "SDN_SUBSCRIPTION_PERIOD" "10")
API_USERNAME=$(get_env_val "API_USERNAME" "admin")
API_PASSWORD=$(get_env_val "API_PASSWORD" "admin")

# Generate a unique tag for local Kubernetes deployment to avoid containerd cache issues
TAG="latest"
if [ "$DEPLOY_MODE" = "helm" ]; then
    TAG="dev-$(date +%s)"
fi

# Docker build
echo "Building docker image..."
docker build -t nsc .
echo "Building docker image with tag nsc:$TAG..."
docker build -t nsc:$TAG -t nsc:latest .

if [ "$DEPLOY_MODE" = "helm" ]; then
    # Verify if helm is installed
    if ! command -v helm &> /dev/null; then
        echo "Error: helm command not found. Please install Helm and try again."
        exit 1
    fi

    echo "Deploying to Kubernetes using Helm..."
    helm upgrade --install nsc ./helm/nsc \
      --set image.repository=nsc \
      --set image.tag=$TAG \
      --set image.pullPolicy=IfNotPresent \
      --set service.type=LoadBalancer \
      --set service.port=$NSC_PORT \
      --set config.loggingLevel=$LOGGING_LEVEL \
      --set config.dumpTemplates=$DUMP_TEMPLATES \
      --set config.nrpEnabled=$NRP_ENABLED \
      --set config.plannerEnabled=$PLANNER_ENABLED \
      --set config.plannerType=$PLANNER_TYPE \
      --set config.pceExternal=$PCE_EXTERNAL \
      --set config.hratIp=$HRAT_IP \
      --set config.e2eOpticalIp=$E2E_OPTICAL_IP \
      --set config.subscribeAlerts=$SUBSCRIBE_ALERTS \
      --set config.subscribeAlertsUrl=$SUBSCRIBE_ALERTS_URL \
      --set config.dummyMode=$DUMMY_MODE \
      --set config.tfsIp=$TFS_IP \
      --set config.uploadType=$UPLOAD_TYPE \
      --set config.tfsL2vpnSupport=$TFS_L2VPN_SUPPORT \
      --set config.ixiaIp=$IXIA_IP \
      --set config.tfsE2eIp=$TFS_E2E_IP \
      --set config.webuiDeploy=$WEBUI_DEPLOY \
      --set config.restconfIp=$RESTCONF_IP \
      --set config.sdnControllerType=$SDN_CONTROLLER_TYPE \
      --set config.dataplaneSupport=$DATAPLANE_SUPPORT \
      --set config.sdnSubscriptionPeriod=$SDN_SUBSCRIPTION_PERIOD \
      --set secretConfig.apiUsername=$API_USERNAME \
      --set secretConfig.apiPassword=$API_PASSWORD
    echo "---READY (Kubernetes/Helm)---"
else
    # Executing nsc
    echo "Running nsc on port $NSC_PORT..."
    docker run -d --env-file .env -p $NSC_PORT:$NSC_PORT --name $CONTAINER_NAME $CONTAINER_NAME
echo "---READY---"
    echo "---READY (Docker)---"
fi

helm/nsc/Chart.yaml

0 → 100644
+6 −0
Original line number Diff line number Diff line
apiVersion: v2
name: nsc
description: A Helm chart for Kubernetes deployment of the Network Slice Controller (NSC)
type: application
version: 0.1.0
appVersion: "1.0.0"
+62 −0
Original line number Diff line number Diff line
{{/*
Expand the name of the chart.
*/}}
{{- define "nsc.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 "nsc.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 "nsc.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "nsc.labels" -}}
helm.sh/chart: {{ include "nsc.chart" . }}
{{ include "nsc.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "nsc.selectorLabels" -}}
app.kubernetes.io/name: {{ include "nsc.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

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