-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp-model.yaml
More file actions
422 lines (378 loc) · 22.4 KB
/
app-model.yaml
File metadata and controls
422 lines (378 loc) · 22.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# Application Model Definition
# This file defines an example of an application template for the Portainer Industrial App Portal (PIAP)
# It includes metadata, deployment configurations, and runtime settings
# Catalog metadata - information about the catalog itself
metadata:
# Catalog version for tracking changes and compatibility
version: "1.0"
# Last updated timestamp
updated: "2025-07-18T10:30:00Z"
# Default configuration inherited by all applications
# These defaults can be overridden at the deployment level
# NOTE: Currently only Compose deployments inherit these defaults (Kubernetes not yet implemented)
defaults:
# Default source repository for deployment files and configurations
# When deployments don't specify their own git repository, they inherit these values
source:
# Default git repository containing deployment files and configurations
git: "github.com/your-org/edge-templates"
# Default git branch or tag to use when not specified in individual deployments
ref: "main"
apps:
node-red:
# Application metadata - describes the application for users browsing the catalog
metadata:
# Display name shown in the application catalog and across the Industrial App Portal
name: "Node-RED"
# Brief one-line description that appears in catalog listings
description: "Low-code programming for event-driven applications"
# Detailed overview explaining the application's purpose and capabilities
# This appears when inspecting a catalog entry
overview: "Node-RED is a powerful tool for building Internet of Things (IoT) applications with a focus on simplifying the creation of event-driven applications. It provides a browser-based flow editor that makes it easy to wire together flows using the wide range of nodes in the palette."
# Organization or entity that maintains this application
publisher: "OpenJS Foundation"
# Available application versions that can be deployed
# Users select from this list during deployment; the selected version is used
# to replace ((PIAP_IMAGE_VERSION)) placeholders in Compose files
# (See "PLACEHOLDER INTERPOLATION SYSTEM" in configuration.variables for details)
versions: ["3.1.14", "3.1.15", "4.0.9"]
# Application category for organizing the catalog (e.g., "databases", "monitoring", "industrial-automation")
category: "industrial-automation"
# URL to the application's icon/logo
icon: "https://cdn.example.com/icons/node-red.svg"
# Searchable tags to help users discover this application
tags: ["automation", "low-code", "mqtt"]
# URLs to application screenshots displayed in the catalog
# These help users understand the application's interface before deployment
screenshots:
- "https://cdn.example.com/screenshots/node-red-dashboard.png"
- "https://cdn.example.com/screenshots/node-red-flow.png"
# URL to official documentation or user guide
documentation: "https://docs.example.com/node-red"
# Application variants - different deployment configurations for the same application
# Each variant represents a different use case, environment, or configuration
# Variant labels should be unique within an application
variants:
# Production variant - optimized for production deployments
# When only one variant exists, it becomes the default and won't show variant selection in UI
- # REQUIRED: Human-readable label for this variant shown in the deployment UI
# This label is used to identify and select the variant
# Must be unique within this application's variants
label: "Production"
# OPTIONAL: Version requirement - single constraint using simple operators
# Supported operators: >=, >, =, <, <= (only ONE constraint per variant)
# This eliminates conflicting constraints and keeps parsing simple
# If omitted, the variant is compatible with all versions listed in metadata.versions
version_requirement: ">=3.1.15" # Requires version 3.1.15 or higher
# Deployment configuration - defines how the application is deployed
# Git properties are optional - when omitted, files are sourced from defaults.source
deployment:
# Docker Compose deployment option
# Inherits git/ref from defaults.source (github.com/your-org/edge-templates@main)
#
# HOW CONFIGURATION INJECTION WORKS:
# - PIAP fetches the docker-compose.yml from git at deployment time
# - Any ((PIAP_*)) placeholders are interpolated directly into the compose content
# (See "PLACEHOLDER INTERPOLATION SYSTEM" in configuration.variables for details)
# - Volume mounts for configuration.files are injected into the compose file
# - The modified compose is sent to Portainer as an Edge Stack
# - Environment variables are passed to the Edge Stack for variables NOT used as placeholders
# - Config files are delivered via Portainer Edge Config (folder-per-device structure)
compose:
# Path to the docker-compose.yml file relative to the source repository root
path: "apps/node-red/docker-compose.yml"
# Kubernetes deployment option
# NOTE: NOT YET IMPLEMENTED - Kubernetes support is planned for a future release
# When implemented, will inherit git/ref from defaults.source
kubernetes:
# Path to Kubernetes manifest file relative to the source repository root
path: "apps/node-red/kubernetes.yaml"
# Runtime configuration system for device-specific and location-specific settings
#
# OPTIONAL: This entire section can be omitted for simple applications that don't need
# any custom configuration. When omitted, the PIAP UI will skip the configuration wizard
# step entirely and proceed directly to deployment.
#
# EDGE CONFIG DELIVERY:
# Configuration files are delivered to devices via Portainer Edge Config using a
# folder-per-device structure. Each device receives its own interpolated config files
# based on its resolved variable values. This allows devices to share an Edge Stack
# even when they have different configuration values.
#
# KEY CONCEPTS:
# 1. Configuration Files (files): Define bind mount mappings for configuration files
# - Specifies WHERE files are stored on device (device_path)
# - Specifies WHERE files are mounted in container (container_path)
# - PIAP automatically handles file propagation, bind mounts, and volume management
# - Each file can have multiple template options for users to select from
#
# 2. Templates: Pre-defined configuration file options stored in the catalog repository
# - Defined inline within each file entry (scoped to that specific mount point)
# - Users select from these templates via dropdown in the PIAP UI
# - Templates can contain ((PIAP_*)) placeholders that are replaced with variable values
#
# 3. Variables: User-provided values collected during app installation
# - Used to replace ((PIAP_*)) placeholders in Compose files and template files
# - Can be used standalone (without files) for environment-only configuration
# - See "PLACEHOLDER INTERPOLATION SYSTEM" in the variables section for detailed behavior
configuration:
# Configuration files to be mounted into the container
# This is a list of file mount points, each with its own template options
# The order in this list determines the display order in the PIAP UI
files:
# First file mount: Application main configuration
- # User-friendly label shown in the PIAP UI for this configuration file
label: "Application Configuration"
# Path on the edge device where this config file will be stored
# PIAP manages this location and ensures the file exists before container starts
device_path: "/data/config.json"
# Path inside the container where this config file will be mounted
# PIAP automatically creates the bind mount: -v device_path:container_path
# If omitted, device_path will be used (e.g., -v /data/config.json:/data/config.json)
container_path: "/tmp/config.json"
# Template options for this specific configuration file
# This is a dictionary where each key is a template identifier
# Users will see these options in a dropdown in the PIAP UI
templates:
# Template identifier: used internally and as the value for "default" property
production:
# REQUIRED: Human-readable name displayed in the template selection dropdown
name: "Production Configuration"
# REQUIRED: Description shown in UI to help users choose the right template
# Should explain when to use this template and what it configures
description: "Production-ready Node-RED configuration with security and performance optimizations. Recommended for production deployments."
# REQUIRED: Path to the template file relative to the source repository root
# This file can contain ((PIAP_*)) placeholders that will be replaced with values from variables
path: "apps/node-red/prod/config.json"
# Alternative template for development environments
development:
name: "Development Configuration"
description: "Development configuration with debug logging enabled and relaxed security. Use for testing and development only."
path: "apps/node-red/dev/config.json"
# Minimal configuration template
minimal:
name: "Minimal Configuration"
description: "Minimal configuration with only essential settings. Good starting point for customization."
path: "apps/node-red/minimal/config.json"
# OPTIONAL: Specifies which template is pre-selected by default
# Must reference a valid key from the templates dictionary above
# If omitted when multiple templates exist, the FIRST template in YAML order is selected
# In this example, if "default" was omitted, "production" would be selected (first in list)
default: "production"
# OPTIONAL: When true, prevents users from changing the template selection in the UI
# Default: false (users can select from available templates)
#
# USE CASES FOR LOCKED CONFIGURATIONS:
# - Corporate security policies that must not be modified by operators
# - Compliance requirements (e.g., HIPAA, PCI-DSS) that mandate specific settings
# - Critical system configurations where user modification could break the application
# - Standardized configurations across multiple edge deployments
#
# UI BEHAVIOR:
# - When locked: true → UI shows "Using: [template name]" (read-only, no dropdown)
# - When locked: false or omitted → UI shows dropdown with all available templates
#
# FLEXIBILITY:
# - You can have locked: true with multiple templates defined
# - This allows you to "lock for now" but easily unlock later without schema changes
# - Useful when you want to enforce a specific config today but may allow selection in future
# - Only the "default" template is used when locked, but others remain available for future use
locked: false
# Second file mount: MQTT broker configuration
# This example shows a locked configuration with multiple templates for future flexibility
- label: "MQTT Broker Configuration"
device_path: "/data/mqtt.json"
container_path: "/tmp/mqtt.json"
templates:
production:
name: "Production MQTT Broker"
description: "Production MQTT broker connection settings with TLS and authentication"
path: "apps/node-red/prod/mqtt.json"
testing:
name: "Test MQTT Broker"
description: "Test environment MQTT broker (no TLS)"
path: "apps/node-red/test/mqtt.json"
default: "production"
# Locked to production for now, but testing template available for future use
locked: true
# Third file mount: Security policy (locked, single template)
# This demonstrates a truly locked configuration for security compliance
- label: "Security Policy"
device_path: "/data/security.json"
container_path: "/app/security.json"
templates:
corporate:
name: "Corporate Security Policy"
description: "Mandatory security policy enforced by corporate IT. Cannot be modified."
path: "apps/node-red/security/corporate.json"
# Only one template, locked to prevent any modification
# No "default" needed when only one template exists (automatically selected)
locked: true
# EDGE CASE: Mounting files that already exist on the device
#
# When the templates section is OMITTED entirely, PIAP will NOT provide any default file
# The file must already exist at device_path before the container starts
# PIAP will only create the bind mount, not manage the file content
#
# USE CASES:
# - Mounting certificates or keys placed by operators
# - Mounting files managed by other processes or tools
# - Mounting shared configuration files used by multiple applications
#
# LENIENT PARSING:
# An empty templates dict (templates: {}) is also accepted and treated identically
# to omitting the templates section entirely. However, omitting the section is
# the preferred/canonical syntax for clarity.
- label: "SSL Certificate"
device_path: "/data/certs/ssl.crt"
container_path: "/app/certs/ssl.crt"
# No templates section - file must already exist on device
- label: "SSH Private Key"
device_path: "/data/.ssh/id_rsa"
container_path: "/root/.ssh/id_rsa"
# File must be placed on device by operator or another process
# ============================================================================
# PLACEHOLDER INTERPOLATION SYSTEM
# ============================================================================
#
# PIAP uses ((PIAP_*)) placeholders to inject dynamic values at deployment time.
# Placeholders are processed in multiple contexts with specific behaviors.
#
# ----------------------------------------------------------------------------
# 1. COMPOSE FILE INTERPOLATION
# ----------------------------------------------------------------------------
# Any ((PIAP_*)) placeholder in docker-compose.yml files is interpolated
# at deployment time, BEFORE the container is started.
#
# SPECIAL PLACEHOLDER - ((PIAP_IMAGE_VERSION)):
# - Automatically available without defining a variable
# - Replaced with the user-selected version from metadata.versions
# - Commonly used in image tags: image: nodered/node-red:((PIAP_IMAGE_VERSION))
#
# USER-DEFINED PLACEHOLDERS in Compose files:
# - Any ((PIAP_VARIABLE_NAME)) placeholder in the Compose file is interpolated
# - The value comes from the matching variable in configuration.variables
# - Example: environment: - API_URL=((PIAP_API_URL))
#
# ----------------------------------------------------------------------------
# 2. CONFIGURATION TEMPLATE INTERPOLATION
# ----------------------------------------------------------------------------
# When configuration.files are defined with templates:
# - Template files can contain ((PIAP_VARIABLE_NAME)) placeholders
# - These are replaced with values from configuration.variables
# - The interpolated file is then written to device_path on the edge device
#
# ----------------------------------------------------------------------------
# 3. ENVIRONMENT VARIABLE INJECTION
# ----------------------------------------------------------------------------
# Environment variables are created based on the following logic:
#
# SCENARIO A - No configuration templates defined:
# - All variables are injected as environment variables
# - Variable "MQTT_BROKER" becomes env var MQTT_BROKER in the container
# - This is the PRIMARY use case for env-only configuration
#
# SCENARIO B - Configuration templates ARE defined:
# - If ((PIAP_VARIABLE_NAME)) placeholder IS FOUND in a template file:
# → Value is interpolated into the file
# → Environment variable is NOT created (no duplication)
# - If ((PIAP_VARIABLE_NAME)) placeholder is NOT FOUND in any template:
# → Environment variable IS created as a FALLBACK
# → This allows mixed config: some values in files, others as env vars
#
# SUMMARY - Environment variables act as:
# - PRIMARY source when no config templates use the variable
# - FALLBACK when templates exist but don't contain the placeholder
# - SKIPPED when the value was already interpolated into a config file
#
# ----------------------------------------------------------------------------
# VARIABLE NAMING CONVENTIONS
# ----------------------------------------------------------------------------
# - Variable names should use UPPER_SNAKE_CASE (e.g., MQTT_BROKER, API_KEY)
# - Placeholders use format: ((PIAP_VARIABLE_NAME))
# - Environment variables use the name directly: VARIABLE_NAME
#
# ============================================================================
variables:
- # REQUIRED: Variable identifier
# Used in placeholders as ((PIAP_MQTT_BROKER)) and as env var MQTT_BROKER
name: "MQTT_BROKER"
# REQUIRED: User-friendly label shown in the app installation form
label: "MQTT Broker Address"
# OPTIONAL: Default value pre-filled in the app installation form
# If omitted, the field will be empty and user must provide a value
default: "mqtt.example.com"
- name: "MQTT_PORT"
label: "MQTT Port"
default: "1883"
- name: "MQTT_USERNAME"
label: "MQTT Username"
default: "user"
# Example without default - user must provide value
- name: "MQTT_PASSWORD"
label: "MQTT Password"
# No default - field will be empty, requiring user input
# Testing variant - configured for development and testing environments
# This variant demonstrates simplified configuration with fewer options
- label: "Testing"
version_requirement: "<4.0.0" # Only v3.x series (3.1.14, 3.1.15)
deployment:
compose:
git: "github.com/node-red/node-red-docker"
ref: "main"
path: "docker-compose.yml"
# Simplified configuration with single template and environment variables
configuration:
files:
- label: "Development Configuration"
device_path: "/data/config.json"
container_path: "/tmp/config.json"
templates:
development:
name: "Development Config"
description: "Debug mode enabled with verbose logging"
path: "apps/node-red/test/config.json"
# Single template - no "default" needed (automatically selected)
variables:
- name: "DEBUG_MODE"
label: "Enable Debug Mode"
default: "true"
- name: "LOG_LEVEL"
label: "Log Level"
default: "debug"
# Legacy variant - minimal configuration example
- label: "Legacy (3.1.14 only)"
version_requirement: "=3.1.14"
deployment:
compose:
git: "github.com/node-red/node-red-docker"
ref: "legacy"
path: "docker-compose.yml"
# No configuration section - PIAP UI will skip configuration wizard step
# Use this for simple applications that require no custom configuration
# Example: Environment variables only (no configuration files)
- label: "Environment Variables Only"
version_requirement: ">=3.1.15"
deployment:
compose:
path: "apps/node-red/docker-compose.yml"
# Configuration with only variables (no files section)
# USE CASE: Applications that are configured entirely via environment variables
#
# IMPORTANT: Variables are injected as environment variables ONLY if they are not
# interpolated elsewhere. If the Compose file (docker-compose.yml) contains
# ((PIAP_VARIABLE_NAME)) placeholders for these variables, they will be interpolated
# there instead, and no environment variable will be created.
# To guarantee env var injection, ensure no ((PIAP_*)) placeholders exist for these
# variables in either the Compose file or any configuration template files.
configuration:
variables:
- name: "NODE_ENV"
label: "Node Environment"
default: "production"
- name: "LOG_LEVEL"
label: "Log Level"
default: "info"
- name: "API_KEY"
label: "API Key"
# No default - user must provide