From cea726298b183d16e27d4e43873de5b99e307973 Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Thu, 7 Aug 2025 19:57:11 +0200 Subject: [PATCH] Feature 11073. Enhanced OSM declarative modelling for applications. App as first class citizen. Add ArgoWF templates Change-Id: Icb8b48fc740a82b0a6bc58578a1b3f9a2ced86ed Signed-off-by: garciadeblas --- .../full-app-management-wft.yaml | 586 ++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 installers/flux/templates/sw-catalogs/infra-configs/osm-workflows/templates/wf-templates/canned-operations/full-app-management-wft.yaml diff --git a/installers/flux/templates/sw-catalogs/infra-configs/osm-workflows/templates/wf-templates/canned-operations/full-app-management-wft.yaml b/installers/flux/templates/sw-catalogs/infra-configs/osm-workflows/templates/wf-templates/canned-operations/full-app-management-wft.yaml new file mode 100644 index 00000000..e5ded974 --- /dev/null +++ b/installers/flux/templates/sw-catalogs/infra-configs/osm-workflows/templates/wf-templates/canned-operations/full-app-management-wft.yaml @@ -0,0 +1,586 @@ +####################################################################################### +# 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. +####################################################################################### + +# =========================================================================================== +# OSM Application Management Workflow Template +# =========================================================================================== +# +# PREREQUISITES: +# - PVC containing application model and parameters must exist +# - Required files: app_instance_model.yaml, parameters/clear/environment.yaml, parameters/secret/environment.yaml +# - Git repositories for Fleet and SW-Catalogs must be accessible +# +# USAGE: +# Use the launcher workflows (launcher-app.yaml) or create custom workflows that reference +# this template. Ensure the model_volume_name parameter points to a properly prepared PVC. +# +# For volume preparation utilities, see: scripts/library/osm/utils/workflow-pvc +# +# =========================================================================================== + +apiVersion: argoproj.io/v1alpha1 +kind: WorkflowTemplate +metadata: + name: full-app-management-wft + namespace: osm-workflows +spec: + arguments: + parameters: + # === Core Operation Configuration === + - name: command + description: | + Full command string to execute with the OSM SDK. + Examples: + - "app create $environment": Deploy new application instance + - "app update $environment": Update existing application instance + - "app delete $environment": Remove application instance + This parameter accepts any valid OSM SDK command for maximum flexibility. + + # === Volume-Based Data Sources === + - name: model_volume_name + description: | + Name of the PersistentVolumeClaim containing application models and parameters. + The PVC must contain the following structure: + - /app_instance_model.yaml: Application instantiation model (required) + - /parameters/clear/environment.yaml: Clear text parameters (optional) + Secret parameters are mounted separately via the secret_name parameter. + - name: secret_name + description: | + Name of the Kubernetes secret to mount at /model/parameters/secret/environment.yaml. + This parameter is optional. When provided, the secret will be mounted as a file + containing sensitive configuration parameters for the application. + + # === Git Repository Configuration === + - name: git_fleet_url + - name: fleet_destination_folder + value: "/fleet/fleet-osm" + - name: git_fleet_cred_secret + - name: git_sw_catalogs_url + - name: sw_catalogs_destination_folder + value: "/sw-catalogs/sw-catalogs-osm" + - name: git_sw_catalogs_cred_secret + + # === Target Deployment Configuration === + - name: app_name + - name: profile_name + - name: profile_type + value: "app-profiles" + - name: project_name + value: "osm_admin" + + # === OSM SDK Container Configuration === + - name: osm_sdk_image_repository + value: "ttl.sh/osm-sdk-operations" + description: | + Repository for the OSM SDK container image. Default is the standardized + OSM SDK operations image that provides consistent behavior across workflows. + - name: osm_sdk_image_tag + value: "24h" + description: | + Tag for the OSM SDK container image. Default is '24h' which provides + a stable, time-limited image for workflow execution. + + # === Workflow Execution Control === + - name: debug + value: "false" + description: | + Enable debug mode for detailed workflow execution information. + When set to 'true', additional debug steps will execute to provide: + - Volume mount status and accessibility checks + - Model content analysis and validation + - Repository structure inspection + - Embedded operations testing + Set to 'true' for troubleshooting workflow issues. + - name: dry_run + value: "false" + description: | + Enable dry-run mode to validate operations without making changes. + When set to 'true', the workflow will: + - Perform all validation and preparation steps + - Execute app operations in dry-run mode (no actual changes) + - Skip Git commit and push operations + Use this mode to test workflow configuration and validate models. + + # === Workflow Lifecycle Management === + # TTL strategy for automatic cleanup of completed workflow instances + ttlStrategy: + secondsAfterCompletion: 6000 # 100 minutes - Time to live after workflow completion + secondsAfterSuccess: 6000 # 100 minutes - Time to live after successful execution + secondsAfterFailure: 9000 # 150 minutes - Extended time for failure analysis + + # Main entry point for the workflow template + entrypoint: app-management + + templates: + # === Main Application Management Template === + # This template orchestrates the complete application lifecycle management process + # using a volume-based approach for application models and parameters. + - name: app-management + inputs: + parameters: + # Core operation configuration + - name: command + # Volume-based data sources + - name: model_volume_name + - name: secret_name + # Git repository configuration for Fleet and SW-Catalogs + - name: git_fleet_url + - name: fleet_destination_folder + - name: git_fleet_cred_secret + - name: git_sw_catalogs_url + - name: sw_catalogs_destination_folder + - name: git_sw_catalogs_cred_secret + # Target deployment configuration + - name: app_name + - name: profile_name + - name: profile_type + - name: project_name + # OSM SDK container configuration with standardized defaults + - name: osm_sdk_image_repository + - name: osm_sdk_image_tag + # Workflow execution control flags + - name: debug + - name: dry_run + + steps: + # === PHASE 1: Parameter Validation === + # Validate that all required parameters are provided for volume-based workflow execution + - - name: validate-parameters + inline: + container: + image: alpine:latest + command: [sh, -c] + args: + - | + set -e + echo "=== Volume-Based Workflow Parameter Validation ===" + echo "Validating required parameters for application management..." + + # Validate core volume parameter + if [ -z "{{inputs.parameters.model_volume_name}}" ]; then + echo "ERROR: model_volume_name parameter is required for volume-based workflow" + echo "Please provide a PVC name containing the application model and parameters" + exit 1 + fi + + # Validate Git repository parameters + if [ -z "{{inputs.parameters.git_fleet_url}}" ]; then + echo "ERROR: git_fleet_url parameter is required for Fleet repository access" + exit 1 + fi + + if [ -z "{{inputs.parameters.git_sw_catalogs_url}}" ]; then + echo "ERROR: git_sw_catalogs_url parameter is required for SW-Catalogs repository access" + exit 1 + fi + + # Validate target deployment parameters + if [ -z "{{inputs.parameters.app_name}}" ]; then + echo "ERROR: app_name parameter is required for application identification" + exit 1 + fi + + if [ -z "{{inputs.parameters.profile_name}}" ]; then + echo "ERROR: profile_name parameter is required for deployment profile" + exit 1 + fi + + echo "✓ All required parameters validated successfully" + echo "Configuration Summary:" + echo " Command: {{inputs.parameters.command}}" + echo " Model Volume: {{inputs.parameters.model_volume_name}}" + echo " Secret Name: {{inputs.parameters.secret_name}}" + echo " Application: {{inputs.parameters.app_name}}" + echo " Profile: {{inputs.parameters.profile_name}} ({{inputs.parameters.profile_type}})" + echo " Project: {{inputs.parameters.project_name}}" + echo " OSM SDK: {{inputs.parameters.osm_sdk_image_repository}}:{{inputs.parameters.osm_sdk_image_tag}}" + echo " Debug Mode: {{inputs.parameters.debug}}" + echo " Dry Run: {{inputs.parameters.dry_run}}" + + # === PHASE 2: Volume Preparation === + # Generate temporary volumes for Git repository operations + # These volumes will store cloned Fleet and SW-Catalogs repositories during workflow execution + - - name: generate-fleet-volume-repo + templateRef: + name: k8s-resources-wft + template: generate-volume + arguments: + parameters: + - name: pvc-size + value: '100Mi' # Sufficient space for Fleet repository content + - name: generate-sw-catalogs-volume-repo + templateRef: + name: k8s-resources-wft + template: generate-volume + arguments: + parameters: + - name: pvc-size + value: '100Mi' # Sufficient space for SW-Catalogs repository content + + # === PHASE 3: Git Repository Cloning === + # Clone the required Git repositories for application modeling and deployment + # These repositories provide the templates and target locations for GitOps operations + - - name: clone-fleet + templateRef: + name: git-wft + template: git-clone + arguments: + parameters: + - name: mount_path + value: "/fleet" + - name: repo_url + value: "{{inputs.parameters.git_fleet_url}}" + - name: destination_folder + value: "{{inputs.parameters.fleet_destination_folder}}" + - name: git_cred_secret + value: "{{inputs.parameters.git_fleet_cred_secret}}" + - name: git_volume_name + value: '{{steps.generate-fleet-volume-repo.outputs.parameters.pvc-name}}' + - name: clone-sw-catalogs + templateRef: + name: git-wft + template: git-clone + arguments: + parameters: + - name: mount_path + value: "/sw-catalogs" + - name: repo_url + value: "{{inputs.parameters.git_sw_catalogs_url}}" + - name: destination_folder + value: "{{inputs.parameters.sw_catalogs_destination_folder}}" + - name: git_cred_secret + value: "{{inputs.parameters.git_sw_catalogs_cred_secret}}" + - name: git_volume_name + value: '{{steps.generate-sw-catalogs-volume-repo.outputs.parameters.pvc-name}}' + + # === PHASE 4: Debug Information (Optional) === + # Comprehensive debugging information for volume-based workflow troubleshooting + # Executed only when debug parameter is set to true + - - name: debug-info + when: "{{inputs.parameters.debug}} == true" + inline: + container: + image: "{{inputs.parameters.osm_sdk_image_repository}}:{{inputs.parameters.osm_sdk_image_tag}}" + args: + - "nu" + - "-c" + - | + echo "=== OSM App Modeling Debug Information (Volume-Based) ===" + echo $"Command: {{inputs.parameters.command}}" + echo $"SDK Image: {{inputs.parameters.osm_sdk_image_repository}}:{{inputs.parameters.osm_sdk_image_tag}}" + echo $"Model Volume: {{inputs.parameters.model_volume_name}}" + echo $"Secret Name: {{inputs.parameters.secret_name}}" + echo $"Timestamp: (date now | format date '%Y-%m-%d %H:%M:%S')" + echo "" + + echo "=== Volume Mount Status and Accessibility ===" + echo "Checking volume mount accessibility..." + + # Check model volume mount + echo "Model volume mount status:" + if (ls /model | length) > 0 { + echo "✓ Model volume mounted successfully at /model" + echo $" Files found: (ls /model | length)" + } else { + echo "✗ Model volume mount failed or empty" + } + + # Check fleet volume mount + echo "Fleet volume mount status:" + if (ls /repos/fleet-osm | length) > 0 { + echo "✓ Fleet volume mounted successfully at /repos/fleet-osm" + echo $" Files found: (ls /repos/fleet-osm | length)" + } else { + echo "✗ Fleet volume mount failed or empty" + } + + # Check sw-catalogs volume mount + echo "SW-Catalogs volume mount status:" + if (ls /repos/sw-catalogs-osm | length) > 0 { + echo "✓ SW-Catalogs volume mounted successfully at /repos/sw-catalogs-osm" + echo $" Files found: (ls /repos/sw-catalogs-osm | length)" + } else { + echo "✗ SW-Catalogs volume mount failed or empty" + } + echo "" + + echo "=== Model Volume Contents and Structure ===" + echo "Model volume directory structure:" + try { + ls /model -la | select name type size permissions | table + } catch { + echo "Error accessing model volume contents" + } + echo "" + + echo "=== Required Model Files Validation ===" + # Check app_instance_model.yaml + if ("/model/app_instance_model.yaml" | path exists) { + echo "✓ app_instance_model.yaml found" + try { + let file_size = (ls /model/app_instance_model.yaml | get size | first) + echo $" Size: ($file_size) bytes" + } catch { + echo " Warning: Could not read file size" + } + } else { + echo "✗ app_instance_model.yaml missing" + } + + # Check clear parameters + if ("/model/parameters/clear/environment.yaml" | path exists) { + echo "✓ Clear parameters file found" + try { + let file_size = (ls /model/parameters/clear/environment.yaml | get size | first) + echo $" Size: ($file_size) bytes" + } catch { + echo " Warning: Could not read file size" + } + } else { + echo "ℹ Clear parameters file missing (optional)" + } + + # Check secret parameters + if ("/model/parameters/secret/environment.yaml" | path exists) { + echo "✓ Secret parameters file found" + try { + let file_size = (ls /model/parameters/secret/environment.yaml | get size | first) + echo $" Size: ($file_size) bytes" + } catch { + echo " Warning: Could not read file size" + } + } else { + echo "ℹ Secret parameters file missing (optional)" + } + + echo "=== Model Content Analysis ===" + echo "App Instance Model (first 30 lines):" + try { + open /model/app_instance_model.yaml | lines | first 30 | str join "\n" + } catch { + echo "Error reading app_instance_model.yaml" + } + echo "" + + echo "Clear Parameters Content:" + try { + open /model/parameters/clear/environment.yaml | to yaml + } catch { + echo "Clear parameters not available" + } + echo "" + + echo "Secret Parameters Content (masked for security):" + try { + if ("/model/parameters/secret/environment.yaml" | path exists) { + echo "Secret file exists - content masked for security" + } else { + echo "Secret parameters not available" + } + } catch { + echo "Error checking secret parameters" + } + echo "" + + echo "=== Loaded Model Instance from Volume ===" + try { + $model_instance | to yaml | lines | first 30 | str join "\n" + } catch { + echo "Error loading model instance" + } + echo "" + + echo "=== Environment Parameters from Volume ===" + try { + $environment | to yaml | lines | first 30 | str join "\n" + } catch { + echo "Error loading environment" + } + echo "" + + echo "=== Repository Structure ===" + echo "Fleet repo contents:" + try { + ls /repos/fleet-osm | select name type size | first 10 | table + } catch { + echo "Error accessing fleet repository" + } + echo "" + echo "SW-Catalogs repo contents:" + try { + ls /repos/sw-catalogs-osm | select name type size | first 10 | table + } catch { + echo "Error accessing sw-catalogs repository" + } + echo "" + + echo "=== Embedded Operations Validation ===" + echo "App Operations Library Status:" + try { + help app | lines | first 10 | str join "\n" + } catch { + echo "Error accessing app operations library" + } + echo "" + + echo "=== Dry Run Test ===" + echo "Testing command execution with volume-mounted data..." + try { + echo $"Command to execute: {{inputs.parameters.command}}" + echo "✓ Command validation successful with volume-based data" + } catch { + echo $"✗ Command validation failed: ($in)" + } + echo "" + + echo "=== Volume Permissions Check ===" + echo "Model volume permissions:" + try { + ls -la /model | head -5 | each { |item| echo $" ($item.name): ($item.permissions)" } | str join "\n" + } catch { + echo "Error checking model volume permissions" + } + echo "" + + echo "=== Debug Information Complete ===" + volumeMounts: + - name: model-volume + mountPath: /model + - name: fleet-volume + mountPath: /repos/fleet-osm + subPath: fleet-osm + - name: sw-catalogs-volume + mountPath: /repos/sw-catalogs-osm + subPath: sw-catalogs-osm + # Mount secret volume when secret_name is provided + - name: secret-volume + mountPath: /model/parameters/secret + readOnly: true + volumes: + - name: model-volume + persistentVolumeClaim: + claimName: "{{inputs.parameters.model_volume_name}}" + - name: fleet-volume + persistentVolumeClaim: + claimName: '{{steps.generate-fleet-volume-repo.outputs.parameters.pvc-name}}' + - name: sw-catalogs-volume + persistentVolumeClaim: + claimName: '{{steps.generate-sw-catalogs-volume-repo.outputs.parameters.pvc-name}}' + - name: secret-volume + secret: + secretName: "{{inputs.parameters.secret_name}}" + optional: true + + # === PHASE 5: Application Operations === + # This phase performs the actual create/update/delete operations on the application model + - - name: run-app-operation + when: "{{inputs.parameters.dry_run}} != true" + inline: + container: + image: "{{inputs.parameters.osm_sdk_image_repository}}:{{inputs.parameters.osm_sdk_image_tag}}" + args: ["{{inputs.parameters.command}}"] # Full command string to execute + volumeMounts: + # Mount model volume containing application data + - name: model-volume + mountPath: /model + # Mount Fleet repository for GitOps target + - name: fleet-volume + mountPath: /repos/fleet-osm + subPath: fleet-osm + # Mount SW-Catalogs repository for application templates + - name: sw-catalogs-volume + mountPath: /repos/sw-catalogs-osm + subPath: sw-catalogs-osm + # Mount secret volume when secret_name is provided + - name: secret-volume + mountPath: /model/parameters/secret + readOnly: true + volumes: + - name: model-volume + persistentVolumeClaim: + claimName: "{{inputs.parameters.model_volume_name}}" + - name: fleet-volume + persistentVolumeClaim: + claimName: '{{steps.generate-fleet-volume-repo.outputs.parameters.pvc-name}}' + - name: sw-catalogs-volume + persistentVolumeClaim: + claimName: '{{steps.generate-sw-catalogs-volume-repo.outputs.parameters.pvc-name}}' + - name: secret-volume + secret: + secretName: "{{inputs.parameters.secret_name}}" + optional: true + # Dry-run variant of the app operation for validation without changes + - name: run-app-operation-dry-run + when: "{{inputs.parameters.dry_run}} == true" + inline: + container: + image: "{{inputs.parameters.osm_sdk_image_repository}}:{{inputs.parameters.osm_sdk_image_tag}}" + args: ["{{inputs.parameters.command}} --dry-run"] # Full command string with dry-run flag + volumeMounts: + # Same volume mounts as regular operation for consistency + - name: model-volume + mountPath: /model + - name: fleet-volume + mountPath: /repos/fleet-osm + subPath: fleet-osm + - name: sw-catalogs-volume + mountPath: /repos/sw-catalogs-osm + subPath: sw-catalogs-osm + # Mount secret volume when secret_name is provided + - name: secret-volume + mountPath: /model/parameters/secret + readOnly: true + volumes: + - name: model-volume + persistentVolumeClaim: + claimName: "{{inputs.parameters.model_volume_name}}" + - name: fleet-volume + persistentVolumeClaim: + claimName: '{{steps.generate-fleet-volume-repo.outputs.parameters.pvc-name}}' + - name: sw-catalogs-volume + persistentVolumeClaim: + claimName: '{{steps.generate-sw-catalogs-volume-repo.outputs.parameters.pvc-name}}' + - name: secret-volume + secret: + secretName: "{{inputs.parameters.secret_name}}" + optional: true + + # === PHASE 7: GitOps Commit and Push === + # Commit and push the generated application manifests to the Fleet repository + # This completes the GitOps workflow by updating the target repository with changes + - - name: push-to-fleet + templateRef: + name: git-wft + template: git-commit-merge-push + arguments: + parameters: + - name: mount_path + value: "/fleet" + - name: repo_folder + value: "{{inputs.parameters.fleet_destination_folder}}" + - name: git_cred_secret + value: "{{inputs.parameters.git_fleet_cred_secret}}" + - name: git_volume_name + value: '{{steps.generate-fleet-volume-repo.outputs.parameters.pvc-name}}' + - name: commit_message + value: "Execute '{{inputs.parameters.command}}' for App '{{inputs.parameters.app_name}}' in {{inputs.parameters.profile_name}} profile ({{inputs.parameters.profile_type}}) @ {{inputs.parameters.project_name}} project [Volume-Based Workflow]" + - name: main_branch + value: main + - name: contrib_branch + value: osm_contrib + - name: dry_run + value: "{{inputs.parameters.dry_run}}" -- 2.25.1